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"
25template <
typename ImplTy,
typename... Args>
29template <
typename ImplTy,
typename T>
101 auto result = allocator.Allocate<T>(elements.size());
102 llvm::uninitialized_copy(elements,
result);
112 char *
result = allocator.Allocate<
char>(str.size() + 1);
113 llvm::uninitialized_copy(str,
result);
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>
168 template <
typename Storage>
172 auto *storage =
new (allocator.allocate<Storage>()) Storage();
177 registerSingletonImpl(
id, ctorFn);
179 template <
typename Storage>
184 template <
typename Storage>
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>
224 std::forward<Args>(args)...);
229 template <
typename Storage>
231 return static_cast<Storage *
>(getSingletonImpl(
id));
234 template <
typename Storage>
270 template <
typename Storage,
typename... Args>
273 return static_cast<Storage &
>(*storage).mutate(
274 allocator, std::forward<Args>(args)...);
276 return mutateImpl(
id, storage, mutationFn);
282 BaseStorage *getParametricStorageTypeImpl(
283 TypeID id,
unsigned hashValue,
285 function_ref<BaseStorage *(StorageAllocator &)> ctorFn);
290 void registerParametricStorageTypeImpl(
295 BaseStorage *getSingletonImpl(
TypeID id);
300 registerSingletonImpl(
TypeID id,
301 function_ref<BaseStorage *(StorageAllocator &)> ctorFn);
305 mutateImpl(
TypeID id, BaseStorage *storage,
306 function_ref<LogicalResult(StorageAllocator &)> mutationFn);
309 std::unique_ptr<detail::StorageUniquerImpl>
impl;
318 template <
typename ImplTy,
typename... Args>
319 static typename ImplTy::KeyTy getKey(Args &&...args) {
322 return ImplTy::getKey(std::forward<Args>(args)...);
324 return typename ImplTy::KeyTy(std::forward<Args>(args)...);
335 template <
typename ImplTy,
typename DerivedKey>
336 static ::llvm::hash_code getHash(
const DerivedKey &derivedKey) {
339 return ImplTy::hashKey(derivedKey);
341 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.
ArrayRef< T > copyInto(ArrayRef< T > elements)
Copy the specified array of elements into memory managed by our bump pointer allocator.
T * allocate()
Allocate an instance of the provided type.
StringRef copyInto(StringRef str)
Copy the provided string into memory managed by our bump pointer allocator.
void * allocate(size_t size, size_t alignment)
Allocate 'size' bytes of 'alignment' aligned memory.
bool allocated(const void *ptr)
Returns true if this allocator allocated the provided object pointer.
bool isInTransientScope() const
Returns true if the uniquer is currently in a transient scope.
Storage * get(TypeID id)
Gets a uniqued instance of 'Storage' which is a singleton storage type.
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...
void registerSingletonStorageType(TypeID id, function_ref< void(Storage *)> initFn)
Register a new singleton storage class, this is necessary to get the singletone instance.
void beginTransientScope()
Begins a transient scope.
Storage * get(function_ref< void(Storage *)> initFn, Args &&...args)
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'.
Storage * get()
Utility override when the storage type represents the type id.
void endTransientScope()
Ends the transient scope and resets back to the base state, freeing all transiently allocated storage...
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.
bool isParametricStorageInitialized(TypeID id)
Test if there is a parametric storage uniquer initialized for the provided TypeID.
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.
static TypeID get()
Construct a type info object for the given type T.
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.
llvm::function_ref< Fn > function_ref
This is the implementation of the StorageUniquer class.