1 | //===- ExtensibleDialect.cpp - Extensible dialect ---------------*- C++ -*-===// |
2 | // |
3 | // This file is licensed 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/IR/ExtensibleDialect.h" |
10 | #include "mlir/IR/AttributeSupport.h" |
11 | #include "mlir/IR/DialectImplementation.h" |
12 | #include "mlir/IR/OperationSupport.h" |
13 | #include "mlir/IR/StorageUniquerSupport.h" |
14 | #include "mlir/Support/LogicalResult.h" |
15 | |
16 | using namespace mlir; |
17 | |
18 | //===----------------------------------------------------------------------===// |
19 | // Dynamic types and attributes shared functions |
20 | //===----------------------------------------------------------------------===// |
21 | |
22 | /// Default parser for dynamic attribute or type parameters. |
23 | /// Parse in the format '(<>)?' or '<attr (,attr)*>'. |
24 | static LogicalResult |
25 | typeOrAttrParser(AsmParser &parser, SmallVectorImpl<Attribute> &parsedParams) { |
26 | // No parameters |
27 | if (parser.parseOptionalLess() || !parser.parseOptionalGreater()) |
28 | return success(); |
29 | |
30 | Attribute attr; |
31 | if (parser.parseAttribute(result&: attr)) |
32 | return failure(); |
33 | parsedParams.push_back(Elt: attr); |
34 | |
35 | while (parser.parseOptionalGreater()) { |
36 | Attribute attr; |
37 | if (parser.parseComma() || parser.parseAttribute(result&: attr)) |
38 | return failure(); |
39 | parsedParams.push_back(Elt: attr); |
40 | } |
41 | |
42 | return success(); |
43 | } |
44 | |
45 | /// Default printer for dynamic attribute or type parameters. |
46 | /// Print in the format '(<>)?' or '<attr (,attr)*>'. |
47 | static void typeOrAttrPrinter(AsmPrinter &printer, ArrayRef<Attribute> params) { |
48 | if (params.empty()) |
49 | return; |
50 | |
51 | printer << "<" ; |
52 | interleaveComma(c: params, os&: printer.getStream()); |
53 | printer << ">" ; |
54 | } |
55 | |
56 | //===----------------------------------------------------------------------===// |
57 | // Dynamic type |
58 | //===----------------------------------------------------------------------===// |
59 | |
60 | std::unique_ptr<DynamicTypeDefinition> |
61 | DynamicTypeDefinition::get(StringRef name, ExtensibleDialect *dialect, |
62 | VerifierFn &&verifier) { |
63 | return DynamicTypeDefinition::get(name, dialect, verifier: std::move(verifier), |
64 | parser: typeOrAttrParser, printer: typeOrAttrPrinter); |
65 | } |
66 | |
67 | std::unique_ptr<DynamicTypeDefinition> |
68 | DynamicTypeDefinition::get(StringRef name, ExtensibleDialect *dialect, |
69 | VerifierFn &&verifier, ParserFn &&parser, |
70 | PrinterFn &&printer) { |
71 | return std::unique_ptr<DynamicTypeDefinition>( |
72 | new DynamicTypeDefinition(name, dialect, std::move(verifier), |
73 | std::move(parser), std::move(printer))); |
74 | } |
75 | |
76 | DynamicTypeDefinition::DynamicTypeDefinition(StringRef nameRef, |
77 | ExtensibleDialect *dialect, |
78 | VerifierFn &&verifier, |
79 | ParserFn &&parser, |
80 | PrinterFn &&printer) |
81 | : name(nameRef), dialect(dialect), verifier(std::move(verifier)), |
82 | parser(std::move(parser)), printer(std::move(printer)), |
83 | ctx(dialect->getContext()) {} |
84 | |
85 | DynamicTypeDefinition::DynamicTypeDefinition(ExtensibleDialect *dialect, |
86 | StringRef nameRef) |
87 | : name(nameRef), dialect(dialect), ctx(dialect->getContext()) {} |
88 | |
89 | void DynamicTypeDefinition::registerInTypeUniquer() { |
90 | detail::TypeUniquer::registerType<DynamicType>(ctx: &getContext(), typeID: getTypeID()); |
91 | } |
92 | |
93 | namespace mlir { |
94 | namespace detail { |
95 | /// Storage of DynamicType. |
96 | /// Contains a pointer to the type definition and type parameters. |
97 | struct DynamicTypeStorage : public TypeStorage { |
98 | |
99 | using KeyTy = std::pair<DynamicTypeDefinition *, ArrayRef<Attribute>>; |
100 | |
101 | explicit DynamicTypeStorage(DynamicTypeDefinition *typeDef, |
102 | ArrayRef<Attribute> params) |
103 | : typeDef(typeDef), params(params) {} |
104 | |
105 | bool operator==(const KeyTy &key) const { |
106 | return typeDef == key.first && params == key.second; |
107 | } |
108 | |
109 | static llvm::hash_code hashKey(const KeyTy &key) { |
110 | return llvm::hash_value(arg: key); |
111 | } |
112 | |
113 | static DynamicTypeStorage *construct(TypeStorageAllocator &alloc, |
114 | const KeyTy &key) { |
115 | return new (alloc.allocate<DynamicTypeStorage>()) |
116 | DynamicTypeStorage(key.first, alloc.copyInto(elements: key.second)); |
117 | } |
118 | |
119 | /// Definition of the type. |
120 | DynamicTypeDefinition *typeDef; |
121 | |
122 | /// The type parameters. |
123 | ArrayRef<Attribute> params; |
124 | }; |
125 | } // namespace detail |
126 | } // namespace mlir |
127 | |
128 | DynamicType DynamicType::get(DynamicTypeDefinition *typeDef, |
129 | ArrayRef<Attribute> params) { |
130 | auto &ctx = typeDef->getContext(); |
131 | auto emitError = detail::getDefaultDiagnosticEmitFn(ctx: &ctx); |
132 | assert(succeeded(typeDef->verify(emitError, params))); |
133 | return detail::TypeUniquer::getWithTypeID<DynamicType>( |
134 | ctx: &ctx, typeID: typeDef->getTypeID(), args&: typeDef, args&: params); |
135 | } |
136 | |
137 | DynamicType |
138 | DynamicType::getChecked(function_ref<InFlightDiagnostic()> emitError, |
139 | DynamicTypeDefinition *typeDef, |
140 | ArrayRef<Attribute> params) { |
141 | if (failed(result: typeDef->verify(emitError, params))) |
142 | return {}; |
143 | auto &ctx = typeDef->getContext(); |
144 | return detail::TypeUniquer::getWithTypeID<DynamicType>( |
145 | ctx: &ctx, typeID: typeDef->getTypeID(), args&: typeDef, args&: params); |
146 | } |
147 | |
148 | DynamicTypeDefinition *DynamicType::getTypeDef() { return getImpl()->typeDef; } |
149 | |
150 | ArrayRef<Attribute> DynamicType::getParams() { return getImpl()->params; } |
151 | |
152 | bool DynamicType::classof(Type type) { |
153 | return type.hasTrait<TypeTrait::IsDynamicType>(); |
154 | } |
155 | |
156 | ParseResult DynamicType::parse(AsmParser &parser, |
157 | DynamicTypeDefinition *typeDef, |
158 | DynamicType &parsedType) { |
159 | SmallVector<Attribute> params; |
160 | if (failed(result: typeDef->parser(parser, params))) |
161 | return failure(); |
162 | parsedType = parser.getChecked<DynamicType>(params&: typeDef, params); |
163 | if (!parsedType) |
164 | return failure(); |
165 | return success(); |
166 | } |
167 | |
168 | void DynamicType::print(AsmPrinter &printer) { |
169 | printer << getTypeDef()->getName(); |
170 | getTypeDef()->printer(printer, getParams()); |
171 | } |
172 | |
173 | //===----------------------------------------------------------------------===// |
174 | // Dynamic attribute |
175 | //===----------------------------------------------------------------------===// |
176 | |
177 | std::unique_ptr<DynamicAttrDefinition> |
178 | DynamicAttrDefinition::get(StringRef name, ExtensibleDialect *dialect, |
179 | VerifierFn &&verifier) { |
180 | return DynamicAttrDefinition::get(name, dialect, verifier: std::move(verifier), |
181 | parser: typeOrAttrParser, printer: typeOrAttrPrinter); |
182 | } |
183 | |
184 | std::unique_ptr<DynamicAttrDefinition> |
185 | DynamicAttrDefinition::get(StringRef name, ExtensibleDialect *dialect, |
186 | VerifierFn &&verifier, ParserFn &&parser, |
187 | PrinterFn &&printer) { |
188 | return std::unique_ptr<DynamicAttrDefinition>( |
189 | new DynamicAttrDefinition(name, dialect, std::move(verifier), |
190 | std::move(parser), std::move(printer))); |
191 | } |
192 | |
193 | DynamicAttrDefinition::DynamicAttrDefinition(StringRef nameRef, |
194 | ExtensibleDialect *dialect, |
195 | VerifierFn &&verifier, |
196 | ParserFn &&parser, |
197 | PrinterFn &&printer) |
198 | : name(nameRef), dialect(dialect), verifier(std::move(verifier)), |
199 | parser(std::move(parser)), printer(std::move(printer)), |
200 | ctx(dialect->getContext()) {} |
201 | |
202 | DynamicAttrDefinition::DynamicAttrDefinition(ExtensibleDialect *dialect, |
203 | StringRef nameRef) |
204 | : name(nameRef), dialect(dialect), ctx(dialect->getContext()) {} |
205 | |
206 | void DynamicAttrDefinition::registerInAttrUniquer() { |
207 | detail::AttributeUniquer::registerAttribute<DynamicAttr>(ctx: &getContext(), |
208 | typeID: getTypeID()); |
209 | } |
210 | |
211 | namespace mlir { |
212 | namespace detail { |
213 | /// Storage of DynamicAttr. |
214 | /// Contains a pointer to the attribute definition and attribute parameters. |
215 | struct DynamicAttrStorage : public AttributeStorage { |
216 | using KeyTy = std::pair<DynamicAttrDefinition *, ArrayRef<Attribute>>; |
217 | |
218 | explicit DynamicAttrStorage(DynamicAttrDefinition *attrDef, |
219 | ArrayRef<Attribute> params) |
220 | : attrDef(attrDef), params(params) {} |
221 | |
222 | bool operator==(const KeyTy &key) const { |
223 | return attrDef == key.first && params == key.second; |
224 | } |
225 | |
226 | static llvm::hash_code hashKey(const KeyTy &key) { |
227 | return llvm::hash_value(arg: key); |
228 | } |
229 | |
230 | static DynamicAttrStorage *construct(AttributeStorageAllocator &alloc, |
231 | const KeyTy &key) { |
232 | return new (alloc.allocate<DynamicAttrStorage>()) |
233 | DynamicAttrStorage(key.first, alloc.copyInto(elements: key.second)); |
234 | } |
235 | |
236 | /// Definition of the type. |
237 | DynamicAttrDefinition *attrDef; |
238 | |
239 | /// The type parameters. |
240 | ArrayRef<Attribute> params; |
241 | }; |
242 | } // namespace detail |
243 | } // namespace mlir |
244 | |
245 | DynamicAttr DynamicAttr::get(DynamicAttrDefinition *attrDef, |
246 | ArrayRef<Attribute> params) { |
247 | auto &ctx = attrDef->getContext(); |
248 | return detail::AttributeUniquer::getWithTypeID<DynamicAttr>( |
249 | ctx: &ctx, typeID: attrDef->getTypeID(), args&: attrDef, args&: params); |
250 | } |
251 | |
252 | DynamicAttr |
253 | DynamicAttr::getChecked(function_ref<InFlightDiagnostic()> emitError, |
254 | DynamicAttrDefinition *attrDef, |
255 | ArrayRef<Attribute> params) { |
256 | if (failed(result: attrDef->verify(emitError, params))) |
257 | return {}; |
258 | return get(attrDef, params); |
259 | } |
260 | |
261 | DynamicAttrDefinition *DynamicAttr::getAttrDef() { return getImpl()->attrDef; } |
262 | |
263 | ArrayRef<Attribute> DynamicAttr::getParams() { return getImpl()->params; } |
264 | |
265 | bool DynamicAttr::classof(Attribute attr) { |
266 | return attr.hasTrait<AttributeTrait::IsDynamicAttr>(); |
267 | } |
268 | |
269 | ParseResult DynamicAttr::parse(AsmParser &parser, |
270 | DynamicAttrDefinition *attrDef, |
271 | DynamicAttr &parsedAttr) { |
272 | SmallVector<Attribute> params; |
273 | if (failed(result: attrDef->parser(parser, params))) |
274 | return failure(); |
275 | parsedAttr = parser.getChecked<DynamicAttr>(params&: attrDef, params); |
276 | if (!parsedAttr) |
277 | return failure(); |
278 | return success(); |
279 | } |
280 | |
281 | void DynamicAttr::print(AsmPrinter &printer) { |
282 | printer << getAttrDef()->getName(); |
283 | getAttrDef()->printer(printer, getParams()); |
284 | } |
285 | |
286 | //===----------------------------------------------------------------------===// |
287 | // Dynamic operation |
288 | //===----------------------------------------------------------------------===// |
289 | |
290 | DynamicOpDefinition::DynamicOpDefinition( |
291 | StringRef name, ExtensibleDialect *dialect, |
292 | OperationName::VerifyInvariantsFn &&verifyFn, |
293 | OperationName::VerifyRegionInvariantsFn &&verifyRegionFn, |
294 | OperationName::ParseAssemblyFn &&parseFn, |
295 | OperationName::PrintAssemblyFn &&printFn, |
296 | OperationName::FoldHookFn &&foldHookFn, |
297 | GetCanonicalizationPatternsFn &&getCanonicalizationPatternsFn, |
298 | OperationName::PopulateDefaultAttrsFn &&populateDefaultAttrsFn) |
299 | : Impl(StringAttr::get(dialect->getContext(), |
300 | (dialect->getNamespace() + "." + name).str()), |
301 | dialect, dialect->allocateTypeID(), |
302 | /*interfaceMap=*/detail::InterfaceMap()), |
303 | verifyFn(std::move(verifyFn)), verifyRegionFn(std::move(verifyRegionFn)), |
304 | parseFn(std::move(parseFn)), printFn(std::move(printFn)), |
305 | foldHookFn(std::move(foldHookFn)), |
306 | getCanonicalizationPatternsFn(std::move(getCanonicalizationPatternsFn)), |
307 | populateDefaultAttrsFn(std::move(populateDefaultAttrsFn)) { |
308 | typeID = dialect->allocateTypeID(); |
309 | } |
310 | |
311 | std::unique_ptr<DynamicOpDefinition> DynamicOpDefinition::get( |
312 | StringRef name, ExtensibleDialect *dialect, |
313 | OperationName::VerifyInvariantsFn &&verifyFn, |
314 | OperationName::VerifyRegionInvariantsFn &&verifyRegionFn) { |
315 | auto parseFn = [](OpAsmParser &parser, OperationState &result) { |
316 | return parser.emitError( |
317 | loc: parser.getCurrentLocation(), |
318 | message: "dynamic operation do not define any parser function" ); |
319 | }; |
320 | |
321 | auto printFn = [](Operation *op, OpAsmPrinter &printer, StringRef) { |
322 | printer.printGenericOp(op); |
323 | }; |
324 | |
325 | return DynamicOpDefinition::get(name, dialect, verifyFn: std::move(verifyFn), |
326 | verifyRegionFn: std::move(verifyRegionFn), parseFn: std::move(parseFn), |
327 | printFn: std::move(printFn)); |
328 | } |
329 | |
330 | std::unique_ptr<DynamicOpDefinition> DynamicOpDefinition::get( |
331 | StringRef name, ExtensibleDialect *dialect, |
332 | OperationName::VerifyInvariantsFn &&verifyFn, |
333 | OperationName::VerifyRegionInvariantsFn &&verifyRegionFn, |
334 | OperationName::ParseAssemblyFn &&parseFn, |
335 | OperationName::PrintAssemblyFn &&printFn) { |
336 | auto foldHookFn = [](Operation *op, ArrayRef<Attribute> operands, |
337 | SmallVectorImpl<OpFoldResult> &results) { |
338 | return failure(); |
339 | }; |
340 | |
341 | auto getCanonicalizationPatternsFn = [](RewritePatternSet &, MLIRContext *) { |
342 | }; |
343 | |
344 | auto populateDefaultAttrsFn = [](const OperationName &, NamedAttrList &) {}; |
345 | |
346 | return DynamicOpDefinition::get(name, dialect, verifyFn: std::move(verifyFn), |
347 | verifyRegionFn: std::move(verifyRegionFn), parseFn: std::move(parseFn), |
348 | printFn: std::move(printFn), foldHookFn: std::move(foldHookFn), |
349 | getCanonicalizationPatternsFn: std::move(getCanonicalizationPatternsFn), |
350 | populateDefaultAttrsFn: std::move(populateDefaultAttrsFn)); |
351 | } |
352 | |
353 | std::unique_ptr<DynamicOpDefinition> DynamicOpDefinition::get( |
354 | StringRef name, ExtensibleDialect *dialect, |
355 | OperationName::VerifyInvariantsFn &&verifyFn, |
356 | OperationName::VerifyInvariantsFn &&verifyRegionFn, |
357 | OperationName::ParseAssemblyFn &&parseFn, |
358 | OperationName::PrintAssemblyFn &&printFn, |
359 | OperationName::FoldHookFn &&foldHookFn, |
360 | GetCanonicalizationPatternsFn &&getCanonicalizationPatternsFn, |
361 | OperationName::PopulateDefaultAttrsFn &&populateDefaultAttrsFn) { |
362 | return std::unique_ptr<DynamicOpDefinition>(new DynamicOpDefinition( |
363 | name, dialect, std::move(verifyFn), std::move(verifyRegionFn), |
364 | std::move(parseFn), std::move(printFn), std::move(foldHookFn), |
365 | std::move(getCanonicalizationPatternsFn), |
366 | std::move(populateDefaultAttrsFn))); |
367 | } |
368 | |
369 | //===----------------------------------------------------------------------===// |
370 | // Extensible dialect |
371 | //===----------------------------------------------------------------------===// |
372 | |
373 | namespace { |
374 | /// Interface that can only be implemented by extensible dialects. |
375 | /// The interface is used to check if a dialect is extensible or not. |
376 | class IsExtensibleDialect : public DialectInterface::Base<IsExtensibleDialect> { |
377 | public: |
378 | IsExtensibleDialect(Dialect *dialect) : Base(dialect) {} |
379 | |
380 | MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(IsExtensibleDialect) |
381 | }; |
382 | } // namespace |
383 | |
384 | ExtensibleDialect::ExtensibleDialect(StringRef name, MLIRContext *ctx, |
385 | TypeID typeID) |
386 | : Dialect(name, ctx, typeID) { |
387 | addInterfaces<IsExtensibleDialect>(); |
388 | } |
389 | |
390 | void ExtensibleDialect::registerDynamicType( |
391 | std::unique_ptr<DynamicTypeDefinition> &&type) { |
392 | DynamicTypeDefinition *typePtr = type.get(); |
393 | TypeID typeID = type->getTypeID(); |
394 | StringRef name = type->getName(); |
395 | ExtensibleDialect *dialect = type->getDialect(); |
396 | |
397 | assert(dialect == this && |
398 | "trying to register a dynamic type in the wrong dialect" ); |
399 | |
400 | // If a type with the same name is already defined, fail. |
401 | auto registered = dynTypes.try_emplace(Key: typeID, Args: std::move(type)).second; |
402 | (void)registered; |
403 | assert(registered && "type TypeID was not unique" ); |
404 | |
405 | registered = nameToDynTypes.insert(KV: {name, typePtr}).second; |
406 | (void)registered; |
407 | assert(registered && |
408 | "Trying to create a new dynamic type with an existing name" ); |
409 | |
410 | // The StringAttr allocates the type name StringRef for the duration of the |
411 | // MLIR context. |
412 | MLIRContext *ctx = getContext(); |
413 | auto nameAttr = |
414 | StringAttr::get(ctx, getNamespace() + "." + typePtr->getName()); |
415 | |
416 | auto abstractType = AbstractType::get( |
417 | *dialect, DynamicAttr::getInterfaceMap(), DynamicType::getHasTraitFn(), |
418 | DynamicType::getWalkImmediateSubElementsFn(), |
419 | DynamicType::getReplaceImmediateSubElementsFn(), typeID, nameAttr); |
420 | |
421 | /// Add the type to the dialect and the type uniquer. |
422 | addType(typeID, std::move(abstractType)); |
423 | typePtr->registerInTypeUniquer(); |
424 | } |
425 | |
426 | void ExtensibleDialect::registerDynamicAttr( |
427 | std::unique_ptr<DynamicAttrDefinition> &&attr) { |
428 | auto *attrPtr = attr.get(); |
429 | auto typeID = attr->getTypeID(); |
430 | auto name = attr->getName(); |
431 | auto *dialect = attr->getDialect(); |
432 | |
433 | assert(dialect == this && |
434 | "trying to register a dynamic attribute in the wrong dialect" ); |
435 | |
436 | // If an attribute with the same name is already defined, fail. |
437 | auto registered = dynAttrs.try_emplace(Key: typeID, Args: std::move(attr)).second; |
438 | (void)registered; |
439 | assert(registered && "attribute TypeID was not unique" ); |
440 | |
441 | registered = nameToDynAttrs.insert(KV: {name, attrPtr}).second; |
442 | (void)registered; |
443 | assert(registered && |
444 | "Trying to create a new dynamic attribute with an existing name" ); |
445 | |
446 | // The StringAttr allocates the attribute name StringRef for the duration of |
447 | // the MLIR context. |
448 | MLIRContext *ctx = getContext(); |
449 | auto nameAttr = |
450 | StringAttr::get(ctx, getNamespace() + "." + attrPtr->getName()); |
451 | |
452 | auto abstractAttr = AbstractAttribute::get( |
453 | *dialect, DynamicAttr::getInterfaceMap(), DynamicAttr::getHasTraitFn(), |
454 | DynamicAttr::getWalkImmediateSubElementsFn(), |
455 | DynamicAttr::getReplaceImmediateSubElementsFn(), typeID, nameAttr); |
456 | |
457 | /// Add the type to the dialect and the type uniquer. |
458 | addAttribute(typeID, std::move(abstractAttr)); |
459 | attrPtr->registerInAttrUniquer(); |
460 | } |
461 | |
462 | void ExtensibleDialect::registerDynamicOp( |
463 | std::unique_ptr<DynamicOpDefinition> &&op) { |
464 | assert(op->dialect == this && |
465 | "trying to register a dynamic op in the wrong dialect" ); |
466 | RegisteredOperationName::insert(std::move(op), /*attrNames=*/{}); |
467 | } |
468 | |
469 | bool ExtensibleDialect::classof(const Dialect *dialect) { |
470 | return const_cast<Dialect *>(dialect) |
471 | ->getRegisteredInterface<IsExtensibleDialect>(); |
472 | } |
473 | |
474 | OptionalParseResult ExtensibleDialect::parseOptionalDynamicType( |
475 | StringRef typeName, AsmParser &parser, Type &resultType) const { |
476 | DynamicTypeDefinition *typeDef = lookupTypeDefinition(name: typeName); |
477 | if (!typeDef) |
478 | return std::nullopt; |
479 | |
480 | DynamicType dynType; |
481 | if (DynamicType::parse(parser, typeDef, parsedType&: dynType)) |
482 | return failure(); |
483 | resultType = dynType; |
484 | return success(); |
485 | } |
486 | |
487 | LogicalResult ExtensibleDialect::printIfDynamicType(Type type, |
488 | AsmPrinter &printer) { |
489 | if (auto dynType = llvm::dyn_cast<DynamicType>(Val&: type)) { |
490 | dynType.print(printer); |
491 | return success(); |
492 | } |
493 | return failure(); |
494 | } |
495 | |
496 | OptionalParseResult ExtensibleDialect::parseOptionalDynamicAttr( |
497 | StringRef attrName, AsmParser &parser, Attribute &resultAttr) const { |
498 | DynamicAttrDefinition *attrDef = lookupAttrDefinition(name: attrName); |
499 | if (!attrDef) |
500 | return std::nullopt; |
501 | |
502 | DynamicAttr dynAttr; |
503 | if (DynamicAttr::parse(parser, attrDef, parsedAttr&: dynAttr)) |
504 | return failure(); |
505 | resultAttr = dynAttr; |
506 | return success(); |
507 | } |
508 | |
509 | LogicalResult ExtensibleDialect::printIfDynamicAttr(Attribute attribute, |
510 | AsmPrinter &printer) { |
511 | if (auto dynAttr = llvm::dyn_cast<DynamicAttr>(Val&: attribute)) { |
512 | dynAttr.print(printer); |
513 | return success(); |
514 | } |
515 | return failure(); |
516 | } |
517 | |
518 | //===----------------------------------------------------------------------===// |
519 | // Dynamic dialect |
520 | //===----------------------------------------------------------------------===// |
521 | |
522 | namespace { |
523 | /// Interface that can only be implemented by extensible dialects. |
524 | /// The interface is used to check if a dialect is extensible or not. |
525 | class IsDynamicDialect : public DialectInterface::Base<IsDynamicDialect> { |
526 | public: |
527 | IsDynamicDialect(Dialect *dialect) : Base(dialect) {} |
528 | |
529 | MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(IsDynamicDialect) |
530 | }; |
531 | } // namespace |
532 | |
533 | DynamicDialect::DynamicDialect(StringRef name, MLIRContext *ctx) |
534 | : SelfOwningTypeID(), |
535 | ExtensibleDialect(name, ctx, SelfOwningTypeID::getTypeID()) { |
536 | addInterfaces<IsDynamicDialect>(); |
537 | } |
538 | |
539 | bool DynamicDialect::classof(const Dialect *dialect) { |
540 | return const_cast<Dialect *>(dialect) |
541 | ->getRegisteredInterface<IsDynamicDialect>(); |
542 | } |
543 | |
544 | Type DynamicDialect::parseType(DialectAsmParser &parser) const { |
545 | auto loc = parser.getCurrentLocation(); |
546 | StringRef typeTag; |
547 | if (failed(result: parser.parseKeyword(keyword: &typeTag))) |
548 | return Type(); |
549 | |
550 | { |
551 | Type dynType; |
552 | auto parseResult = parseOptionalDynamicType(typeName: typeTag, parser, resultType&: dynType); |
553 | if (parseResult.has_value()) { |
554 | if (succeeded(result: parseResult.value())) |
555 | return dynType; |
556 | return Type(); |
557 | } |
558 | } |
559 | |
560 | parser.emitError(loc, message: "expected dynamic type" ); |
561 | return Type(); |
562 | } |
563 | |
564 | void DynamicDialect::printType(Type type, DialectAsmPrinter &printer) const { |
565 | auto wasDynamic = printIfDynamicType(type, printer); |
566 | (void)wasDynamic; |
567 | assert(succeeded(wasDynamic) && |
568 | "non-dynamic type defined in dynamic dialect" ); |
569 | } |
570 | |
571 | Attribute DynamicDialect::parseAttribute(DialectAsmParser &parser, |
572 | Type type) const { |
573 | auto loc = parser.getCurrentLocation(); |
574 | StringRef typeTag; |
575 | if (failed(result: parser.parseKeyword(keyword: &typeTag))) |
576 | return Attribute(); |
577 | |
578 | { |
579 | Attribute dynAttr; |
580 | auto parseResult = parseOptionalDynamicAttr(attrName: typeTag, parser, resultAttr&: dynAttr); |
581 | if (parseResult.has_value()) { |
582 | if (succeeded(result: parseResult.value())) |
583 | return dynAttr; |
584 | return Attribute(); |
585 | } |
586 | } |
587 | |
588 | parser.emitError(loc, message: "expected dynamic attribute" ); |
589 | return Attribute(); |
590 | } |
591 | void DynamicDialect::printAttribute(Attribute attr, |
592 | DialectAsmPrinter &printer) const { |
593 | auto wasDynamic = printIfDynamicAttr(attribute: attr, printer); |
594 | (void)wasDynamic; |
595 | assert(succeeded(wasDynamic) && |
596 | "non-dynamic attribute defined in dynamic dialect" ); |
597 | } |
598 | |