195b4e88bSRiver Riddle //===- MLIRGen.cpp --------------------------------------------------------===//
295b4e88bSRiver Riddle //
395b4e88bSRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
495b4e88bSRiver Riddle // See https://llvm.org/LICENSE.txt for license information.
595b4e88bSRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
695b4e88bSRiver Riddle //
795b4e88bSRiver Riddle //===----------------------------------------------------------------------===//
895b4e88bSRiver Riddle 
995b4e88bSRiver Riddle #include "mlir/Tools/PDLL/CodeGen/MLIRGen.h"
10*c60b897dSRiver Riddle #include "mlir/AsmParser/AsmParser.h"
1195b4e88bSRiver Riddle #include "mlir/Dialect/PDL/IR/PDL.h"
1295b4e88bSRiver Riddle #include "mlir/Dialect/PDL/IR/PDLOps.h"
1395b4e88bSRiver Riddle #include "mlir/Dialect/PDL/IR/PDLTypes.h"
1495b4e88bSRiver Riddle #include "mlir/IR/Builders.h"
1595b4e88bSRiver Riddle #include "mlir/IR/BuiltinOps.h"
1695b4e88bSRiver Riddle #include "mlir/IR/Verifier.h"
1795b4e88bSRiver Riddle #include "mlir/Tools/PDLL/AST/Context.h"
1895b4e88bSRiver Riddle #include "mlir/Tools/PDLL/AST/Nodes.h"
1995b4e88bSRiver Riddle #include "mlir/Tools/PDLL/AST/Types.h"
2081f2f4dfSRiver Riddle #include "mlir/Tools/PDLL/ODS/Context.h"
2181f2f4dfSRiver Riddle #include "mlir/Tools/PDLL/ODS/Operation.h"
2295b4e88bSRiver Riddle #include "llvm/ADT/ScopedHashTable.h"
2395b4e88bSRiver Riddle #include "llvm/ADT/StringExtras.h"
2495b4e88bSRiver Riddle #include "llvm/ADT/TypeSwitch.h"
2595b4e88bSRiver Riddle 
2695b4e88bSRiver Riddle using namespace mlir;
2795b4e88bSRiver Riddle using namespace mlir::pdll;
2895b4e88bSRiver Riddle 
2995b4e88bSRiver Riddle //===----------------------------------------------------------------------===//
3095b4e88bSRiver Riddle // CodeGen
3195b4e88bSRiver Riddle //===----------------------------------------------------------------------===//
3295b4e88bSRiver Riddle 
3395b4e88bSRiver Riddle namespace {
3495b4e88bSRiver Riddle class CodeGen {
3595b4e88bSRiver Riddle public:
CodeGen(MLIRContext * mlirContext,const ast::Context & context,const llvm::SourceMgr & sourceMgr)3695b4e88bSRiver Riddle   CodeGen(MLIRContext *mlirContext, const ast::Context &context,
3795b4e88bSRiver Riddle           const llvm::SourceMgr &sourceMgr)
3881f2f4dfSRiver Riddle       : builder(mlirContext), odsContext(context.getODSContext()),
3981f2f4dfSRiver Riddle         sourceMgr(sourceMgr) {
4095b4e88bSRiver Riddle     // Make sure that the PDL dialect is loaded.
4195b4e88bSRiver Riddle     mlirContext->loadDialect<pdl::PDLDialect>();
4295b4e88bSRiver Riddle   }
4395b4e88bSRiver Riddle 
4495b4e88bSRiver Riddle   OwningOpRef<ModuleOp> generate(const ast::Module &module);
4595b4e88bSRiver Riddle 
4695b4e88bSRiver Riddle private:
4795b4e88bSRiver Riddle   /// Generate an MLIR location from the given source location.
4895b4e88bSRiver Riddle   Location genLoc(llvm::SMLoc loc);
genLoc(llvm::SMRange loc)4995b4e88bSRiver Riddle   Location genLoc(llvm::SMRange loc) { return genLoc(loc.Start); }
5095b4e88bSRiver Riddle 
5195b4e88bSRiver Riddle   /// Generate an MLIR type from the given source type.
5295b4e88bSRiver Riddle   Type genType(ast::Type type);
5395b4e88bSRiver Riddle 
5495b4e88bSRiver Riddle   /// Generate MLIR for the given AST node.
5595b4e88bSRiver Riddle   void gen(const ast::Node *node);
5695b4e88bSRiver Riddle 
5795b4e88bSRiver Riddle   //===--------------------------------------------------------------------===//
5895b4e88bSRiver Riddle   // Statements
5995b4e88bSRiver Riddle   //===--------------------------------------------------------------------===//
6095b4e88bSRiver Riddle 
6195b4e88bSRiver Riddle   void genImpl(const ast::CompoundStmt *stmt);
6295b4e88bSRiver Riddle   void genImpl(const ast::EraseStmt *stmt);
6395b4e88bSRiver Riddle   void genImpl(const ast::LetStmt *stmt);
6495b4e88bSRiver Riddle   void genImpl(const ast::ReplaceStmt *stmt);
6595b4e88bSRiver Riddle   void genImpl(const ast::RewriteStmt *stmt);
6695b4e88bSRiver Riddle   void genImpl(const ast::ReturnStmt *stmt);
6795b4e88bSRiver Riddle 
6895b4e88bSRiver Riddle   //===--------------------------------------------------------------------===//
6995b4e88bSRiver Riddle   // Decls
7095b4e88bSRiver Riddle   //===--------------------------------------------------------------------===//
7195b4e88bSRiver Riddle 
7295b4e88bSRiver Riddle   void genImpl(const ast::UserConstraintDecl *decl);
7395b4e88bSRiver Riddle   void genImpl(const ast::UserRewriteDecl *decl);
7495b4e88bSRiver Riddle   void genImpl(const ast::PatternDecl *decl);
7595b4e88bSRiver Riddle 
7695b4e88bSRiver Riddle   /// Generate the set of MLIR values defined for the given variable decl, and
7795b4e88bSRiver Riddle   /// apply any attached constraints.
7895b4e88bSRiver Riddle   SmallVector<Value> genVar(const ast::VariableDecl *varDecl);
7995b4e88bSRiver Riddle 
8095b4e88bSRiver Riddle   /// Generate the value for a variable that does not have an initializer
8195b4e88bSRiver Riddle   /// expression, i.e. create the PDL value based on the type/constraints of the
8295b4e88bSRiver Riddle   /// variable.
8395b4e88bSRiver Riddle   Value genNonInitializerVar(const ast::VariableDecl *varDecl, Location loc);
8495b4e88bSRiver Riddle 
8595b4e88bSRiver Riddle   /// Apply the constraints of the given variable to `values`, which correspond
8695b4e88bSRiver Riddle   /// to the MLIR values of the variable.
8795b4e88bSRiver Riddle   void applyVarConstraints(const ast::VariableDecl *varDecl, ValueRange values);
8895b4e88bSRiver Riddle 
8995b4e88bSRiver Riddle   //===--------------------------------------------------------------------===//
9095b4e88bSRiver Riddle   // Expressions
9195b4e88bSRiver Riddle   //===--------------------------------------------------------------------===//
9295b4e88bSRiver Riddle 
9395b4e88bSRiver Riddle   Value genSingleExpr(const ast::Expr *expr);
9495b4e88bSRiver Riddle   SmallVector<Value> genExpr(const ast::Expr *expr);
9595b4e88bSRiver Riddle   Value genExprImpl(const ast::AttributeExpr *expr);
9695b4e88bSRiver Riddle   SmallVector<Value> genExprImpl(const ast::CallExpr *expr);
9795b4e88bSRiver Riddle   SmallVector<Value> genExprImpl(const ast::DeclRefExpr *expr);
9895b4e88bSRiver Riddle   Value genExprImpl(const ast::MemberAccessExpr *expr);
9995b4e88bSRiver Riddle   Value genExprImpl(const ast::OperationExpr *expr);
10095b4e88bSRiver Riddle   SmallVector<Value> genExprImpl(const ast::TupleExpr *expr);
10195b4e88bSRiver Riddle   Value genExprImpl(const ast::TypeExpr *expr);
10295b4e88bSRiver Riddle 
10395b4e88bSRiver Riddle   SmallVector<Value> genConstraintCall(const ast::UserConstraintDecl *decl,
10495b4e88bSRiver Riddle                                        Location loc, ValueRange inputs);
10595b4e88bSRiver Riddle   SmallVector<Value> genRewriteCall(const ast::UserRewriteDecl *decl,
10695b4e88bSRiver Riddle                                     Location loc, ValueRange inputs);
10795b4e88bSRiver Riddle   template <typename PDLOpT, typename T>
10895b4e88bSRiver Riddle   SmallVector<Value> genConstraintOrRewriteCall(const T *decl, Location loc,
10995b4e88bSRiver Riddle                                                 ValueRange inputs);
11095b4e88bSRiver Riddle 
11195b4e88bSRiver Riddle   //===--------------------------------------------------------------------===//
11295b4e88bSRiver Riddle   // Fields
11395b4e88bSRiver Riddle   //===--------------------------------------------------------------------===//
11495b4e88bSRiver Riddle 
11595b4e88bSRiver Riddle   /// The MLIR builder used for building the resultant IR.
11695b4e88bSRiver Riddle   OpBuilder builder;
11795b4e88bSRiver Riddle 
11895b4e88bSRiver Riddle   /// A map from variable declarations to the MLIR equivalent.
11995b4e88bSRiver Riddle   using VariableMapTy =
12095b4e88bSRiver Riddle       llvm::ScopedHashTable<const ast::VariableDecl *, SmallVector<Value>>;
12195b4e88bSRiver Riddle   VariableMapTy variables;
12295b4e88bSRiver Riddle 
12381f2f4dfSRiver Riddle   /// A reference to the ODS context.
12481f2f4dfSRiver Riddle   const ods::Context &odsContext;
12581f2f4dfSRiver Riddle 
12695b4e88bSRiver Riddle   /// The source manager of the PDLL ast.
12795b4e88bSRiver Riddle   const llvm::SourceMgr &sourceMgr;
12895b4e88bSRiver Riddle };
12995b4e88bSRiver Riddle } // namespace
13095b4e88bSRiver Riddle 
generate(const ast::Module & module)13195b4e88bSRiver Riddle OwningOpRef<ModuleOp> CodeGen::generate(const ast::Module &module) {
13295b4e88bSRiver Riddle   OwningOpRef<ModuleOp> mlirModule =
13395b4e88bSRiver Riddle       builder.create<ModuleOp>(genLoc(module.getLoc()));
13495b4e88bSRiver Riddle   builder.setInsertionPointToStart(mlirModule->getBody());
13595b4e88bSRiver Riddle 
13695b4e88bSRiver Riddle   // Generate code for each of the decls within the module.
13795b4e88bSRiver Riddle   for (const ast::Decl *decl : module.getChildren())
13895b4e88bSRiver Riddle     gen(decl);
13995b4e88bSRiver Riddle 
14095b4e88bSRiver Riddle   return mlirModule;
14195b4e88bSRiver Riddle }
14295b4e88bSRiver Riddle 
genLoc(llvm::SMLoc loc)14395b4e88bSRiver Riddle Location CodeGen::genLoc(llvm::SMLoc loc) {
14495b4e88bSRiver Riddle   unsigned fileID = sourceMgr.FindBufferContainingLoc(loc);
14595b4e88bSRiver Riddle 
14695b4e88bSRiver Riddle   // TODO: Fix performance issues in SourceMgr::getLineAndColumn so that we can
14795b4e88bSRiver Riddle   //       use it here.
14895b4e88bSRiver Riddle   auto &bufferInfo = sourceMgr.getBufferInfo(fileID);
14995b4e88bSRiver Riddle   unsigned lineNo = bufferInfo.getLineNumber(loc.getPointer());
15095b4e88bSRiver Riddle   unsigned column =
15195b4e88bSRiver Riddle       (loc.getPointer() - bufferInfo.getPointerForLineNumber(lineNo)) + 1;
15295b4e88bSRiver Riddle   auto *buffer = sourceMgr.getMemoryBuffer(fileID);
15395b4e88bSRiver Riddle 
15495b4e88bSRiver Riddle   return FileLineColLoc::get(builder.getContext(),
15595b4e88bSRiver Riddle                              buffer->getBufferIdentifier(), lineNo, column);
15695b4e88bSRiver Riddle }
15795b4e88bSRiver Riddle 
genType(ast::Type type)15895b4e88bSRiver Riddle Type CodeGen::genType(ast::Type type) {
15995b4e88bSRiver Riddle   return TypeSwitch<ast::Type, Type>(type)
16095b4e88bSRiver Riddle       .Case([&](ast::AttributeType astType) -> Type {
16195b4e88bSRiver Riddle         return builder.getType<pdl::AttributeType>();
16295b4e88bSRiver Riddle       })
16395b4e88bSRiver Riddle       .Case([&](ast::OperationType astType) -> Type {
16495b4e88bSRiver Riddle         return builder.getType<pdl::OperationType>();
16595b4e88bSRiver Riddle       })
16695b4e88bSRiver Riddle       .Case([&](ast::TypeType astType) -> Type {
16795b4e88bSRiver Riddle         return builder.getType<pdl::TypeType>();
16895b4e88bSRiver Riddle       })
16995b4e88bSRiver Riddle       .Case([&](ast::ValueType astType) -> Type {
17095b4e88bSRiver Riddle         return builder.getType<pdl::ValueType>();
17195b4e88bSRiver Riddle       })
17295b4e88bSRiver Riddle       .Case([&](ast::RangeType astType) -> Type {
17395b4e88bSRiver Riddle         return pdl::RangeType::get(genType(astType.getElementType()));
17495b4e88bSRiver Riddle       });
17595b4e88bSRiver Riddle }
17695b4e88bSRiver Riddle 
gen(const ast::Node * node)17795b4e88bSRiver Riddle void CodeGen::gen(const ast::Node *node) {
17895b4e88bSRiver Riddle   TypeSwitch<const ast::Node *>(node)
17995b4e88bSRiver Riddle       .Case<const ast::CompoundStmt, const ast::EraseStmt, const ast::LetStmt,
18095b4e88bSRiver Riddle             const ast::ReplaceStmt, const ast::RewriteStmt,
18195b4e88bSRiver Riddle             const ast::ReturnStmt, const ast::UserConstraintDecl,
18295b4e88bSRiver Riddle             const ast::UserRewriteDecl, const ast::PatternDecl>(
18395b4e88bSRiver Riddle           [&](auto derivedNode) { this->genImpl(derivedNode); })
18495b4e88bSRiver Riddle       .Case([&](const ast::Expr *expr) { genExpr(expr); });
18595b4e88bSRiver Riddle }
18695b4e88bSRiver Riddle 
18795b4e88bSRiver Riddle //===----------------------------------------------------------------------===//
18895b4e88bSRiver Riddle // CodeGen: Statements
18995b4e88bSRiver Riddle //===----------------------------------------------------------------------===//
19095b4e88bSRiver Riddle 
genImpl(const ast::CompoundStmt * stmt)19195b4e88bSRiver Riddle void CodeGen::genImpl(const ast::CompoundStmt *stmt) {
19295b4e88bSRiver Riddle   VariableMapTy::ScopeTy varScope(variables);
19395b4e88bSRiver Riddle   for (const ast::Stmt *childStmt : stmt->getChildren())
19495b4e88bSRiver Riddle     gen(childStmt);
19595b4e88bSRiver Riddle }
19695b4e88bSRiver Riddle 
19795b4e88bSRiver Riddle /// If the given builder is nested under a PDL PatternOp, build a rewrite
19895b4e88bSRiver Riddle /// operation and update the builder to nest under it. This is necessary for
19995b4e88bSRiver Riddle /// PDLL operation rewrite statements that are directly nested within a Pattern.
checkAndNestUnderRewriteOp(OpBuilder & builder,Value rootExpr,Location loc)20095b4e88bSRiver Riddle static void checkAndNestUnderRewriteOp(OpBuilder &builder, Value rootExpr,
20195b4e88bSRiver Riddle                                        Location loc) {
20295b4e88bSRiver Riddle   if (isa<pdl::PatternOp>(builder.getInsertionBlock()->getParentOp())) {
2039595f356SRiver Riddle     pdl::RewriteOp rewrite =
2049595f356SRiver Riddle         builder.create<pdl::RewriteOp>(loc, rootExpr, /*name=*/StringAttr(),
2059595f356SRiver Riddle                                        /*externalArgs=*/ValueRange());
20695b4e88bSRiver Riddle     builder.createBlock(&rewrite.body());
20795b4e88bSRiver Riddle   }
20895b4e88bSRiver Riddle }
20995b4e88bSRiver Riddle 
genImpl(const ast::EraseStmt * stmt)21095b4e88bSRiver Riddle void CodeGen::genImpl(const ast::EraseStmt *stmt) {
21195b4e88bSRiver Riddle   OpBuilder::InsertionGuard insertGuard(builder);
21295b4e88bSRiver Riddle   Value rootExpr = genSingleExpr(stmt->getRootOpExpr());
21395b4e88bSRiver Riddle   Location loc = genLoc(stmt->getLoc());
21495b4e88bSRiver Riddle 
21595b4e88bSRiver Riddle   // Make sure we are nested in a RewriteOp.
21695b4e88bSRiver Riddle   OpBuilder::InsertionGuard guard(builder);
21795b4e88bSRiver Riddle   checkAndNestUnderRewriteOp(builder, rootExpr, loc);
21895b4e88bSRiver Riddle   builder.create<pdl::EraseOp>(loc, rootExpr);
21995b4e88bSRiver Riddle }
22095b4e88bSRiver Riddle 
genImpl(const ast::LetStmt * stmt)22195b4e88bSRiver Riddle void CodeGen::genImpl(const ast::LetStmt *stmt) { genVar(stmt->getVarDecl()); }
22295b4e88bSRiver Riddle 
genImpl(const ast::ReplaceStmt * stmt)22395b4e88bSRiver Riddle void CodeGen::genImpl(const ast::ReplaceStmt *stmt) {
22495b4e88bSRiver Riddle   OpBuilder::InsertionGuard insertGuard(builder);
22595b4e88bSRiver Riddle   Value rootExpr = genSingleExpr(stmt->getRootOpExpr());
22695b4e88bSRiver Riddle   Location loc = genLoc(stmt->getLoc());
22795b4e88bSRiver Riddle 
22895b4e88bSRiver Riddle   // Make sure we are nested in a RewriteOp.
22995b4e88bSRiver Riddle   OpBuilder::InsertionGuard guard(builder);
23095b4e88bSRiver Riddle   checkAndNestUnderRewriteOp(builder, rootExpr, loc);
23195b4e88bSRiver Riddle 
23295b4e88bSRiver Riddle   SmallVector<Value> replValues;
23395b4e88bSRiver Riddle   for (ast::Expr *replExpr : stmt->getReplExprs())
23495b4e88bSRiver Riddle     replValues.push_back(genSingleExpr(replExpr));
23595b4e88bSRiver Riddle 
23695b4e88bSRiver Riddle   // Check to see if the statement has a replacement operation, or a range of
23795b4e88bSRiver Riddle   // replacement values.
23895b4e88bSRiver Riddle   bool usesReplOperation =
23995b4e88bSRiver Riddle       replValues.size() == 1 &&
24095b4e88bSRiver Riddle       replValues.front().getType().isa<pdl::OperationType>();
24195b4e88bSRiver Riddle   builder.create<pdl::ReplaceOp>(
24295b4e88bSRiver Riddle       loc, rootExpr, usesReplOperation ? replValues[0] : Value(),
24395b4e88bSRiver Riddle       usesReplOperation ? ValueRange() : ValueRange(replValues));
24495b4e88bSRiver Riddle }
24595b4e88bSRiver Riddle 
genImpl(const ast::RewriteStmt * stmt)24695b4e88bSRiver Riddle void CodeGen::genImpl(const ast::RewriteStmt *stmt) {
24795b4e88bSRiver Riddle   OpBuilder::InsertionGuard insertGuard(builder);
24895b4e88bSRiver Riddle   Value rootExpr = genSingleExpr(stmt->getRootOpExpr());
24995b4e88bSRiver Riddle 
25095b4e88bSRiver Riddle   // Make sure we are nested in a RewriteOp.
25195b4e88bSRiver Riddle   OpBuilder::InsertionGuard guard(builder);
25295b4e88bSRiver Riddle   checkAndNestUnderRewriteOp(builder, rootExpr, genLoc(stmt->getLoc()));
25395b4e88bSRiver Riddle   gen(stmt->getRewriteBody());
25495b4e88bSRiver Riddle }
25595b4e88bSRiver Riddle 
genImpl(const ast::ReturnStmt * stmt)25695b4e88bSRiver Riddle void CodeGen::genImpl(const ast::ReturnStmt *stmt) {
25795b4e88bSRiver Riddle   // ReturnStmt generation is handled by the respective constraint or rewrite
25895b4e88bSRiver Riddle   // parent node.
25995b4e88bSRiver Riddle }
26095b4e88bSRiver Riddle 
26195b4e88bSRiver Riddle //===----------------------------------------------------------------------===//
26295b4e88bSRiver Riddle // CodeGen: Decls
26395b4e88bSRiver Riddle //===----------------------------------------------------------------------===//
26495b4e88bSRiver Riddle 
genImpl(const ast::UserConstraintDecl * decl)26595b4e88bSRiver Riddle void CodeGen::genImpl(const ast::UserConstraintDecl *decl) {
26695b4e88bSRiver Riddle   // All PDLL constraints get inlined when called, and the main native
26795b4e88bSRiver Riddle   // constraint declarations doesn't require any MLIR to be generated, only uses
26895b4e88bSRiver Riddle   // of it do.
26995b4e88bSRiver Riddle }
27095b4e88bSRiver Riddle 
genImpl(const ast::UserRewriteDecl * decl)27195b4e88bSRiver Riddle void CodeGen::genImpl(const ast::UserRewriteDecl *decl) {
27295b4e88bSRiver Riddle   // All PDLL rewrites get inlined when called, and the main native
27395b4e88bSRiver Riddle   // rewrite declarations doesn't require any MLIR to be generated, only uses
27495b4e88bSRiver Riddle   // of it do.
27595b4e88bSRiver Riddle }
27695b4e88bSRiver Riddle 
genImpl(const ast::PatternDecl * decl)27795b4e88bSRiver Riddle void CodeGen::genImpl(const ast::PatternDecl *decl) {
27895b4e88bSRiver Riddle   const ast::Name *name = decl->getName();
27995b4e88bSRiver Riddle 
28095b4e88bSRiver Riddle   // FIXME: Properly model HasBoundedRecursion in PDL so that we don't drop it
28195b4e88bSRiver Riddle   // here.
28295b4e88bSRiver Riddle   pdl::PatternOp pattern = builder.create<pdl::PatternOp>(
28395b4e88bSRiver Riddle       genLoc(decl->getLoc()), decl->getBenefit(),
28495b4e88bSRiver Riddle       name ? Optional<StringRef>(name->getName()) : Optional<StringRef>());
28595b4e88bSRiver Riddle 
28695b4e88bSRiver Riddle   OpBuilder::InsertionGuard savedInsertPoint(builder);
28795b4e88bSRiver Riddle   builder.setInsertionPointToStart(pattern.getBody());
28895b4e88bSRiver Riddle   gen(decl->getBody());
28995b4e88bSRiver Riddle }
29095b4e88bSRiver Riddle 
genVar(const ast::VariableDecl * varDecl)29195b4e88bSRiver Riddle SmallVector<Value> CodeGen::genVar(const ast::VariableDecl *varDecl) {
29295b4e88bSRiver Riddle   auto it = variables.begin(varDecl);
29395b4e88bSRiver Riddle   if (it != variables.end())
29495b4e88bSRiver Riddle     return *it;
29595b4e88bSRiver Riddle 
29695b4e88bSRiver Riddle   // If the variable has an initial value, use that as the base value.
29795b4e88bSRiver Riddle   // Otherwise, generate a value using the constraint list.
29895b4e88bSRiver Riddle   SmallVector<Value> values;
29995b4e88bSRiver Riddle   if (const ast::Expr *initExpr = varDecl->getInitExpr())
30095b4e88bSRiver Riddle     values = genExpr(initExpr);
30195b4e88bSRiver Riddle   else
30295b4e88bSRiver Riddle     values.push_back(genNonInitializerVar(varDecl, genLoc(varDecl->getLoc())));
30395b4e88bSRiver Riddle 
30495b4e88bSRiver Riddle   // Apply the constraints of the values of the variable.
30595b4e88bSRiver Riddle   applyVarConstraints(varDecl, values);
30695b4e88bSRiver Riddle 
30795b4e88bSRiver Riddle   variables.insert(varDecl, values);
30895b4e88bSRiver Riddle   return values;
30995b4e88bSRiver Riddle }
31095b4e88bSRiver Riddle 
genNonInitializerVar(const ast::VariableDecl * varDecl,Location loc)31195b4e88bSRiver Riddle Value CodeGen::genNonInitializerVar(const ast::VariableDecl *varDecl,
31295b4e88bSRiver Riddle                                     Location loc) {
31395b4e88bSRiver Riddle   // A functor used to generate expressions nested
31495b4e88bSRiver Riddle   auto getTypeConstraint = [&]() -> Value {
31595b4e88bSRiver Riddle     for (const ast::ConstraintRef &constraint : varDecl->getConstraints()) {
31695b4e88bSRiver Riddle       Value typeValue =
31795b4e88bSRiver Riddle           TypeSwitch<const ast::Node *, Value>(constraint.constraint)
31895b4e88bSRiver Riddle               .Case<ast::AttrConstraintDecl, ast::ValueConstraintDecl,
3191c2edb02SRiver Riddle                     ast::ValueRangeConstraintDecl>(
3201c2edb02SRiver Riddle                   [&, this](auto *cst) -> Value {
32195b4e88bSRiver Riddle                     if (auto *typeConstraintExpr = cst->getTypeExpr())
32247ddf382SMehdi Amini                       return this->genSingleExpr(typeConstraintExpr);
32395b4e88bSRiver Riddle                     return Value();
32495b4e88bSRiver Riddle                   })
32595b4e88bSRiver Riddle               .Default(Value());
32695b4e88bSRiver Riddle       if (typeValue)
32795b4e88bSRiver Riddle         return typeValue;
32895b4e88bSRiver Riddle     }
32995b4e88bSRiver Riddle     return Value();
33095b4e88bSRiver Riddle   };
33195b4e88bSRiver Riddle 
33295b4e88bSRiver Riddle   // Generate a value based on the type of the variable.
33395b4e88bSRiver Riddle   ast::Type type = varDecl->getType();
33495b4e88bSRiver Riddle   Type mlirType = genType(type);
33595b4e88bSRiver Riddle   if (type.isa<ast::ValueType>())
33695b4e88bSRiver Riddle     return builder.create<pdl::OperandOp>(loc, mlirType, getTypeConstraint());
33795b4e88bSRiver Riddle   if (type.isa<ast::TypeType>())
33895b4e88bSRiver Riddle     return builder.create<pdl::TypeOp>(loc, mlirType, /*type=*/TypeAttr());
33995b4e88bSRiver Riddle   if (type.isa<ast::AttributeType>())
34095b4e88bSRiver Riddle     return builder.create<pdl::AttributeOp>(loc, getTypeConstraint());
34195b4e88bSRiver Riddle   if (ast::OperationType opType = type.dyn_cast<ast::OperationType>()) {
34295b4e88bSRiver Riddle     Value operands = builder.create<pdl::OperandsOp>(
34395b4e88bSRiver Riddle         loc, pdl::RangeType::get(builder.getType<pdl::ValueType>()),
34495b4e88bSRiver Riddle         /*type=*/Value());
34595b4e88bSRiver Riddle     Value results = builder.create<pdl::TypesOp>(
34695b4e88bSRiver Riddle         loc, pdl::RangeType::get(builder.getType<pdl::TypeType>()),
34795b4e88bSRiver Riddle         /*types=*/ArrayAttr());
34895b4e88bSRiver Riddle     return builder.create<pdl::OperationOp>(loc, opType.getName(), operands,
34995b4e88bSRiver Riddle                                             llvm::None, ValueRange(), results);
35095b4e88bSRiver Riddle   }
35195b4e88bSRiver Riddle 
35295b4e88bSRiver Riddle   if (ast::RangeType rangeTy = type.dyn_cast<ast::RangeType>()) {
35395b4e88bSRiver Riddle     ast::Type eleTy = rangeTy.getElementType();
35495b4e88bSRiver Riddle     if (eleTy.isa<ast::ValueType>())
35595b4e88bSRiver Riddle       return builder.create<pdl::OperandsOp>(loc, mlirType,
35695b4e88bSRiver Riddle                                              getTypeConstraint());
35795b4e88bSRiver Riddle     if (eleTy.isa<ast::TypeType>())
35895b4e88bSRiver Riddle       return builder.create<pdl::TypesOp>(loc, mlirType, /*types=*/ArrayAttr());
35995b4e88bSRiver Riddle   }
36095b4e88bSRiver Riddle 
36195b4e88bSRiver Riddle   llvm_unreachable("invalid non-initialized variable type");
36295b4e88bSRiver Riddle }
36395b4e88bSRiver Riddle 
applyVarConstraints(const ast::VariableDecl * varDecl,ValueRange values)36495b4e88bSRiver Riddle void CodeGen::applyVarConstraints(const ast::VariableDecl *varDecl,
36595b4e88bSRiver Riddle                                   ValueRange values) {
36695b4e88bSRiver Riddle   // Generate calls to any user constraints that were attached via the
36795b4e88bSRiver Riddle   // constraint list.
36895b4e88bSRiver Riddle   for (const ast::ConstraintRef &ref : varDecl->getConstraints())
36995b4e88bSRiver Riddle     if (const auto *userCst = dyn_cast<ast::UserConstraintDecl>(ref.constraint))
37095b4e88bSRiver Riddle       genConstraintCall(userCst, genLoc(ref.referenceLoc), values);
37195b4e88bSRiver Riddle }
37295b4e88bSRiver Riddle 
37395b4e88bSRiver Riddle //===----------------------------------------------------------------------===//
37495b4e88bSRiver Riddle // CodeGen: Expressions
37595b4e88bSRiver Riddle //===----------------------------------------------------------------------===//
37695b4e88bSRiver Riddle 
genSingleExpr(const ast::Expr * expr)37795b4e88bSRiver Riddle Value CodeGen::genSingleExpr(const ast::Expr *expr) {
37895b4e88bSRiver Riddle   return TypeSwitch<const ast::Expr *, Value>(expr)
37995b4e88bSRiver Riddle       .Case<const ast::AttributeExpr, const ast::MemberAccessExpr,
38095b4e88bSRiver Riddle             const ast::OperationExpr, const ast::TypeExpr>(
38195b4e88bSRiver Riddle           [&](auto derivedNode) { return this->genExprImpl(derivedNode); })
38295b4e88bSRiver Riddle       .Case<const ast::CallExpr, const ast::DeclRefExpr, const ast::TupleExpr>(
38395b4e88bSRiver Riddle           [&](auto derivedNode) {
38495b4e88bSRiver Riddle             SmallVector<Value> results = this->genExprImpl(derivedNode);
38595b4e88bSRiver Riddle             assert(results.size() == 1 && "expected single expression result");
38695b4e88bSRiver Riddle             return results[0];
38795b4e88bSRiver Riddle           });
38895b4e88bSRiver Riddle }
38995b4e88bSRiver Riddle 
genExpr(const ast::Expr * expr)39095b4e88bSRiver Riddle SmallVector<Value> CodeGen::genExpr(const ast::Expr *expr) {
39195b4e88bSRiver Riddle   return TypeSwitch<const ast::Expr *, SmallVector<Value>>(expr)
39295b4e88bSRiver Riddle       .Case<const ast::CallExpr, const ast::DeclRefExpr, const ast::TupleExpr>(
39395b4e88bSRiver Riddle           [&](auto derivedNode) { return this->genExprImpl(derivedNode); })
39495b4e88bSRiver Riddle       .Default([&](const ast::Expr *expr) -> SmallVector<Value> {
39595b4e88bSRiver Riddle         return {genSingleExpr(expr)};
39695b4e88bSRiver Riddle       });
39795b4e88bSRiver Riddle }
39895b4e88bSRiver Riddle 
genExprImpl(const ast::AttributeExpr * expr)39995b4e88bSRiver Riddle Value CodeGen::genExprImpl(const ast::AttributeExpr *expr) {
40095b4e88bSRiver Riddle   Attribute attr = parseAttribute(expr->getValue(), builder.getContext());
40195b4e88bSRiver Riddle   assert(attr && "invalid MLIR attribute data");
40295b4e88bSRiver Riddle   return builder.create<pdl::AttributeOp>(genLoc(expr->getLoc()), attr);
40395b4e88bSRiver Riddle }
40495b4e88bSRiver Riddle 
genExprImpl(const ast::CallExpr * expr)40595b4e88bSRiver Riddle SmallVector<Value> CodeGen::genExprImpl(const ast::CallExpr *expr) {
40695b4e88bSRiver Riddle   Location loc = genLoc(expr->getLoc());
40795b4e88bSRiver Riddle   SmallVector<Value> arguments;
40895b4e88bSRiver Riddle   for (const ast::Expr *arg : expr->getArguments())
40995b4e88bSRiver Riddle     arguments.push_back(genSingleExpr(arg));
41095b4e88bSRiver Riddle 
41195b4e88bSRiver Riddle   // Resolve the callable expression of this call.
41295b4e88bSRiver Riddle   auto *callableExpr = dyn_cast<ast::DeclRefExpr>(expr->getCallableExpr());
41395b4e88bSRiver Riddle   assert(callableExpr && "unhandled CallExpr callable");
41495b4e88bSRiver Riddle 
41595b4e88bSRiver Riddle   // Generate the PDL based on the type of callable.
41695b4e88bSRiver Riddle   const ast::Decl *callable = callableExpr->getDecl();
41795b4e88bSRiver Riddle   if (const auto *decl = dyn_cast<ast::UserConstraintDecl>(callable))
41895b4e88bSRiver Riddle     return genConstraintCall(decl, loc, arguments);
41995b4e88bSRiver Riddle   if (const auto *decl = dyn_cast<ast::UserRewriteDecl>(callable))
42095b4e88bSRiver Riddle     return genRewriteCall(decl, loc, arguments);
42195b4e88bSRiver Riddle   llvm_unreachable("unhandled CallExpr callable");
42295b4e88bSRiver Riddle }
42395b4e88bSRiver Riddle 
genExprImpl(const ast::DeclRefExpr * expr)42495b4e88bSRiver Riddle SmallVector<Value> CodeGen::genExprImpl(const ast::DeclRefExpr *expr) {
42595b4e88bSRiver Riddle   if (const auto *varDecl = dyn_cast<ast::VariableDecl>(expr->getDecl()))
42695b4e88bSRiver Riddle     return genVar(varDecl);
42795b4e88bSRiver Riddle   llvm_unreachable("unknown decl reference expression");
42895b4e88bSRiver Riddle }
42995b4e88bSRiver Riddle 
genExprImpl(const ast::MemberAccessExpr * expr)43095b4e88bSRiver Riddle Value CodeGen::genExprImpl(const ast::MemberAccessExpr *expr) {
43195b4e88bSRiver Riddle   Location loc = genLoc(expr->getLoc());
43295b4e88bSRiver Riddle   StringRef name = expr->getMemberName();
43395b4e88bSRiver Riddle   SmallVector<Value> parentExprs = genExpr(expr->getParentExpr());
43495b4e88bSRiver Riddle   ast::Type parentType = expr->getParentExpr()->getType();
43595b4e88bSRiver Riddle 
43695b4e88bSRiver Riddle   // Handle operation based member access.
43795b4e88bSRiver Riddle   if (ast::OperationType opType = parentType.dyn_cast<ast::OperationType>()) {
43895b4e88bSRiver Riddle     if (isa<ast::AllResultsMemberAccessExpr>(expr)) {
43995b4e88bSRiver Riddle       Type mlirType = genType(expr->getType());
44095b4e88bSRiver Riddle       if (mlirType.isa<pdl::ValueType>())
44195b4e88bSRiver Riddle         return builder.create<pdl::ResultOp>(loc, mlirType, parentExprs[0],
44295b4e88bSRiver Riddle                                              builder.getI32IntegerAttr(0));
44395b4e88bSRiver Riddle       return builder.create<pdl::ResultsOp>(loc, mlirType, parentExprs[0]);
44495b4e88bSRiver Riddle     }
44581f2f4dfSRiver Riddle 
4461c2edb02SRiver Riddle     const ods::Operation *odsOp = opType.getODSOperation();
447c088fbe7SChia-hung Duan     if (!odsOp) {
4481c2edb02SRiver Riddle       assert(llvm::isDigit(name[0]) &&
4491c2edb02SRiver Riddle              "unregistered op only allows numeric indexing");
450c088fbe7SChia-hung Duan       unsigned resultIndex;
451c088fbe7SChia-hung Duan       name.getAsInteger(/*Radix=*/10, resultIndex);
452c088fbe7SChia-hung Duan       IntegerAttr index = builder.getI32IntegerAttr(resultIndex);
453c088fbe7SChia-hung Duan       return builder.create<pdl::ResultOp>(loc, genType(expr->getType()),
454c088fbe7SChia-hung Duan                                            parentExprs[0], index);
455c088fbe7SChia-hung Duan     }
45681f2f4dfSRiver Riddle 
45781f2f4dfSRiver Riddle     // Find the result with the member name or by index.
45881f2f4dfSRiver Riddle     ArrayRef<ods::OperandOrResult> results = odsOp->getResults();
45981f2f4dfSRiver Riddle     unsigned resultIndex = results.size();
46081f2f4dfSRiver Riddle     if (llvm::isDigit(name[0])) {
46181f2f4dfSRiver Riddle       name.getAsInteger(/*Radix=*/10, resultIndex);
46281f2f4dfSRiver Riddle     } else {
46381f2f4dfSRiver Riddle       auto findFn = [&](const ods::OperandOrResult &result) {
46481f2f4dfSRiver Riddle         return result.getName() == name;
46581f2f4dfSRiver Riddle       };
46681f2f4dfSRiver Riddle       resultIndex = llvm::find_if(results, findFn) - results.begin();
46781f2f4dfSRiver Riddle     }
46881f2f4dfSRiver Riddle     assert(resultIndex < results.size() && "invalid result index");
46981f2f4dfSRiver Riddle 
47081f2f4dfSRiver Riddle     // Generate the result access.
47181f2f4dfSRiver Riddle     IntegerAttr index = builder.getI32IntegerAttr(resultIndex);
47281f2f4dfSRiver Riddle     return builder.create<pdl::ResultsOp>(loc, genType(expr->getType()),
47381f2f4dfSRiver Riddle                                           parentExprs[0], index);
47495b4e88bSRiver Riddle   }
47595b4e88bSRiver Riddle 
47695b4e88bSRiver Riddle   // Handle tuple based member access.
47795b4e88bSRiver Riddle   if (auto tupleType = parentType.dyn_cast<ast::TupleType>()) {
47895b4e88bSRiver Riddle     auto elementNames = tupleType.getElementNames();
47995b4e88bSRiver Riddle 
48095b4e88bSRiver Riddle     // The index is either a numeric index, or a name.
48195b4e88bSRiver Riddle     unsigned index = 0;
48295b4e88bSRiver Riddle     if (llvm::isDigit(name[0]))
48395b4e88bSRiver Riddle       name.getAsInteger(/*Radix=*/10, index);
48495b4e88bSRiver Riddle     else
48595b4e88bSRiver Riddle       index = llvm::find(elementNames, name) - elementNames.begin();
48695b4e88bSRiver Riddle 
48795b4e88bSRiver Riddle     assert(index < parentExprs.size() && "invalid result index");
48895b4e88bSRiver Riddle     return parentExprs[index];
48995b4e88bSRiver Riddle   }
49095b4e88bSRiver Riddle 
49195b4e88bSRiver Riddle   llvm_unreachable("unhandled member access expression");
49295b4e88bSRiver Riddle }
49395b4e88bSRiver Riddle 
genExprImpl(const ast::OperationExpr * expr)49495b4e88bSRiver Riddle Value CodeGen::genExprImpl(const ast::OperationExpr *expr) {
49595b4e88bSRiver Riddle   Location loc = genLoc(expr->getLoc());
49695b4e88bSRiver Riddle   Optional<StringRef> opName = expr->getName();
49795b4e88bSRiver Riddle 
49895b4e88bSRiver Riddle   // Operands.
49995b4e88bSRiver Riddle   SmallVector<Value> operands;
50095b4e88bSRiver Riddle   for (const ast::Expr *operand : expr->getOperands())
50195b4e88bSRiver Riddle     operands.push_back(genSingleExpr(operand));
50295b4e88bSRiver Riddle 
50395b4e88bSRiver Riddle   // Attributes.
50495b4e88bSRiver Riddle   SmallVector<StringRef> attrNames;
50595b4e88bSRiver Riddle   SmallVector<Value> attrValues;
50695b4e88bSRiver Riddle   for (const ast::NamedAttributeDecl *attr : expr->getAttributes()) {
50795b4e88bSRiver Riddle     attrNames.push_back(attr->getName().getName());
50895b4e88bSRiver Riddle     attrValues.push_back(genSingleExpr(attr->getValue()));
50995b4e88bSRiver Riddle   }
51095b4e88bSRiver Riddle 
51195b4e88bSRiver Riddle   // Results.
51295b4e88bSRiver Riddle   SmallVector<Value> results;
51395b4e88bSRiver Riddle   for (const ast::Expr *result : expr->getResultTypes())
51495b4e88bSRiver Riddle     results.push_back(genSingleExpr(result));
51595b4e88bSRiver Riddle 
51695b4e88bSRiver Riddle   return builder.create<pdl::OperationOp>(loc, opName, operands, attrNames,
51795b4e88bSRiver Riddle                                           attrValues, results);
51895b4e88bSRiver Riddle }
51995b4e88bSRiver Riddle 
genExprImpl(const ast::TupleExpr * expr)52095b4e88bSRiver Riddle SmallVector<Value> CodeGen::genExprImpl(const ast::TupleExpr *expr) {
52195b4e88bSRiver Riddle   SmallVector<Value> elements;
52295b4e88bSRiver Riddle   for (const ast::Expr *element : expr->getElements())
52395b4e88bSRiver Riddle     elements.push_back(genSingleExpr(element));
52495b4e88bSRiver Riddle   return elements;
52595b4e88bSRiver Riddle }
52695b4e88bSRiver Riddle 
genExprImpl(const ast::TypeExpr * expr)52795b4e88bSRiver Riddle Value CodeGen::genExprImpl(const ast::TypeExpr *expr) {
52895b4e88bSRiver Riddle   Type type = parseType(expr->getValue(), builder.getContext());
52995b4e88bSRiver Riddle   assert(type && "invalid MLIR type data");
53095b4e88bSRiver Riddle   return builder.create<pdl::TypeOp>(genLoc(expr->getLoc()),
53195b4e88bSRiver Riddle                                      builder.getType<pdl::TypeType>(),
53295b4e88bSRiver Riddle                                      TypeAttr::get(type));
53395b4e88bSRiver Riddle }
53495b4e88bSRiver Riddle 
53595b4e88bSRiver Riddle SmallVector<Value>
genConstraintCall(const ast::UserConstraintDecl * decl,Location loc,ValueRange inputs)53695b4e88bSRiver Riddle CodeGen::genConstraintCall(const ast::UserConstraintDecl *decl, Location loc,
53795b4e88bSRiver Riddle                            ValueRange inputs) {
53895b4e88bSRiver Riddle   // Apply any constraints defined on the arguments to the input values.
53995b4e88bSRiver Riddle   for (auto it : llvm::zip(decl->getInputs(), inputs))
54095b4e88bSRiver Riddle     applyVarConstraints(std::get<0>(it), std::get<1>(it));
54195b4e88bSRiver Riddle 
54295b4e88bSRiver Riddle   // Generate the constraint call.
54395b4e88bSRiver Riddle   SmallVector<Value> results =
54495b4e88bSRiver Riddle       genConstraintOrRewriteCall<pdl::ApplyNativeConstraintOp>(decl, loc,
54595b4e88bSRiver Riddle                                                                inputs);
54695b4e88bSRiver Riddle 
54795b4e88bSRiver Riddle   // Apply any constraints defined on the results of the constraint.
54895b4e88bSRiver Riddle   for (auto it : llvm::zip(decl->getResults(), results))
54995b4e88bSRiver Riddle     applyVarConstraints(std::get<0>(it), std::get<1>(it));
55095b4e88bSRiver Riddle   return results;
55195b4e88bSRiver Riddle }
55295b4e88bSRiver Riddle 
genRewriteCall(const ast::UserRewriteDecl * decl,Location loc,ValueRange inputs)55395b4e88bSRiver Riddle SmallVector<Value> CodeGen::genRewriteCall(const ast::UserRewriteDecl *decl,
55495b4e88bSRiver Riddle                                            Location loc, ValueRange inputs) {
55595b4e88bSRiver Riddle   return genConstraintOrRewriteCall<pdl::ApplyNativeRewriteOp>(decl, loc,
55695b4e88bSRiver Riddle                                                                inputs);
55795b4e88bSRiver Riddle }
55895b4e88bSRiver Riddle 
55995b4e88bSRiver Riddle template <typename PDLOpT, typename T>
genConstraintOrRewriteCall(const T * decl,Location loc,ValueRange inputs)56095b4e88bSRiver Riddle SmallVector<Value> CodeGen::genConstraintOrRewriteCall(const T *decl,
56195b4e88bSRiver Riddle                                                        Location loc,
56295b4e88bSRiver Riddle                                                        ValueRange inputs) {
56395b4e88bSRiver Riddle   const ast::CompoundStmt *cstBody = decl->getBody();
56495b4e88bSRiver Riddle 
56595b4e88bSRiver Riddle   // If the decl doesn't have a statement body, it is a native decl.
56695b4e88bSRiver Riddle   if (!cstBody) {
56795b4e88bSRiver Riddle     ast::Type declResultType = decl->getResultType();
56895b4e88bSRiver Riddle     SmallVector<Type> resultTypes;
56995b4e88bSRiver Riddle     if (ast::TupleType tupleType = declResultType.dyn_cast<ast::TupleType>()) {
57095b4e88bSRiver Riddle       for (ast::Type type : tupleType.getElementTypes())
57195b4e88bSRiver Riddle         resultTypes.push_back(genType(type));
57295b4e88bSRiver Riddle     } else {
57395b4e88bSRiver Riddle       resultTypes.push_back(genType(declResultType));
57495b4e88bSRiver Riddle     }
5759595f356SRiver Riddle     Operation *pdlOp = builder.create<PDLOpT>(
5769595f356SRiver Riddle         loc, resultTypes, decl->getName().getName(), inputs);
57795b4e88bSRiver Riddle     return pdlOp->getResults();
57895b4e88bSRiver Riddle   }
57995b4e88bSRiver Riddle 
58095b4e88bSRiver Riddle   // Otherwise, this is a PDLL decl.
58195b4e88bSRiver Riddle   VariableMapTy::ScopeTy varScope(variables);
58295b4e88bSRiver Riddle 
58395b4e88bSRiver Riddle   // Map the inputs of the call to the decl arguments.
58495b4e88bSRiver Riddle   // Note: This is only valid because we do not support recursion, meaning
58595b4e88bSRiver Riddle   // we don't need to worry about conflicting mappings here.
58695b4e88bSRiver Riddle   for (auto it : llvm::zip(inputs, decl->getInputs()))
58795b4e88bSRiver Riddle     variables.insert(std::get<1>(it), {std::get<0>(it)});
58895b4e88bSRiver Riddle 
58995b4e88bSRiver Riddle   // Visit the body of the call as normal.
59095b4e88bSRiver Riddle   gen(cstBody);
59195b4e88bSRiver Riddle 
59295b4e88bSRiver Riddle   // If the decl has no results, there is nothing to do.
59395b4e88bSRiver Riddle   if (cstBody->getChildren().empty())
59495b4e88bSRiver Riddle     return SmallVector<Value>();
59595b4e88bSRiver Riddle   auto *returnStmt = dyn_cast<ast::ReturnStmt>(cstBody->getChildren().back());
59695b4e88bSRiver Riddle   if (!returnStmt)
59795b4e88bSRiver Riddle     return SmallVector<Value>();
59895b4e88bSRiver Riddle 
59995b4e88bSRiver Riddle   // Otherwise, grab the results from the return statement.
60095b4e88bSRiver Riddle   return genExpr(returnStmt->getResultExpr());
60195b4e88bSRiver Riddle }
60295b4e88bSRiver Riddle 
60395b4e88bSRiver Riddle //===----------------------------------------------------------------------===//
60495b4e88bSRiver Riddle // MLIRGen
60595b4e88bSRiver Riddle //===----------------------------------------------------------------------===//
60695b4e88bSRiver Riddle 
codegenPDLLToMLIR(MLIRContext * mlirContext,const ast::Context & context,const llvm::SourceMgr & sourceMgr,const ast::Module & module)60795b4e88bSRiver Riddle OwningOpRef<ModuleOp> mlir::pdll::codegenPDLLToMLIR(
60895b4e88bSRiver Riddle     MLIRContext *mlirContext, const ast::Context &context,
60995b4e88bSRiver Riddle     const llvm::SourceMgr &sourceMgr, const ast::Module &module) {
61095b4e88bSRiver Riddle   CodeGen codegen(mlirContext, context, sourceMgr);
61195b4e88bSRiver Riddle   OwningOpRef<ModuleOp> mlirModule = codegen.generate(module);
61295b4e88bSRiver Riddle   if (failed(verify(*mlirModule)))
61395b4e88bSRiver Riddle     return nullptr;
61495b4e88bSRiver Riddle   return mlirModule;
61595b4e88bSRiver Riddle }
616