MLIR 23.0.0git
ExtensibleDialect.h
Go to the documentation of this file.
1//===- ExtensibleDialect.h - 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// This file defines the DynamicOpDefinition class, the DynamicTypeDefinition
10// class, and the DynamicAttrDefinition class, which represent respectively
11// operations, types, and attributes that can be defined at runtime. They can
12// be registered at runtime to an extensible dialect, using the
13// ExtensibleDialect class defined in this file.
14//
15// For a more complete documentation, see
16// https://mlir.llvm.org/docs/ExtensibleDialects/ .
17//
18//===----------------------------------------------------------------------===//
19
20#ifndef MLIR_IR_EXTENSIBLEDIALECT_H
21#define MLIR_IR_EXTENSIBLEDIALECT_H
22
23#include "mlir/IR/Dialect.h"
25#include "mlir/IR/MLIRContext.h"
28#include "mlir/Support/TypeID.h"
29#include "llvm/ADT/StringMap.h"
30#include "llvm/Support/ErrorHandling.h"
31#include <optional>
32
33namespace mlir {
34class AsmParser;
35class AsmPrinter;
36class DynamicAttr;
37class DynamicType;
39class MLIRContext;
41
42namespace detail {
45} // namespace detail
46
47//===----------------------------------------------------------------------===//
48// Dynamic attribute
49//===----------------------------------------------------------------------===//
50
51/// The definition of a dynamic attribute. A dynamic attribute is an attribute
52/// that is defined at runtime, and that can be registered at runtime by an
53/// extensible dialect (a dialect inheriting ExtensibleDialect). This class
54/// stores the parser, the printer, and the verifier of the attribute. Each
55/// dynamic attribute definition refers to one instance of this class.
56class DynamicAttrDefinition : public SelfOwningTypeID {
57public:
58 using VerifierFn = llvm::unique_function<LogicalResult(
60 using ParserFn = llvm::unique_function<ParseResult(
61 AsmParser &parser, llvm::SmallVectorImpl<Attribute> &parsedAttributes)
62 const>;
63 using PrinterFn = llvm::unique_function<void(
64 AsmPrinter &printer, ArrayRef<Attribute> params) const>;
65
66 /// Create a new attribute definition at runtime. The attribute is registered
67 /// only after passing it to the dialect using registerDynamicAttr.
68 static std::unique_ptr<DynamicAttrDefinition>
69 get(StringRef name, ExtensibleDialect *dialect, VerifierFn &&verifier);
70 static std::unique_ptr<DynamicAttrDefinition>
71 get(StringRef name, ExtensibleDialect *dialect, VerifierFn &&verifier,
72 ParserFn &&parser, PrinterFn &&printer);
73
74 /// Sets the verifier function for this attribute. It should emits an error
75 /// message and returns failure if a problem is detected, or returns success
76 /// if everything is ok.
77 void setVerifyFn(VerifierFn &&verify) { verifier = std::move(verify); }
78
79 /// Sets the static hook for parsing this attribute assembly.
80 void setParseFn(ParserFn &&parse) { parser = std::move(parse); }
81
82 /// Sets the static hook for printing this attribute assembly.
83 void setPrintFn(PrinterFn &&print) { printer = std::move(print); }
84
85 /// Check that the attribute parameters are valid.
87 ArrayRef<Attribute> params) const {
88 return verifier(emitError, params);
89 }
90
91 /// Return the MLIRContext in which the dynamic attributes are uniqued.
92 MLIRContext &getContext() const { return *ctx; }
93
94 /// Return the name of the attribute, in the format 'attrname' and
95 /// not 'dialectname.attrname'.
96 StringRef getName() const { return name; }
97
98 /// Return the dialect defining the attribute.
99 ExtensibleDialect *getDialect() const { return dialect; }
100
101private:
102 DynamicAttrDefinition(StringRef name, ExtensibleDialect *dialect,
103 VerifierFn &&verifier, ParserFn &&parser,
104 PrinterFn &&printer);
105
106 /// This constructor should only be used when we need a pointer to
107 /// the DynamicAttrDefinition in the verifier, the parser, or the printer.
108 /// The verifier, parser, and printer need thus to be initialized after the
109 /// constructor.
110 DynamicAttrDefinition(ExtensibleDialect *dialect, StringRef name);
111
112 /// Register the concrete attribute in the attribute Uniquer.
113 void registerInAttrUniquer();
114
115 /// The name should be prefixed with the dialect name followed by '.'.
116 std::string name;
117
118 /// Dialect in which this attribute is defined.
119 ExtensibleDialect *dialect;
120
121 /// The attribute verifier. It checks that the attribute parameters satisfy
122 /// the invariants.
123 VerifierFn verifier;
124
125 /// The attribute parameters parser. It parses only the parameters, and
126 /// expects the attribute name to have already been parsed.
127 ParserFn parser;
128
129 /// The attribute parameters printer. It prints only the parameters, and
130 /// expects the attribute name to have already been printed.
131 PrinterFn printer;
132
133 /// Context in which the concrete attributes are uniqued.
134 MLIRContext *ctx;
135
136 friend ExtensibleDialect;
137 friend DynamicAttr;
138};
139
140/// This trait is used to determine if an attribute is a dynamic attribute or
141/// not; it should only be implemented by dynamic attributes.
142/// Note: This is only required because dynamic attributes do not have a
143/// static/single TypeID.
144namespace AttributeTrait {
145template <typename ConcreteType>
146class IsDynamicAttr : public TraitBase<ConcreteType, IsDynamicAttr> {};
147} // namespace AttributeTrait
148
149/// A dynamic attribute instance. This is an attribute whose definition is
150/// defined at runtime.
151/// It is possible to check if an attribute is a dynamic attribute using
152/// `isa<DynamicAttr>(myAttr)`, and getting the attribute definition of a
153/// dynamic attribute using the `DynamicAttr::getAttrDef` method.
154/// All dynamic attributes have the same storage, which is an array of
155/// attributes.
156
157class DynamicAttr : public Attribute::AttrBase<DynamicAttr, Attribute,
158 detail::DynamicAttrStorage,
159 AttributeTrait::IsDynamicAttr> {
160public:
161 // Inherit Base constructors.
162 using Base::Base;
163
164 /// Return an instance of a dynamic attribute given a dynamic attribute
165 /// definition and attribute parameters.
166 /// This asserts that the attribute verifier succeeded.
167 static DynamicAttr get(DynamicAttrDefinition *attrDef,
168 ArrayRef<Attribute> params = {});
169
170 /// Return an instance of a dynamic attribute given a dynamic attribute
171 /// definition and attribute parameters. If the parameters provided are
172 /// invalid, errors are emitted using the provided location and a null object
173 /// is returned.
175 DynamicAttrDefinition *attrDef,
176 ArrayRef<Attribute> params = {});
177
178 /// Return the attribute definition of the concrete attribute.
180
181 /// Return the attribute parameters.
183
184 /// Check if an attribute is a specific dynamic attribute.
185 static bool isa(Attribute attr, DynamicAttrDefinition *attrDef) {
186 return attr.getTypeID() == attrDef->getTypeID();
187 }
188
189 /// Check if an attribute is a dynamic attribute.
190 static bool classof(Attribute attr);
191
192 /// Parse the dynamic attribute parameters and construct the attribute.
193 /// The parameters are either empty, and nothing is parsed,
194 /// or they are in the format '<>' or '<attr (,attr)*>'.
195 static ParseResult parse(AsmParser &parser, DynamicAttrDefinition *attrDef,
196 DynamicAttr &parsedAttr);
197
198 /// Print the dynamic attribute with the format 'attrname' if there is no
199 /// parameters, or 'attrname<attr (,attr)*>'.
200 void print(AsmPrinter &printer);
201};
202
203//===----------------------------------------------------------------------===//
204// Dynamic type
205//===----------------------------------------------------------------------===//
206
207/// The definition of a dynamic type. A dynamic type is a type that is
208/// defined at runtime, and that can be registered at runtime by an
209/// extensible dialect (a dialect inheriting ExtensibleDialect). This class
210/// stores the parser, the printer, and the verifier of the type. Each dynamic
211/// type definition refers to one instance of this class.
212class DynamicTypeDefinition : public SelfOwningTypeID {
213public:
214 using VerifierFn = llvm::unique_function<LogicalResult(
216 using ParserFn = llvm::unique_function<ParseResult(
217 AsmParser &parser, llvm::SmallVectorImpl<Attribute> &parsedAttributes)
218 const>;
219 using PrinterFn = llvm::unique_function<void(
220 AsmPrinter &printer, ArrayRef<Attribute> params) const>;
221
222 /// Create a new dynamic type definition. The type is registered only after
223 /// passing it to the dialect using registerDynamicType.
224 static std::unique_ptr<DynamicTypeDefinition>
225 get(StringRef name, ExtensibleDialect *dialect, VerifierFn &&verifier);
226 static std::unique_ptr<DynamicTypeDefinition>
227 get(StringRef name, ExtensibleDialect *dialect, VerifierFn &&verifier,
228 ParserFn &&parser, PrinterFn &&printer);
229
230 /// Sets the verifier function for this type. It should emits an error
231 /// message and returns failure if a problem is detected, or returns success
232 /// if everything is ok.
233 void setVerifyFn(VerifierFn &&verify) { verifier = std::move(verify); }
234
235 /// Sets the static hook for parsing this type assembly.
236 void setParseFn(ParserFn &&parse) { parser = std::move(parse); }
237
238 /// Sets the static hook for printing this type assembly.
239 void setPrintFn(PrinterFn &&print) { printer = std::move(print); }
240
241 /// Check that the type parameters are valid.
243 ArrayRef<Attribute> params) const {
244 return verifier(emitError, params);
245 }
246
247 /// Return the MLIRContext in which the dynamic types is uniqued.
248 MLIRContext &getContext() const { return *ctx; }
249
250 /// Return the name of the type, in the format 'typename' and
251 /// not 'dialectname.typename'.
252 StringRef getName() const { return name; }
253
254 /// Return the dialect defining the type.
255 ExtensibleDialect *getDialect() const { return dialect; }
256
257private:
258 DynamicTypeDefinition(StringRef name, ExtensibleDialect *dialect,
259 VerifierFn &&verifier, ParserFn &&parser,
260 PrinterFn &&printer);
261
262 /// This constructor should only be used when we need a pointer to
263 /// the DynamicTypeDefinition in the verifier, the parser, or the printer.
264 /// The verifier, parser, and printer need thus to be initialized after the
265 /// constructor.
266 DynamicTypeDefinition(ExtensibleDialect *dialect, StringRef name);
267
268 /// Register the concrete type in the type Uniquer.
269 void registerInTypeUniquer();
270
271 /// The name should be prefixed with the dialect name followed by '.'.
272 std::string name;
273
274 /// Dialect in which this type is defined.
275 ExtensibleDialect *dialect;
276
277 /// The type verifier. It checks that the type parameters satisfy the
278 /// invariants.
279 VerifierFn verifier;
280
281 /// The type parameters parser. It parses only the parameters, and expects the
282 /// type name to have already been parsed.
283 ParserFn parser;
284
285 /// The type parameters printer. It prints only the parameters, and expects
286 /// the type name to have already been printed.
287 PrinterFn printer;
288
289 /// Context in which the concrete types are uniqued.
290 MLIRContext *ctx;
291
292 friend ExtensibleDialect;
293 friend DynamicType;
294};
295
296/// This trait is used to determine if a type is a dynamic type or not;
297/// it should only be implemented by dynamic types.
298/// Note: This is only required because dynamic type do not have a
299/// static/single TypeID.
300namespace TypeTrait {
301template <typename ConcreteType>
302class IsDynamicType : public TypeTrait::TraitBase<ConcreteType, IsDynamicType> {
303};
304} // namespace TypeTrait
305
306/// A dynamic type instance. This is a type whose definition is defined at
307/// runtime.
308/// It is possible to check if a type is a dynamic type using
309/// `isa<DynamicType>(myType)`, and getting the type definition of a dynamic
310/// type using the `DynamicType::getTypeDef` method.
311/// All dynamic types have the same storage, which is an array of attributes.
313 : public Type::TypeBase<DynamicType, Type, detail::DynamicTypeStorage,
314 TypeTrait::IsDynamicType> {
315public:
316 // Inherit Base constructors.
317 using Base::Base;
318
319 /// Return an instance of a dynamic type given a dynamic type definition and
320 /// type parameters.
321 /// This asserts that the type verifier succeeded.
322 static DynamicType get(DynamicTypeDefinition *typeDef,
323 ArrayRef<Attribute> params = {});
324
325 /// Return an instance of a dynamic type given a dynamic type definition and
326 /// type parameters. If the parameters provided are invalid, errors are
327 /// emitted using the provided location and a null object is returned.
329 DynamicTypeDefinition *typeDef,
330 ArrayRef<Attribute> params = {});
331
332 /// Return the type definition of the concrete type.
334
335 /// Return the type parameters.
337
338 /// Check if a type is a specific dynamic type.
339 static bool isa(Type type, DynamicTypeDefinition *typeDef) {
340 return type.getTypeID() == typeDef->getTypeID();
341 }
342
343 /// Check if a type is a dynamic type.
344 static bool classof(Type type);
345
346 /// Parse the dynamic type parameters and construct the type.
347 /// The parameters are either empty, and nothing is parsed,
348 /// or they are in the format '<>' or '<attr (,attr)*>'.
349 static ParseResult parse(AsmParser &parser, DynamicTypeDefinition *typeDef,
350 DynamicType &parsedType);
351
352 /// Print the dynamic type with the format
353 /// 'type' or 'type<>' if there is no parameters, or 'type<attr (,attr)*>'.
354 void print(AsmPrinter &printer);
355};
356
357/// Base class of traits for dynamic-defined operations.
359public:
360 virtual LogicalResult verifyTrait(Operation *op) const { return success(); };
361 virtual LogicalResult verifyRegionTrait(Operation *op) const {
362 return success();
363 };
364
365 /// Returns the TypeID of the trait.
366 /// It must be equal to the TypeID of corresponding static trait
367 /// which will be used in `hasTrait(TypeID)`.
368 virtual TypeID getTypeID() const = 0;
369 virtual ~DynamicOpTrait() = default;
370};
371
372/// This class holds a list of traits for dynamic-defined operations.
374public:
375 bool insert(std::unique_ptr<DynamicOpTrait> trait) {
376 return traits.try_emplace(trait->getTypeID(), std::move(trait)).second;
377 }
378
379 bool contains(TypeID id) const { return traits.contains(id); }
380
381 LogicalResult verifyTraits(Operation *op) const {
382 for (const auto &[_, trait] : traits) {
383 if (failed(trait->verifyTrait(op)))
384 return failure();
385 }
386 return success();
387 }
388
389 LogicalResult verifyRegionTraits(Operation *op) const {
390 for (const auto &[_, trait] : traits) {
391 if (failed(trait->verifyRegionTrait(op)))
392 return failure();
393 }
394 return success();
395 }
396
397private:
398 llvm::MapVector<TypeID, std::unique_ptr<DynamicOpTrait>> traits;
399};
400
401template <template <typename T> class Trait>
403public:
405 TypeID getTypeID() const override { return getStaticTypeID(); }
406};
407
409
410class IsTerminator : public DynamicOpTraitImpl<OpTrait::IsTerminator> {
411public:
412 LogicalResult verifyTrait(Operation *op) const override {
414 }
415};
416
417class NoTerminator : public DynamicOpTraitImpl<OpTrait::NoTerminator> {};
418
419} // namespace DynamicOpTraits
420
421//===----------------------------------------------------------------------===//
422// Dynamic operation
423//===----------------------------------------------------------------------===//
424
425/// The definition of a dynamic op. A dynamic op is an op that is defined at
426/// runtime, and that can be registered at runtime by an extensible dialect (a
427/// dialect inheriting ExtensibleDialect). This class implements the method
428/// exposed by the OperationName class, and in addition defines the TypeID of
429/// the op that will be defined. Each dynamic operation definition refers to one
430/// instance of this class.
431class DynamicOpDefinition : public OperationName::Impl {
432public:
434 llvm::unique_function<void(RewritePatternSet &, MLIRContext *) const>;
435
436 /// Create a new op at runtime. The op is registered only after passing it to
437 /// the dialect using registerDynamicOp.
438 static std::unique_ptr<DynamicOpDefinition>
439 get(StringRef name, ExtensibleDialect *dialect,
442 static std::unique_ptr<DynamicOpDefinition>
443 get(StringRef name, ExtensibleDialect *dialect,
448 static std::unique_ptr<DynamicOpDefinition>
449 get(StringRef name, ExtensibleDialect *dialect,
454 OperationName::FoldHookFn &&foldHookFn,
455 GetCanonicalizationPatternsFn &&getCanonicalizationPatternsFn,
456 OperationName::PopulateDefaultAttrsFn &&populateDefaultAttrsFn);
457
458 /// Returns the op typeID.
459 TypeID getTypeID() { return typeID; }
460
461 /// Sets the verifier function for this operation. It should emits an error
462 /// message and returns failure if a problem is detected, or returns success
463 /// if everything is ok.
465 verifyFn = std::move(verify);
466 }
467
468 /// Sets the region verifier function for this operation. It should emits an
469 /// error message and returns failure if a problem is detected, or returns
470 /// success if everything is ok.
472 verifyRegionFn = std::move(verify);
473 }
474
475 /// Sets the static hook for parsing this op assembly.
477 parseFn = std::move(parse);
478 }
479
480 /// Sets the static hook for printing this op assembly.
482 printFn = std::move(print);
483 }
484
485 /// Sets the hook implementing a generalized folder for the op. See
486 /// `RegisteredOperationName::foldHook` for more details
488 foldHookFn = std::move(foldHook);
489 }
490
491 /// Set the hook returning any canonicalization pattern rewrites that the op
492 /// supports, for use by the canonicalization pass.
497
498 /// Set the hook populating default attributes.
503
504 /// Attach a trait to this dynamic-defined op.
505 bool addTrait(std::unique_ptr<DynamicOpTrait> trait) {
506 return traits.insert(std::move(trait));
507 }
508
509 LogicalResult foldHook(Operation *op, ArrayRef<Attribute> attrs,
510 SmallVectorImpl<OpFoldResult> &results) final {
511 return foldHookFn(op, attrs, results);
512 }
514 MLIRContext *context) final {
515 getCanonicalizationPatternsFn(set, context);
516 }
517 bool hasTrait(TypeID id) final { return traits.contains(id); }
519 return [&](OpAsmParser &parser, OperationState &state) {
520 return parseFn(parser, state);
521 };
522 }
524 NamedAttrList &attrs) final {
525 populateDefaultAttrsFn(name, attrs);
526 }
528 StringRef name) final {
529 printFn(op, printer, name);
530 }
531 LogicalResult verifyInvariants(Operation *op) final {
532 return failure(failed(traits.verifyTraits(op)) || failed(verifyFn(op)));
533 }
534 LogicalResult verifyRegionInvariants(Operation *op) final {
535 return failure(failed(traits.verifyRegionTraits(op)) ||
536 failed(verifyRegionFn(op)));
537 }
538
539 /// Implementation for properties (unsupported right now here).
540 std::optional<Attribute> getInherentAttr(Operation *op,
541 StringRef name) final {
542 llvm::report_fatal_error("Unsupported getInherentAttr on Dynamic dialects");
543 }
544 void setInherentAttr(Operation *op, StringAttr name, Attribute value) final {
545 llvm::report_fatal_error("Unsupported setInherentAttr on Dynamic dialects");
546 }
548 LogicalResult
551 return success();
552 }
553 int getOpPropertyByteSize() final { return 0; }
555 OpaqueProperties init) final {}
558 OpaqueProperties properties) final {}
559
560 LogicalResult
562 Attribute attr,
564 emitError() << "extensible Dialects don't support properties";
565 return failure();
566 }
567 Attribute getPropertiesAsAttr(Operation *op) final { return {}; }
570 return true;
571 }
572 llvm::hash_code hashProperties(OpaqueProperties prop) final { return {}; }
573
574private:
576 StringRef name, ExtensibleDialect *dialect,
581 OperationName::FoldHookFn &&foldHookFn,
582 GetCanonicalizationPatternsFn &&getCanonicalizationPatternsFn,
583 OperationName::PopulateDefaultAttrsFn &&populateDefaultAttrsFn);
584
585 /// Dialect defining this operation.
586 ExtensibleDialect *getdialect();
587
592 OperationName::FoldHookFn foldHookFn;
593 GetCanonicalizationPatternsFn getCanonicalizationPatternsFn;
594 OperationName::PopulateDefaultAttrsFn populateDefaultAttrsFn;
595 DynamicOpTraitList traits;
596
597 friend ExtensibleDialect;
598};
599
600//===----------------------------------------------------------------------===//
601// Extensible dialect
602//===----------------------------------------------------------------------===//
603
604/// A dialect that can be extended with new operations/types/attributes at
605/// runtime.
607public:
608 ExtensibleDialect(StringRef name, MLIRContext *ctx, TypeID typeID);
609
610 /// Add a new type defined at runtime to the dialect.
611 void registerDynamicType(std::unique_ptr<DynamicTypeDefinition> &&type);
612
613 /// Add a new attribute defined at runtime to the dialect.
614 void registerDynamicAttr(std::unique_ptr<DynamicAttrDefinition> &&attr);
615
616 /// Add a new operation defined at runtime to the dialect.
617 void registerDynamicOp(std::unique_ptr<DynamicOpDefinition> &&type);
618
619 /// Check if the dialect is an extensible dialect.
620 static bool classof(const Dialect *dialect);
621
622 /// Returns nullptr if the definition was not found.
624 return nameToDynTypes.lookup(name);
625 }
626
627 /// Returns nullptr if the definition was not found.
629 auto it = dynTypes.find(id);
630 if (it == dynTypes.end())
631 return nullptr;
632 return it->second.get();
633 }
634
635 /// Returns nullptr if the definition was not found.
637 return nameToDynAttrs.lookup(name);
638 }
639
640 /// Returns nullptr if the definition was not found.
642 auto it = dynAttrs.find(id);
643 if (it == dynAttrs.end())
644 return nullptr;
645 return it->second.get();
646 }
647
648protected:
649 /// Parse the dynamic type 'typeName' in the dialect 'dialect'.
650 /// typename should not be prefixed with the dialect name.
651 /// If the dynamic type does not exist, return no value.
652 /// Otherwise, parse it, and return the parse result.
653 /// If the parsing succeed, put the resulting type in 'resultType'.
655 AsmParser &parser,
656 Type &resultType) const;
657
658 /// If 'type' is a dynamic type, print it.
659 /// Returns success if the type was printed, and failure if the type was not a
660 /// dynamic type.
661 static LogicalResult printIfDynamicType(Type type, AsmPrinter &printer);
662
663 /// Parse the dynamic attribute 'attrName' in the dialect 'dialect'.
664 /// attrname should not be prefixed with the dialect name.
665 /// If the dynamic attribute does not exist, return no value.
666 /// Otherwise, parse it, and return the parse result.
667 /// If the parsing succeed, put the resulting attribute in 'resultAttr'.
669 AsmParser &parser,
670 Attribute &resultAttr) const;
671
672 /// If 'attr' is a dynamic attribute, print it.
673 /// Returns success if the attribute was printed, and failure if the
674 /// attribute was not a dynamic attribute.
675 static LogicalResult printIfDynamicAttr(Attribute attr, AsmPrinter &printer);
676
677private:
678 /// The set of all dynamic types registered.
680
681 /// This structure allows to get in O(1) a dynamic type given its name.
682 llvm::StringMap<DynamicTypeDefinition *> nameToDynTypes;
683
684 /// The set of all dynamic attributes registered.
686
687 /// This structure allows to get in O(1) a dynamic attribute given its name.
688 llvm::StringMap<DynamicAttrDefinition *> nameToDynAttrs;
689
690 /// Give DynamicOpDefinition access to allocateTypeID.
691 friend DynamicOpDefinition;
692
693 /// Allocates a type ID to uniquify operations.
694 TypeID allocateTypeID() { return typeIDAllocator.allocate(); }
695
696 /// Owns the TypeID generated at runtime for operations.
697 TypeIDAllocator typeIDAllocator;
698};
699
700//===----------------------------------------------------------------------===//
701// Dynamic dialect
702//===----------------------------------------------------------------------===//
703
704/// A dialect that can be defined at runtime. It can be extended with new
705/// operations, types, and attributes at runtime.
707public:
708 DynamicDialect(StringRef name, MLIRContext *ctx);
709
711
712 /// Check if the dialect is an extensible dialect.
713 static bool classof(const Dialect *dialect);
714
715 virtual Type parseType(DialectAsmParser &parser) const override;
716 virtual void printType(Type type, DialectAsmPrinter &printer) const override;
717
719 Type type) const override;
720 virtual void printAttribute(Attribute attr,
721 DialectAsmPrinter &printer) const override;
722};
723} // namespace mlir
724
725namespace llvm {
726/// Provide isa functionality for ExtensibleDialect.
727/// This is to override the isa functionality for Dialect.
728template <>
729struct isa_impl<mlir::ExtensibleDialect, mlir::Dialect> {
730 static inline bool doit(const ::mlir::Dialect &dialect) {
731 return mlir::ExtensibleDialect::classof(&dialect);
732 }
733};
734
735/// Provide isa functionality for DynamicDialect.
736/// This is to override the isa functionality for Dialect.
737template <>
738struct isa_impl<mlir::DynamicDialect, mlir::Dialect> {
739 static inline bool doit(const ::mlir::Dialect &dialect) {
740 return mlir::DynamicDialect::classof(&dialect);
741 }
742};
743} // namespace llvm
744
745#endif // MLIR_IR_EXTENSIBLEDIALECT_H
return success()
lhs
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
This base class exposes generic asm parser hooks, usable across the various derived parsers.
This base class exposes generic asm printer hooks, usable across the various derived printers.
Attributes are known-constant values of operations.
Definition Attributes.h:25
detail::StorageUserBase< ConcreteType, BaseType, StorageType, detail::AttributeUniquer, Traits... > AttrBase
Utility class for implementing attributes.
Definition Attributes.h:30
TypeID getTypeID()
Return a unique identifier for the concrete attribute type.
Definition Attributes.h:52
The DialectAsmParser has methods for interacting with the asm parser when parsing attributes and type...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition Dialect.h:38
friend class MLIRContext
Definition Dialect.h:371
Dialect(StringRef name, MLIRContext *context, TypeID id)
The constructor takes a unique namespace for this dialect as well as the context to bind to.
Definition Dialect.cpp:35
The definition of a dynamic attribute.
llvm::unique_function< void( AsmPrinter &printer, ArrayRef< Attribute > params) const > PrinterFn
void setVerifyFn(VerifierFn &&verify)
Sets the verifier function for this attribute.
static std::unique_ptr< DynamicAttrDefinition > get(StringRef name, ExtensibleDialect *dialect, VerifierFn &&verifier)
Create a new attribute definition at runtime.
LogicalResult verify(function_ref< InFlightDiagnostic()> emitError, ArrayRef< Attribute > params) const
Check that the attribute parameters are valid.
void setParseFn(ParserFn &&parse)
Sets the static hook for parsing this attribute assembly.
StringRef getName() const
Return the name of the attribute, in the format 'attrname' and not 'dialectname.attrname'.
void setPrintFn(PrinterFn &&print)
Sets the static hook for printing this attribute assembly.
llvm::unique_function< ParseResult( AsmParser &parser, llvm::SmallVectorImpl< Attribute > &parsedAttributes) const > ParserFn
MLIRContext & getContext() const
Return the MLIRContext in which the dynamic attributes are uniqued.
ExtensibleDialect * getDialect() const
Return the dialect defining the attribute.
llvm::unique_function< LogicalResult( function_ref< InFlightDiagnostic()>, ArrayRef< Attribute >) const > VerifierFn
A dynamic attribute instance.
static DynamicAttr getChecked(function_ref< InFlightDiagnostic()> emitError, DynamicAttrDefinition *attrDef, ArrayRef< Attribute > params={})
Return an instance of a dynamic attribute given a dynamic attribute definition and attribute paramete...
ArrayRef< Attribute > getParams()
Return the attribute parameters.
static DynamicAttr get(DynamicAttrDefinition *attrDef, ArrayRef< Attribute > params={})
Return an instance of a dynamic attribute given a dynamic attribute definition and attribute paramete...
void print(AsmPrinter &printer)
Print the dynamic attribute with the format 'attrname' if there is no parameters, or 'attrname<attr (...
static bool classof(Attribute attr)
Check if an attribute is a dynamic attribute.
static ParseResult parse(AsmParser &parser, DynamicAttrDefinition *attrDef, DynamicAttr &parsedAttr)
Parse the dynamic attribute parameters and construct the attribute.
DynamicAttrDefinition * getAttrDef()
Return the attribute definition of the concrete attribute.
static bool isa(Attribute attr, DynamicAttrDefinition *attrDef)
Check if an attribute is a specific dynamic attribute.
virtual void printAttribute(Attribute attr, DialectAsmPrinter &printer) const override
Print an attribute registered to this dialect.
DynamicDialect(StringRef name, MLIRContext *ctx)
virtual Attribute parseAttribute(DialectAsmParser &parser, Type type) const override
Parse an attribute registered to this dialect.
virtual void printType(Type type, DialectAsmPrinter &printer) const override
Print a type registered to this dialect.
static bool classof(const Dialect *dialect)
Check if the dialect is an extensible dialect.
virtual Type parseType(DialectAsmParser &parser) const override
Parse a type registered to this dialect.
The definition of a dynamic op.
LogicalResult verifyInvariants(Operation *op) final
TypeID getTypeID()
Returns the op typeID.
std::optional< Attribute > getInherentAttr(Operation *op, StringRef name) final
Implementation for properties (unsupported right now here).
LogicalResult foldHook(Operation *op, ArrayRef< Attribute > attrs, SmallVectorImpl< OpFoldResult > &results) final
LogicalResult verifyRegionInvariants(Operation *op) final
bool addTrait(std::unique_ptr< DynamicOpTrait > trait)
Attach a trait to this dynamic-defined op.
void setParseFn(OperationName::ParseAssemblyFn &&parse)
Sets the static hook for parsing this op assembly.
bool hasTrait(TypeID id) final
void setVerifyRegionFn(OperationName::VerifyRegionInvariantsFn &&verify)
Sets the region verifier function for this operation.
static std::unique_ptr< DynamicOpDefinition > get(StringRef name, ExtensibleDialect *dialect, OperationName::VerifyInvariantsFn &&verifyFn, OperationName::VerifyRegionInvariantsFn &&verifyRegionFn)
Create a new op at runtime.
void printAssembly(Operation *op, OpAsmPrinter &printer, StringRef name) final
Attribute getPropertiesAsAttr(Operation *op) final
void initProperties(OperationName opName, OpaqueProperties storage, OpaqueProperties init) final
OperationName::ParseAssemblyFn getParseAssemblyFn() final
void setFoldHookFn(OperationName::FoldHookFn &&foldHook)
Sets the hook implementing a generalized folder for the op.
void copyProperties(OpaqueProperties lhs, OpaqueProperties rhs) final
LogicalResult setPropertiesFromAttr(OperationName opName, OpaqueProperties properties, Attribute attr, function_ref< InFlightDiagnostic()> emitError) final
LogicalResult verifyInherentAttrs(OperationName opName, NamedAttrList &attributes, function_ref< InFlightDiagnostic()> emitError) final
void populateDefaultAttrs(const OperationName &name, NamedAttrList &attrs) final
bool compareProperties(OpaqueProperties, OpaqueProperties) final
llvm::unique_function< void(RewritePatternSet &, MLIRContext *) const > GetCanonicalizationPatternsFn
void setInherentAttr(Operation *op, StringAttr name, Attribute value) final
void populateInherentAttrs(Operation *op, NamedAttrList &attrs) final
void deleteProperties(OpaqueProperties prop) final
void setVerifyFn(OperationName::VerifyInvariantsFn &&verify)
Sets the verifier function for this operation.
void populateDefaultProperties(OperationName opName, OpaqueProperties properties) final
llvm::hash_code hashProperties(OpaqueProperties prop) final
void setGetCanonicalizationPatternsFn(GetCanonicalizationPatternsFn &&getCanonicalizationPatterns)
Set the hook returning any canonicalization pattern rewrites that the op supports,...
void setPrintFn(OperationName::PrintAssemblyFn &&print)
Sets the static hook for printing this op assembly.
void setPopulateDefaultAttrsFn(OperationName::PopulateDefaultAttrsFn &&populateDefaultAttrs)
Set the hook populating default attributes.
void getCanonicalizationPatterns(RewritePatternSet &set, MLIRContext *context) final
TypeID getTypeID() const override
Returns the TypeID of the trait.
This class holds a list of traits for dynamic-defined operations.
bool contains(TypeID id) const
LogicalResult verifyRegionTraits(Operation *op) const
LogicalResult verifyTraits(Operation *op) const
bool insert(std::unique_ptr< DynamicOpTrait > trait)
Base class of traits for dynamic-defined operations.
virtual LogicalResult verifyRegionTrait(Operation *op) const
virtual TypeID getTypeID() const =0
Returns the TypeID of the trait.
virtual LogicalResult verifyTrait(Operation *op) const
virtual ~DynamicOpTrait()=default
LogicalResult verifyTrait(Operation *op) const override
The definition of a dynamic type.
llvm::unique_function< void( AsmPrinter &printer, ArrayRef< Attribute > params) const > PrinterFn
void setPrintFn(PrinterFn &&print)
Sets the static hook for printing this type assembly.
MLIRContext & getContext() const
Return the MLIRContext in which the dynamic types is uniqued.
LogicalResult verify(function_ref< InFlightDiagnostic()> emitError, ArrayRef< Attribute > params) const
Check that the type parameters are valid.
StringRef getName() const
Return the name of the type, in the format 'typename' and not 'dialectname.typename'.
void setVerifyFn(VerifierFn &&verify)
Sets the verifier function for this type.
void setParseFn(ParserFn &&parse)
Sets the static hook for parsing this type assembly.
llvm::unique_function< ParseResult( AsmParser &parser, llvm::SmallVectorImpl< Attribute > &parsedAttributes) const > ParserFn
llvm::unique_function< LogicalResult( function_ref< InFlightDiagnostic()>, ArrayRef< Attribute >) const > VerifierFn
ExtensibleDialect * getDialect() const
Return the dialect defining the type.
static std::unique_ptr< DynamicTypeDefinition > get(StringRef name, ExtensibleDialect *dialect, VerifierFn &&verifier)
Create a new dynamic type definition.
A dynamic type instance.
static DynamicType getChecked(function_ref< InFlightDiagnostic()> emitError, DynamicTypeDefinition *typeDef, ArrayRef< Attribute > params={})
Return an instance of a dynamic type given a dynamic type definition and type parameters.
ArrayRef< Attribute > getParams()
Return the type parameters.
static bool isa(Type type, DynamicTypeDefinition *typeDef)
Check if a type is a specific dynamic type.
void print(AsmPrinter &printer)
Print the dynamic type with the format 'type' or 'type<>' if there is no parameters,...
DynamicTypeDefinition * getTypeDef()
Return the type definition of the concrete type.
static DynamicType get(DynamicTypeDefinition *typeDef, ArrayRef< Attribute > params={})
Return an instance of a dynamic type given a dynamic type definition and type parameters.
static ParseResult parse(AsmParser &parser, DynamicTypeDefinition *typeDef, DynamicType &parsedType)
Parse the dynamic type parameters and construct the type.
static bool classof(Type type)
Check if a type is a dynamic type.
A dialect that can be extended with new operations/types/attributes at runtime.
DynamicAttrDefinition * lookupAttrDefinition(TypeID id) const
Returns nullptr if the definition was not found.
static bool classof(const Dialect *dialect)
Check if the dialect is an extensible dialect.
void registerDynamicOp(std::unique_ptr< DynamicOpDefinition > &&type)
Add a new operation defined at runtime to the dialect.
DynamicTypeDefinition * lookupTypeDefinition(TypeID id) const
Returns nullptr if the definition was not found.
DynamicTypeDefinition * lookupTypeDefinition(StringRef name) const
Returns nullptr if the definition was not found.
static LogicalResult printIfDynamicType(Type type, AsmPrinter &printer)
If 'type' is a dynamic type, print it.
DynamicAttrDefinition * lookupAttrDefinition(StringRef name) const
Returns nullptr if the definition was not found.
void registerDynamicType(std::unique_ptr< DynamicTypeDefinition > &&type)
Add a new type defined at runtime to the dialect.
static LogicalResult printIfDynamicAttr(Attribute attr, AsmPrinter &printer)
If 'attr' is a dynamic attribute, print it.
OptionalParseResult parseOptionalDynamicAttr(StringRef attrName, AsmParser &parser, Attribute &resultAttr) const
Parse the dynamic attribute 'attrName' in the dialect 'dialect'.
ExtensibleDialect(StringRef name, MLIRContext *ctx, TypeID typeID)
void registerDynamicAttr(std::unique_ptr< DynamicAttrDefinition > &&attr)
Add a new attribute defined at runtime to the dialect.
OptionalParseResult parseOptionalDynamicType(StringRef typeName, AsmParser &parser, Type &resultType) const
Parse the dynamic type 'typeName' in the dialect 'dialect'.
This class represents a diagnostic that is inflight and set to be reported.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
Simple wrapper around a void* in order to express generically how to pass in op properties through AP...
StringAttr name
The name of the operation.
TypeID typeID
The unique identifier of the derived Op class.
Dialect * dialect
The following fields are only populated when the operation is registered.
llvm::unique_function< LogicalResult(Operation *) const > VerifyInvariantsFn
llvm::unique_function< void(const OperationName &, NamedAttrList &) const > PopulateDefaultAttrsFn
llvm::unique_function< ParseResult(OpAsmParser &, OperationState &)> ParseAssemblyFn
llvm::unique_function< LogicalResult(Operation *) const > VerifyRegionInvariantsFn
llvm::unique_function< LogicalResult( Operation *, ArrayRef< Attribute >, SmallVectorImpl< OpFoldResult > &) const > FoldHookFn
llvm::unique_function< void(Operation *, OpAsmPrinter &, StringRef) const > PrintAssemblyFn
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
This class implements Optional functionality for ParseResult.
TypeID getTypeID() const
Return the TypeID owned by this object.
Definition TypeID.h:381
TypeID allocate()
Allocate a new TypeID, that is ensured to be unique for the lifetime of the TypeIDAllocator.
Definition TypeID.h:353
This class provides an efficient unique identifier for a specific C++ type.
Definition TypeID.h:107
static TypeID get()
Construct a type info object for the given type T.
Definition TypeID.h:245
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
detail::StorageUserBase< ConcreteType, BaseType, StorageType, detail::TypeUniquer, Traits... > TypeBase
Utility class for implementing types.
Definition Types.h:79
TypeID getTypeID()
Return a unique identifier for the concrete type.
Definition Types.h:101
StorageUserBase< ConcreteType, BaseType, StorageType, detail::TypeUniquer, Traits... > Base
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition CallGraph.h:229
detail::StorageUserTraitBase< ConcreteType, TraitType > TraitBase
This class represents the base of an attribute trait.
Definition Attributes.h:242
LogicalResult verifyIsTerminator(Operation *op)
This trait is used to determine if a type is a dynamic type or not; it should only be implemented by ...
detail::StorageUserTraitBase< ConcreteType, TraitType > TraitBase
This class represents the base of a type trait.
Definition Types.h:252
AttrTypeReplacer.
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
Definition LLVM.h:120
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition Verifier.cpp:480
llvm::function_ref< Fn > function_ref
Definition LLVM.h:147
static bool doit(const ::mlir::Dialect &dialect)
static bool doit(const ::mlir::Dialect &dialect)
This represents an operation in an abstracted form, suitable for use with the builder APIs.