//===- StorageUniquer.h - Common Storage Class Uniquer ----------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef MLIR_SUPPORT_STORAGEUNIQUER_H #define MLIR_SUPPORT_STORAGEUNIQUER_H #include "mlir/Support/LLVM.h" #include "mlir/Support/TypeID.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include <utility> namespace mlir { namespace detail { struct StorageUniquerImpl; /// Trait to check if ImplTy provides a 'getKey' method with types 'Args'. has_impltype_getkey_t; /// Trait to check if ImplTy provides a 'hashKey' method for 'T'. has_impltype_hash_t; } // namespace detail /// A utility class to get or create instances of "storage classes". These /// storage classes must derive from 'StorageUniquer::BaseStorage'. /// /// For non-parametric storage classes, i.e. singleton classes, nothing else is /// needed. Instances of these classes can be created by calling `get` without /// trailing arguments. /// /// Otherwise, the parametric storage classes may be created with `get`, /// and must respect the following: /// - Define a type alias, KeyTy, to a type that uniquely identifies the /// instance of the storage class. /// * The key type must be constructible from the values passed into the /// getComplex call. /// * If the KeyTy does not have an llvm::DenseMapInfo specialization, the /// storage class must define a hashing method: /// 'static unsigned hashKey(const KeyTy &)' /// /// - Provide a method, 'bool operator==(const KeyTy &) const', to /// compare the storage instance against an instance of the key type. /// /// - Provide a static construction method: /// 'DerivedStorage *construct(StorageAllocator &, const KeyTy &key)' /// that builds a unique instance of the derived storage. The arguments to /// this function are an allocator to store any uniqued data and the key /// type for this storage. /// /// - Provide a cleanup method: /// 'void cleanup()' /// that is called when erasing a storage instance. This should cleanup any /// fields of the storage as necessary and not attempt to free the memory /// of the storage itself. /// /// Storage classes may have an optional mutable component, which must not take /// part in the unique immutable key. In this case, storage classes may be /// mutated with `mutate` and must additionally respect the following: /// - Provide a mutation method: /// 'LogicalResult mutate(StorageAllocator &, <...>)' /// that is called when mutating a storage instance. The first argument is /// an allocator to store any mutable data, and the remaining arguments are /// forwarded from the call site. The storage can be mutated at any time /// after creation. Care must be taken to avoid excessive mutation since /// the allocated storage can keep containing previous states. The return /// value of the function is used to indicate whether the mutation was /// successful, e.g., to limit the number of mutations or enable deferred /// one-time assignment of the mutable component. /// /// All storage classes must be registered with the uniquer via /// `registerParametricStorageType` or `registerSingletonStorageType` /// using an appropriate unique `TypeID` for the storage class. class StorageUniquer { … }; } // namespace mlir #endif