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 template <typename OpT> 31 static LogicalResult verifySwitchOp(OpT op) { 32 // Verify that the number of case destinations matches the number of case 33 // values. 34 size_t numDests = op.cases().size(); 35 size_t numValues = op.caseValues().size(); 36 if (numDests != numValues) { 37 return op.emitOpError( 38 "expected number of cases to match the number of case " 39 "values, got ") 40 << numDests << " but expected " << numValues; 41 } 42 return success(); 43 } 44 45 //===----------------------------------------------------------------------===// 46 // pdl_interp::CreateOperationOp 47 //===----------------------------------------------------------------------===// 48 49 static ParseResult parseCreateOperationOpAttributes( 50 OpAsmParser &p, SmallVectorImpl<OpAsmParser::OperandType> &attrOperands, 51 ArrayAttr &attrNamesAttr) { 52 Builder &builder = p.getBuilder(); 53 SmallVector<Attribute, 4> attrNames; 54 if (succeeded(p.parseOptionalLBrace())) { 55 do { 56 StringAttr nameAttr; 57 OpAsmParser::OperandType operand; 58 if (p.parseAttribute(nameAttr) || p.parseEqual() || 59 p.parseOperand(operand)) 60 return failure(); 61 attrNames.push_back(nameAttr); 62 attrOperands.push_back(operand); 63 } while (succeeded(p.parseOptionalComma())); 64 if (p.parseRBrace()) 65 return failure(); 66 } 67 attrNamesAttr = builder.getArrayAttr(attrNames); 68 return success(); 69 } 70 71 static void printCreateOperationOpAttributes(OpAsmPrinter &p, 72 CreateOperationOp op, 73 OperandRange attrArgs, 74 ArrayAttr attrNames) { 75 if (attrNames.empty()) 76 return; 77 p << " {"; 78 interleaveComma(llvm::seq<int>(0, attrNames.size()), p, 79 [&](int i) { p << attrNames[i] << " = " << attrArgs[i]; }); 80 p << '}'; 81 } 82 83 //===----------------------------------------------------------------------===// 84 // pdl_interp::ForEachOp 85 //===----------------------------------------------------------------------===// 86 87 void ForEachOp::build(::mlir::OpBuilder &builder, ::mlir::OperationState &state, 88 Value range, Block *successor, bool initLoop) { 89 build(builder, state, range, successor); 90 if (initLoop) { 91 // Create the block and the loop variable. 92 // FIXME: Allow passing in a proper location for the loop variable. 93 auto rangeType = range.getType().cast<pdl::RangeType>(); 94 state.regions.front()->emplaceBlock(); 95 state.regions.front()->addArgument(rangeType.getElementType(), 96 state.location); 97 } 98 } 99 100 ParseResult ForEachOp::parse(OpAsmParser &parser, OperationState &result) { 101 // Parse the loop variable followed by type. 102 OpAsmParser::OperandType loopVariable; 103 Type loopVariableType; 104 if (parser.parseRegionArgument(loopVariable) || 105 parser.parseColonType(loopVariableType)) 106 return failure(); 107 108 // Parse the "in" keyword. 109 if (parser.parseKeyword("in", " after loop variable")) 110 return failure(); 111 112 // Parse the operand (value range). 113 OpAsmParser::OperandType operandInfo; 114 if (parser.parseOperand(operandInfo)) 115 return failure(); 116 117 // Resolve the operand. 118 Type rangeType = pdl::RangeType::get(loopVariableType); 119 if (parser.resolveOperand(operandInfo, rangeType, result.operands)) 120 return failure(); 121 122 // Parse the body region. 123 Region *body = result.addRegion(); 124 if (parser.parseRegion(*body, {loopVariable}, {loopVariableType})) 125 return failure(); 126 127 // Parse the attribute dictionary. 128 if (parser.parseOptionalAttrDict(result.attributes)) 129 return failure(); 130 131 // Parse the successor. 132 Block *successor; 133 if (parser.parseArrow() || parser.parseSuccessor(successor)) 134 return failure(); 135 result.addSuccessors(successor); 136 137 return success(); 138 } 139 140 void ForEachOp::print(OpAsmPrinter &p) { 141 BlockArgument arg = getLoopVariable(); 142 p << ' ' << arg << " : " << arg.getType() << " in " << values() << ' '; 143 p.printRegion(region(), /*printEntryBlockArgs=*/false); 144 p.printOptionalAttrDict((*this)->getAttrs()); 145 p << " -> "; 146 p.printSuccessor(successor()); 147 } 148 149 LogicalResult ForEachOp::verify() { 150 // Verify that the operation has exactly one argument. 151 if (region().getNumArguments() != 1) 152 return emitOpError("requires exactly one argument"); 153 154 // Verify that the loop variable and the operand (value range) 155 // have compatible types. 156 BlockArgument arg = getLoopVariable(); 157 Type rangeType = pdl::RangeType::get(arg.getType()); 158 if (rangeType != values().getType()) 159 return emitOpError("operand must be a range of loop variable type"); 160 161 return success(); 162 } 163 164 //===----------------------------------------------------------------------===// 165 // pdl_interp::GetValueTypeOp 166 //===----------------------------------------------------------------------===// 167 168 /// Given the result type of a `GetValueTypeOp`, return the expected input type. 169 static Type getGetValueTypeOpValueType(Type type) { 170 Type valueTy = pdl::ValueType::get(type.getContext()); 171 return type.isa<pdl::RangeType>() ? pdl::RangeType::get(valueTy) : valueTy; 172 } 173 174 //===----------------------------------------------------------------------===// 175 // pdl_interp::SwitchAttributeOp 176 //===----------------------------------------------------------------------===// 177 178 LogicalResult SwitchAttributeOp::verify() { return verifySwitchOp(*this); } 179 180 //===----------------------------------------------------------------------===// 181 // pdl_interp::SwitchOperandCountOp 182 //===----------------------------------------------------------------------===// 183 184 LogicalResult SwitchOperandCountOp::verify() { return verifySwitchOp(*this); } 185 186 //===----------------------------------------------------------------------===// 187 // pdl_interp::SwitchOperationNameOp 188 //===----------------------------------------------------------------------===// 189 190 LogicalResult SwitchOperationNameOp::verify() { return verifySwitchOp(*this); } 191 192 //===----------------------------------------------------------------------===// 193 // pdl_interp::SwitchResultCountOp 194 //===----------------------------------------------------------------------===// 195 196 LogicalResult SwitchResultCountOp::verify() { return verifySwitchOp(*this); } 197 198 //===----------------------------------------------------------------------===// 199 // pdl_interp::SwitchTypeOp 200 //===----------------------------------------------------------------------===// 201 202 LogicalResult SwitchTypeOp::verify() { return verifySwitchOp(*this); } 203 204 //===----------------------------------------------------------------------===// 205 // pdl_interp::SwitchTypesOp 206 //===----------------------------------------------------------------------===// 207 208 LogicalResult SwitchTypesOp::verify() { return verifySwitchOp(*this); } 209 210 //===----------------------------------------------------------------------===// 211 // TableGen Auto-Generated Op and Interface Definitions 212 //===----------------------------------------------------------------------===// 213 214 #define GET_OP_CLASSES 215 #include "mlir/Dialect/PDLInterp/IR/PDLInterpOps.cpp.inc" 216