1 //===- PDLInterp.cpp - PDL Interpreter Dialect ------------------*- C++ -*-===// 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/Dialect/PDLInterp/IR/PDLInterp.h" 10 #include "mlir/Dialect/PDL/IR/PDLTypes.h" 11 #include "mlir/IR/BuiltinTypes.h" 12 #include "mlir/IR/DialectImplementation.h" 13 14 using namespace mlir; 15 using namespace mlir::pdl_interp; 16 17 #include "mlir/Dialect/PDLInterp/IR/PDLInterpOpsDialect.cpp.inc" 18 19 //===----------------------------------------------------------------------===// 20 // PDLInterp Dialect 21 //===----------------------------------------------------------------------===// 22 23 void PDLInterpDialect::initialize() { 24 addOperations< 25 #define GET_OP_LIST 26 #include "mlir/Dialect/PDLInterp/IR/PDLInterpOps.cpp.inc" 27 >(); 28 } 29 30 //===----------------------------------------------------------------------===// 31 // pdl_interp::CreateOperationOp 32 //===----------------------------------------------------------------------===// 33 34 static ParseResult parseCreateOperationOpAttributes( 35 OpAsmParser &p, SmallVectorImpl<OpAsmParser::OperandType> &attrOperands, 36 ArrayAttr &attrNamesAttr) { 37 Builder &builder = p.getBuilder(); 38 SmallVector<Attribute, 4> attrNames; 39 if (succeeded(p.parseOptionalLBrace())) { 40 do { 41 StringAttr nameAttr; 42 OpAsmParser::OperandType operand; 43 if (p.parseAttribute(nameAttr) || p.parseEqual() || 44 p.parseOperand(operand)) 45 return failure(); 46 attrNames.push_back(nameAttr); 47 attrOperands.push_back(operand); 48 } while (succeeded(p.parseOptionalComma())); 49 if (p.parseRBrace()) 50 return failure(); 51 } 52 attrNamesAttr = builder.getArrayAttr(attrNames); 53 return success(); 54 } 55 56 static void printCreateOperationOpAttributes(OpAsmPrinter &p, 57 CreateOperationOp op, 58 OperandRange attrArgs, 59 ArrayAttr attrNames) { 60 if (attrNames.empty()) 61 return; 62 p << " {"; 63 interleaveComma(llvm::seq<int>(0, attrNames.size()), p, 64 [&](int i) { p << attrNames[i] << " = " << attrArgs[i]; }); 65 p << '}'; 66 } 67 68 //===----------------------------------------------------------------------===// 69 // pdl_interp::ForEachOp 70 //===----------------------------------------------------------------------===// 71 72 void ForEachOp::build(::mlir::OpBuilder &builder, ::mlir::OperationState &state, 73 Value range, Block *successor, bool initLoop) { 74 build(builder, state, range, successor); 75 if (initLoop) { 76 // Create the block and the loop variable. 77 // FIXME: Allow passing in a proper location for the loop variable. 78 auto rangeType = range.getType().cast<pdl::RangeType>(); 79 state.regions.front()->emplaceBlock(); 80 state.regions.front()->addArgument(rangeType.getElementType(), 81 state.location); 82 } 83 } 84 85 static ParseResult parseForEachOp(OpAsmParser &parser, OperationState &result) { 86 // Parse the loop variable followed by type. 87 OpAsmParser::OperandType loopVariable; 88 Type loopVariableType; 89 if (parser.parseRegionArgument(loopVariable) || 90 parser.parseColonType(loopVariableType)) 91 return failure(); 92 93 // Parse the "in" keyword. 94 if (parser.parseKeyword("in", " after loop variable")) 95 return failure(); 96 97 // Parse the operand (value range). 98 OpAsmParser::OperandType operandInfo; 99 if (parser.parseOperand(operandInfo)) 100 return failure(); 101 102 // Resolve the operand. 103 Type rangeType = pdl::RangeType::get(loopVariableType); 104 if (parser.resolveOperand(operandInfo, rangeType, result.operands)) 105 return failure(); 106 107 // Parse the body region. 108 Region *body = result.addRegion(); 109 if (parser.parseRegion(*body, {loopVariable}, {loopVariableType})) 110 return failure(); 111 112 // Parse the attribute dictionary. 113 if (parser.parseOptionalAttrDict(result.attributes)) 114 return failure(); 115 116 // Parse the successor. 117 Block *successor; 118 if (parser.parseArrow() || parser.parseSuccessor(successor)) 119 return failure(); 120 result.addSuccessors(successor); 121 122 return success(); 123 } 124 125 static void print(OpAsmPrinter &p, ForEachOp op) { 126 BlockArgument arg = op.getLoopVariable(); 127 p << ' ' << arg << " : " << arg.getType() << " in " << op.values() << ' '; 128 p.printRegion(op.region(), /*printEntryBlockArgs=*/false); 129 p.printOptionalAttrDict(op->getAttrs()); 130 p << " -> "; 131 p.printSuccessor(op.successor()); 132 } 133 134 static LogicalResult verify(ForEachOp op) { 135 // Verify that the operation has exactly one argument. 136 if (op.region().getNumArguments() != 1) 137 return op.emitOpError("requires exactly one argument"); 138 139 // Verify that the loop variable and the operand (value range) 140 // have compatible types. 141 BlockArgument arg = op.getLoopVariable(); 142 Type rangeType = pdl::RangeType::get(arg.getType()); 143 if (rangeType != op.values().getType()) 144 return op.emitOpError("operand must be a range of loop variable type"); 145 146 return success(); 147 } 148 149 //===----------------------------------------------------------------------===// 150 // pdl_interp::GetValueTypeOp 151 //===----------------------------------------------------------------------===// 152 153 /// Given the result type of a `GetValueTypeOp`, return the expected input type. 154 static Type getGetValueTypeOpValueType(Type type) { 155 Type valueTy = pdl::ValueType::get(type.getContext()); 156 return type.isa<pdl::RangeType>() ? pdl::RangeType::get(valueTy) : valueTy; 157 } 158 159 //===----------------------------------------------------------------------===// 160 // TableGen Auto-Generated Op and Interface Definitions 161 //===----------------------------------------------------------------------===// 162 163 #define GET_OP_CLASSES 164 #include "mlir/Dialect/PDLInterp/IR/PDLInterpOps.cpp.inc" 165