9 #ifndef MLIR_SUPPORT_STORAGEUNIQUER_H
10 #define MLIR_SUPPORT_STORAGEUNIQUER_H
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/DenseSet.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/Allocator.h"
22 struct StorageUniquerImpl;
25 template <
typename ImplTy,
typename... Args>
29 template <
typename ImplTy,
typename T>
101 auto result = allocator.Allocate<T>(elements.size());
102 std::uninitialized_copy(elements.begin(), elements.end(), result);
112 char *result = allocator.Allocate<
char>(str.size() + 1);
113 std::uninitialized_copy(str.begin(), str.end(), result);
114 result[str.size()] = 0;
115 return StringRef(result, str.size());
119 template <
typename T>
121 return allocator.Allocate<T>();
126 return allocator.Allocate(size, alignment);
131 return allocator.identifyObject(ptr).has_value();
136 llvm::BumpPtrAllocator allocator;
148 template <
typename Storage>
152 if constexpr (std::is_trivially_destructible_v<Storage>)
153 return registerParametricStorageTypeImpl(
id,
nullptr);
154 registerParametricStorageTypeImpl(
id, [](
BaseStorage *storage) {
155 static_cast<Storage *
>(storage)->~Storage();
159 template <
typename Storage>
161 registerParametricStorageType<Storage>(TypeID::get<Storage>());
168 template <
typename Storage>
172 auto *storage =
new (allocator.allocate<Storage>()) Storage();
177 registerSingletonImpl(
id, ctorFn);
179 template <
typename Storage>
181 registerSingletonStorageType<Storage>(
id, std::nullopt);
184 template <
typename Storage>
186 registerSingletonStorageType<Storage>(TypeID::get<Storage>(), initFn);
194 template <
typename Storage,
typename... Args>
198 auto derivedKey = getKey<Storage>(std::forward<Args>(args)...);
201 unsigned hashValue = getHash<Storage>(derivedKey);
204 auto isEqual = [&derivedKey](
const BaseStorage *existing) {
205 return static_cast<const Storage &
>(*existing) == derivedKey;
210 auto *storage = Storage::construct(allocator, std::move(derivedKey));
217 return static_cast<Storage *
>(
218 getParametricStorageTypeImpl(
id, hashValue, isEqual, ctorFn));
221 template <
typename Storage,
typename... Args>
223 return get<Storage>(initFn, TypeID::get<Storage>(),
224 std::forward<Args>(args)...);
229 template <
typename Storage>
231 return static_cast<Storage *
>(getSingletonImpl(
id));
234 template <
typename Storage>
236 return get<Storage>(TypeID::get<Storage>());
251 template <
typename Storage,
typename... Args>
254 return static_cast<Storage &
>(*storage).mutate(
255 allocator, std::forward<Args>(args)...);
257 return mutateImpl(
id, storage, mutationFn);
263 BaseStorage *getParametricStorageTypeImpl(
264 TypeID id,
unsigned hashValue,
266 function_ref<BaseStorage *(StorageAllocator &)> ctorFn);
271 void registerParametricStorageTypeImpl(
276 BaseStorage *getSingletonImpl(
TypeID id);
281 registerSingletonImpl(
TypeID id,
282 function_ref<BaseStorage *(StorageAllocator &)> ctorFn);
286 mutateImpl(
TypeID id, BaseStorage *storage,
287 function_ref<LogicalResult(StorageAllocator &)> mutationFn);
290 std::unique_ptr<detail::StorageUniquerImpl>
impl;
299 template <
typename ImplTy,
typename... Args>
300 static typename ImplTy::KeyTy getKey(Args &&...args) {
303 return ImplTy::getKey(std::forward<Args>(args)...);
305 return typename ImplTy::KeyTy(std::forward<Args>(args)...);
316 template <
typename ImplTy,
typename DerivedKey>
317 static ::llvm::hash_code getHash(
const DerivedKey &derivedKey) {
320 return ImplTy::hashKey(derivedKey);
322 return DenseMapInfo<DerivedKey>::getHashValue(derivedKey);
This class acts as the base storage that all storage classes must derived from.
This is a utility allocator used to allocate memory for instances of derived types.
void * allocate(size_t size, size_t alignment)
Allocate 'size' bytes of 'alignment' aligned memory.
StringRef copyInto(StringRef str)
Copy the provided string into memory managed by our bump pointer allocator.
ArrayRef< T > copyInto(ArrayRef< T > elements)
Copy the specified array of elements into memory managed by our bump pointer allocator.
bool allocated(const void *ptr)
Returns true if this allocator allocated the provided object pointer.
T * allocate()
Allocate an instance of the provided type.
A utility class to get or create instances of "storage classes".
void disableMultithreading(bool disable=true)
Set the flag specifying if multi-threading is disabled within the uniquer.
LogicalResult mutate(TypeID id, Storage *storage, Args &&...args)
Changes the mutable component of 'storage' by forwarding the trailing arguments to the 'mutate' funct...
Storage * get(function_ref< void(Storage *)> initFn, Args &&...args)
Utility override when the storage type represents the type id.
void registerSingletonStorageType(TypeID id, function_ref< void(Storage *)> initFn)
Register a new singleton storage class, this is necessary to get the singletone instance.
bool isSingletonStorageInitialized(TypeID id)
Test if there is a singleton storage uniquer initialized for the provided TypeID.
void registerParametricStorageType()
Utility override when the storage type represents the type id.
Storage * get(function_ref< void(Storage *)> initFn, TypeID id, Args &&...args)
Gets a uniqued instance of 'Storage'.
bool isParametricStorageInitialized(TypeID id)
Test if there is a parametric storage uniquer initialized for the provided TypeID.
Storage * get()
Utility override when the storage type represents the type id.
Storage * get(TypeID id)
Gets a uniqued instance of 'Storage' which is a singleton storage type.
void registerSingletonStorageType(function_ref< void(Storage *)> initFn={})
Utility override when the storage type represents the type id.
void registerSingletonStorageType(TypeID id)
void registerParametricStorageType(TypeID id)
Register a new parametric storage class, this is necessary to create instances of this class type.
This class provides an efficient unique identifier for a specific C++ type.
decltype(ImplTy::getKey(std::declval< Args >()...)) has_impltype_getkey_t
Trait to check if ImplTy provides a 'getKey' method with types 'Args'.
decltype(ImplTy::hashKey(std::declval< T >())) has_impltype_hash_t
Trait to check if ImplTy provides a 'hashKey' method for 'T'.
Include the generated interface declarations.