1 //===- EmitC.cpp - EmitC Dialect ------------------------------------------===// 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/EmitC/IR/EmitC.h" 10 #include "mlir/IR/Builders.h" 11 #include "mlir/IR/DialectImplementation.h" 12 #include "llvm/ADT/StringExtras.h" 13 #include "llvm/ADT/TypeSwitch.h" 14 15 using namespace mlir; 16 using namespace mlir::emitc; 17 18 #include "mlir/Dialect/EmitC/IR/EmitCDialect.cpp.inc" 19 20 //===----------------------------------------------------------------------===// 21 // EmitCDialect 22 //===----------------------------------------------------------------------===// 23 24 void EmitCDialect::initialize() { 25 addOperations< 26 #define GET_OP_LIST 27 #include "mlir/Dialect/EmitC/IR/EmitC.cpp.inc" 28 >(); 29 addTypes< 30 #define GET_TYPEDEF_LIST 31 #include "mlir/Dialect/EmitC/IR/EmitCTypes.cpp.inc" 32 >(); 33 addAttributes< 34 #define GET_ATTRDEF_LIST 35 #include "mlir/Dialect/EmitC/IR/EmitCAttributes.cpp.inc" 36 >(); 37 } 38 39 /// Materialize a single constant operation from a given attribute value with 40 /// the desired resultant type. 41 Operation *EmitCDialect::materializeConstant(OpBuilder &builder, 42 Attribute value, Type type, 43 Location loc) { 44 return builder.create<emitc::ConstantOp>(loc, type, value); 45 } 46 47 //===----------------------------------------------------------------------===// 48 // ApplyOp 49 //===----------------------------------------------------------------------===// 50 51 LogicalResult ApplyOp::verify() { 52 StringRef applicableOperatorStr = applicableOperator(); 53 54 // Applicable operator must not be empty. 55 if (applicableOperatorStr.empty()) 56 return emitOpError("applicable operator must not be empty"); 57 58 // Only `*` and `&` are supported. 59 if (applicableOperatorStr != "&" && applicableOperatorStr != "*") 60 return emitOpError("applicable operator is illegal"); 61 62 return success(); 63 } 64 65 //===----------------------------------------------------------------------===// 66 // CallOp 67 //===----------------------------------------------------------------------===// 68 69 LogicalResult emitc::CallOp::verify() { 70 // Callee must not be empty. 71 if (callee().empty()) 72 return emitOpError("callee must not be empty"); 73 74 if (Optional<ArrayAttr> argsAttr = args()) { 75 for (Attribute arg : argsAttr.getValue()) { 76 if (arg.getType().isa<IndexType>()) { 77 int64_t index = arg.cast<IntegerAttr>().getInt(); 78 // Args with elements of type index must be in range 79 // [0..operands.size). 80 if ((index < 0) || (index >= static_cast<int64_t>(getNumOperands()))) 81 return emitOpError("index argument is out of range"); 82 83 // Args with elements of type ArrayAttr must have a type. 84 } else if (arg.isa<ArrayAttr>() && arg.getType().isa<NoneType>()) { 85 return emitOpError("array argument has no type"); 86 } 87 } 88 } 89 90 if (Optional<ArrayAttr> templateArgsAttr = template_args()) { 91 for (Attribute tArg : templateArgsAttr.getValue()) { 92 if (!tArg.isa<TypeAttr>() && !tArg.isa<IntegerAttr>() && 93 !tArg.isa<FloatAttr>() && !tArg.isa<emitc::OpaqueAttr>()) 94 return emitOpError("template argument has invalid type"); 95 } 96 } 97 98 return success(); 99 } 100 101 //===----------------------------------------------------------------------===// 102 // ConstantOp 103 //===----------------------------------------------------------------------===// 104 105 /// The constant op requires that the attribute's type matches the return type. 106 LogicalResult emitc::ConstantOp::verify() { 107 Attribute value = valueAttr(); 108 Type type = getType(); 109 if (!value.getType().isa<NoneType>() && type != value.getType()) 110 return emitOpError() << "requires attribute's type (" << value.getType() 111 << ") to match op's return type (" << type << ")"; 112 return success(); 113 } 114 115 OpFoldResult emitc::ConstantOp::fold(ArrayRef<Attribute> operands) { 116 assert(operands.empty() && "constant has no operands"); 117 return value(); 118 } 119 120 //===----------------------------------------------------------------------===// 121 // IncludeOp 122 //===----------------------------------------------------------------------===// 123 124 void IncludeOp::print(OpAsmPrinter &p) { 125 bool standardInclude = is_standard_include(); 126 127 p << " "; 128 if (standardInclude) 129 p << "<"; 130 p << "\"" << include() << "\""; 131 if (standardInclude) 132 p << ">"; 133 } 134 135 ParseResult IncludeOp::parse(OpAsmParser &parser, OperationState &result) { 136 bool standardInclude = !parser.parseOptionalLess(); 137 138 StringAttr include; 139 OptionalParseResult includeParseResult = 140 parser.parseOptionalAttribute(include, "include", result.attributes); 141 if (!includeParseResult.hasValue()) 142 return parser.emitError(parser.getNameLoc()) << "expected string attribute"; 143 144 if (standardInclude && parser.parseOptionalGreater()) 145 return parser.emitError(parser.getNameLoc()) 146 << "expected trailing '>' for standard include"; 147 148 if (standardInclude) 149 result.addAttribute("is_standard_include", 150 UnitAttr::get(parser.getContext())); 151 152 return success(); 153 } 154 155 //===----------------------------------------------------------------------===// 156 // VariableOp 157 //===----------------------------------------------------------------------===// 158 159 /// The variable op requires that the attribute's type matches the return type. 160 LogicalResult emitc::VariableOp::verify() { 161 Attribute value = valueAttr(); 162 Type type = getType(); 163 if (!value.getType().isa<NoneType>() && type != value.getType()) 164 return emitOpError() << "requires attribute's type (" << value.getType() 165 << ") to match op's return type (" << type << ")"; 166 return success(); 167 } 168 169 //===----------------------------------------------------------------------===// 170 // TableGen'd op method definitions 171 //===----------------------------------------------------------------------===// 172 173 #define GET_OP_CLASSES 174 #include "mlir/Dialect/EmitC/IR/EmitC.cpp.inc" 175 176 //===----------------------------------------------------------------------===// 177 // EmitC Attributes 178 //===----------------------------------------------------------------------===// 179 180 #define GET_ATTRDEF_CLASSES 181 #include "mlir/Dialect/EmitC/IR/EmitCAttributes.cpp.inc" 182 183 Attribute emitc::OpaqueAttr::parse(AsmParser &parser, Type type) { 184 if (parser.parseLess()) 185 return Attribute(); 186 std::string value; 187 SMLoc loc = parser.getCurrentLocation(); 188 if (parser.parseOptionalString(&value)) { 189 parser.emitError(loc) << "expected string"; 190 return Attribute(); 191 } 192 if (parser.parseGreater()) 193 return Attribute(); 194 return get(parser.getContext(), value); 195 } 196 197 void emitc::OpaqueAttr::print(AsmPrinter &printer) const { 198 printer << "<\""; 199 llvm::printEscapedString(getValue(), printer.getStream()); 200 printer << "\">"; 201 } 202 203 //===----------------------------------------------------------------------===// 204 // EmitC Types 205 //===----------------------------------------------------------------------===// 206 207 #define GET_TYPEDEF_CLASSES 208 #include "mlir/Dialect/EmitC/IR/EmitCTypes.cpp.inc" 209 210 //===----------------------------------------------------------------------===// 211 // OpaqueType 212 //===----------------------------------------------------------------------===// 213 214 Type emitc::OpaqueType::parse(AsmParser &parser) { 215 if (parser.parseLess()) 216 return Type(); 217 std::string value; 218 SMLoc loc = parser.getCurrentLocation(); 219 if (parser.parseOptionalString(&value) || value.empty()) { 220 parser.emitError(loc) << "expected non empty string"; 221 return Type(); 222 } 223 if (parser.parseGreater()) 224 return Type(); 225 return get(parser.getContext(), value); 226 } 227 228 void emitc::OpaqueType::print(AsmPrinter &printer) const { 229 printer << "<\""; 230 llvm::printEscapedString(getValue(), printer.getStream()); 231 printer << "\">"; 232 } 233