MLIR  15.0.0git
StorageUniquerSupport.h
Go to the documentation of this file.
1 //===- StorageUniquerSupport.h - MLIR Storage Uniquer Utilities -*- 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 // This file defines utility classes for interfacing with StorageUniquer.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_IR_STORAGEUNIQUERSUPPORT_H
14 #define MLIR_IR_STORAGEUNIQUERSUPPORT_H
15 
19 #include "mlir/Support/TypeID.h"
20 #include "llvm/ADT/FunctionExtras.h"
21 
22 namespace mlir {
23 class InFlightDiagnostic;
24 class Location;
25 class MLIRContext;
26 
27 namespace detail {
28 /// Utility method to generate a callback that can be used to generate a
29 /// diagnostic when checking the construction invariants of a storage object.
30 /// This is defined out-of-line to avoid the need to include Location.h.
31 llvm::unique_function<InFlightDiagnostic()>
32 getDefaultDiagnosticEmitFn(MLIRContext *ctx);
33 llvm::unique_function<InFlightDiagnostic()>
34 getDefaultDiagnosticEmitFn(const Location &loc);
35 
36 //===----------------------------------------------------------------------===//
37 // StorageUserTraitBase
38 //===----------------------------------------------------------------------===//
39 
40 /// Helper class for implementing traits for storage classes. Clients are not
41 /// expected to interact with this directly, so its members are all protected.
42 template <typename ConcreteType, template <typename> class TraitType>
44 protected:
45  /// Return the derived instance.
46  ConcreteType getInstance() const {
47  // We have to cast up to the trait type, then to the concrete type because
48  // the concrete type will multiply derive from the (content free) TraitBase
49  // class, and we need to be able to disambiguate the path for the C++
50  // compiler.
51  auto *trait = static_cast<const TraitType<ConcreteType> *>(this);
52  return *static_cast<const ConcreteType *>(trait);
53  }
54 };
55 
56 //===----------------------------------------------------------------------===//
57 // StorageUserBase
58 //===----------------------------------------------------------------------===//
59 
60 namespace storage_user_base_impl {
61 /// Returns true if this given Trait ID matches the IDs of any of the provided
62 /// trait types `Traits`.
63 template <template <typename T> class... Traits>
64 bool hasTrait(TypeID traitID) {
65  TypeID traitIDs[] = {TypeID::get<Traits>()...};
66  for (unsigned i = 0, e = sizeof...(Traits); i != e; ++i)
67  if (traitIDs[i] == traitID)
68  return true;
69  return false;
70 }
71 
72 // We specialize for the empty case to not define an empty array.
73 template <>
74 inline bool hasTrait(TypeID traitID) {
75  return false;
76 }
77 } // namespace storage_user_base_impl
78 
79 /// Utility class for implementing users of storage classes uniqued by a
80 /// StorageUniquer. Clients are not expected to interact with this class
81 /// directly.
82 template <typename ConcreteT, typename BaseT, typename StorageT,
83  typename UniquerT, template <typename T> class... Traits>
84 class StorageUserBase : public BaseT, public Traits<ConcreteT>... {
85 public:
86  using BaseT::BaseT;
87 
88  /// Utility declarations for the concrete attribute class.
89  using Base = StorageUserBase<ConcreteT, BaseT, StorageT, UniquerT, Traits...>;
90  using ImplType = StorageT;
91  using HasTraitFn = bool (*)(TypeID);
92 
93  /// Return a unique identifier for the concrete type.
94  static TypeID getTypeID() { return TypeID::get<ConcreteT>(); }
95 
96  /// Provide an implementation of 'classof' that compares the type id of the
97  /// provided value with that of the concrete type.
98  template <typename T> static bool classof(T val) {
100  "casting from a non-convertible type");
101  return val.getTypeID() == getTypeID();
102  }
103 
104  /// Returns an interface map for the interfaces registered to this storage
105  /// user. This should not be used directly.
107  return detail::InterfaceMap::template get<Traits<ConcreteT>...>();
108  }
109 
110  /// Returns the function that returns true if the given Trait ID matches the
111  /// IDs of any of the traits defined by the storage user.
113  return [](TypeID id) {
114  return storage_user_base_impl::hasTrait<Traits...>(id);
115  };
116  }
117 
118  /// Attach the given models as implementations of the corresponding interfaces
119  /// for the concrete storage user class. The type must be registered with the
120  /// context, i.e. the dialect to which the type belongs must be loaded. The
121  /// call will abort otherwise.
122  template <typename... IfaceModels>
123  static void attachInterface(MLIRContext &context) {
124  typename ConcreteT::AbstractTy *abstract =
125  ConcreteT::AbstractTy::lookupMutable(TypeID::get<ConcreteT>(),
126  &context);
127  if (!abstract)
128  llvm::report_fatal_error("Registering an interface for an attribute/type "
129  "that is not itself registered.");
130  abstract->interfaceMap.template insert<IfaceModels...>();
131  }
132 
133  /// Get or create a new ConcreteT instance within the ctx. This
134  /// function is guaranteed to return a non null object and will assert if
135  /// the arguments provided are invalid.
136  template <typename... Args>
137  static ConcreteT get(MLIRContext *ctx, Args... args) {
138  // Ensure that the invariants are correct for construction.
139  assert(
141  return UniquerT::template get<ConcreteT>(ctx, args...);
142  }
143 
144  /// Get or create a new ConcreteT instance within the ctx, defined at
145  /// the given, potentially unknown, location. If the arguments provided are
146  /// invalid, errors are emitted using the provided location and a null object
147  /// is returned.
148  template <typename... Args>
149  static ConcreteT getChecked(const Location &loc, Args... args) {
150  return ConcreteT::getChecked(getDefaultDiagnosticEmitFn(loc), args...);
151  }
152 
153  /// Get or create a new ConcreteT instance within the ctx. If the arguments
154  /// provided are invalid, errors are emitted using the provided `emitError`
155  /// and a null object is returned.
156  template <typename... Args>
157  static ConcreteT getChecked(function_ref<InFlightDiagnostic()> emitErrorFn,
158  MLIRContext *ctx, Args... args) {
159  // If the construction invariants fail then we return a null attribute.
160  if (failed(ConcreteT::verify(emitErrorFn, args...)))
161  return ConcreteT();
162  return UniquerT::template get<ConcreteT>(ctx, args...);
163  }
164 
165  /// Get an instance of the concrete type from a void pointer.
166  static ConcreteT getFromOpaquePointer(const void *ptr) {
167  return ConcreteT((const typename BaseT::ImplType *)ptr);
168  }
169 
170 protected:
171  /// Mutate the current storage instance. This will not change the unique key.
172  /// The arguments are forwarded to 'ConcreteT::mutate'.
173  template <typename... Args> LogicalResult mutate(Args &&...args) {
174  return UniquerT::template mutate<ConcreteT>(this->getContext(), getImpl(),
175  std::forward<Args>(args)...);
176  }
177 
178  /// Default implementation that just returns success.
179  template <typename... Args> static LogicalResult verify(Args... args) {
180  return success();
181  }
182 
183  /// Utility for easy access to the storage instance.
184  ImplType *getImpl() const { return static_cast<ImplType *>(this->impl); }
185 };
186 } // namespace detail
187 } // namespace mlir
188 
189 #endif
Include the generated interface declarations.
bool hasTrait(TypeID traitID)
Returns true if this given Trait ID matches the IDs of any of the provided trait types Traits...
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:311
ConcreteType getInstance() const
Return the derived instance.
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value...
Definition: LogicalResult.h:72
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value...
Definition: LogicalResult.h:68
static constexpr const bool value
This class provides an efficient unique identifier for a specific C++ type.
Definition: TypeID.h:104
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:48
static LogicalResult verify(Args... args)
Default implementation that just returns success.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
This class provides an efficient mapping between a given Interface type, and a particular implementat...
static HasTraitFn getHasTraitFn()
Returns the function that returns true if the given Trait ID matches the IDs of any of the traits def...
static ConcreteT getChecked(function_ref< InFlightDiagnostic()> emitErrorFn, MLIRContext *ctx, Args... args)
Get or create a new ConcreteT instance within the ctx.
static detail::InterfaceMap getInterfaceMap()
Returns an interface map for the interfaces registered to this storage user.
llvm::unique_function< InFlightDiagnostic()> getDefaultDiagnosticEmitFn(MLIRContext *ctx)
Utility method to generate a callback that can be used to generate a diagnostic when checking the con...
static void attachInterface(MLIRContext &context)
Attach the given models as implementations of the corresponding interfaces for the concrete storage u...
static ConcreteT getFromOpaquePointer(const void *ptr)
Get an instance of the concrete type from a void pointer.
LogicalResult mutate(Args &&...args)
Mutate the current storage instance.
ImplType * getImpl() const
Utility for easy access to the storage instance.
Utility class for implementing users of storage classes uniqued by a StorageUniquer.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:55
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs, on this operation and any nested operations.
Definition: Verifier.cpp:372
static TypeID getTypeID()
Return a unique identifier for the concrete type.
Helper class for implementing traits for storage classes.
static bool classof(T val)
Provide an implementation of &#39;classof&#39; that compares the type id of the provided value with that of t...
static ConcreteT getChecked(const Location &loc, Args... args)
Get or create a new ConcreteT instance within the ctx, defined at the given, potentially unknown...