llvm/mlir/include/mlir/IR/StorageUniquerSupport.h

//===- StorageUniquerSupport.h - MLIR Storage Uniquer Utilities -*- 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
//
//===----------------------------------------------------------------------===//
//
// This file defines utility classes for interfacing with StorageUniquer.
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_IR_STORAGEUNIQUERSUPPORT_H
#define MLIR_IR_STORAGEUNIQUERSUPPORT_H

#include "mlir/IR/AttrTypeSubElements.h"
#include "mlir/IR/DialectRegistry.h"
#include "mlir/Support/InterfaceSupport.h"
#include "mlir/Support/StorageUniquer.h"
#include "mlir/Support/TypeID.h"
#include "llvm/ADT/FunctionExtras.h"

namespace mlir {
class InFlightDiagnostic;
class Location;
class MLIRContext;

namespace detail {
/// Utility method to generate a callback that can be used to generate a
/// diagnostic when checking the construction invariants of a storage object.
/// This is defined out-of-line to avoid the need to include Location.h.
llvm::unique_function<InFlightDiagnostic()>
getDefaultDiagnosticEmitFn(MLIRContext *ctx);
llvm::unique_function<InFlightDiagnostic()>
getDefaultDiagnosticEmitFn(const Location &loc);

//===----------------------------------------------------------------------===//
// StorageUserTraitBase
//===----------------------------------------------------------------------===//

/// Helper class for implementing traits for storage classes. Clients are not
/// expected to interact with this directly, so its members are all protected.
template <typename ConcreteType, template <typename> class TraitType>
class StorageUserTraitBase {};

namespace StorageUserTrait {
/// This trait is used to determine if a storage user, like Type, is mutable
/// or not. A storage user is mutable if ImplType of the derived class defines
/// a `mutate` function with a proper signature. Note that this trait is not
/// supposed to be used publicly. Users should use alias names like
/// `TypeTrait::IsMutable` instead.
template <typename ConcreteType>
struct IsMutable : public StorageUserTraitBase<ConcreteType, IsMutable> {};
} // namespace StorageUserTrait

//===----------------------------------------------------------------------===//
// StorageUserBase
//===----------------------------------------------------------------------===//

namespace storage_user_base_impl {
/// Returns true if this given Trait ID matches the IDs of any of the provided
/// trait types `Traits`.
template <template <typename T> class... Traits>
bool hasTrait(TypeID traitID) {}

// We specialize for the empty case to not define an empty array.
template <>
inline bool hasTrait(TypeID traitID) {}
} // namespace storage_user_base_impl

/// Utility class for implementing users of storage classes uniqued by a
/// StorageUniquer. Clients are not expected to interact with this class
/// directly.
template <typename ConcreteT, typename BaseT, typename StorageT,
          typename UniquerT, template <typename T> class... Traits>
class StorageUserBase : public BaseT, public Traits<ConcreteT>... {};
} // namespace detail
} // namespace mlir

#endif