blob: 8cc811cb916db7b64d25eb5ed5dbcd9cece55725 [file] [log] [blame]
//===- TypeSupport.h --------------------------------------------*- C++ -*-===//
//
// Part of the MLIR 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 support types for registering dialect extended types.
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_IR_TYPE_SUPPORT_H
#define MLIR_IR_TYPE_SUPPORT_H
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/StorageUniquerSupport.h"
namespace mlir {
struct ClassID;
class Dialect;
class MLIRContext;
//===----------------------------------------------------------------------===//
// TypeStorage
//===----------------------------------------------------------------------===//
namespace detail {
class TypeUniquer;
} // end namespace detail
/// Base storage class appearing in a Type.
class TypeStorage : public StorageUniquer::BaseStorage {
friend detail::TypeUniquer;
friend StorageUniquer;
protected:
/// This constructor is used by derived classes as part of the TypeUniquer.
/// When using this constructor, the initializeTypeInfo function must be
/// invoked afterwards for the storage to be valid.
TypeStorage(unsigned subclassData = 0)
: dialect(nullptr), subclassData(subclassData) {}
public:
/// Get the dialect that this type is registered to.
Dialect &getDialect() {
assert(dialect && "Malformed type storage object.");
return *dialect;
}
/// Get the subclass data.
unsigned getSubclassData() const { return subclassData; }
/// Set the subclass data.
void setSubclassData(unsigned val) { subclassData = val; }
private:
// Set the dialect for this storage instance. This is used by the TypeUniquer
// when initializing a newly constructed type storage object.
void initializeDialect(Dialect &newDialect) { dialect = &newDialect; }
/// The dialect for this type.
Dialect *dialect;
/// Space for subclasses to store data.
unsigned subclassData;
};
/// Default storage type for types that require no additional initialization or
/// storage.
using DefaultTypeStorage = TypeStorage;
//===----------------------------------------------------------------------===//
// TypeStorageAllocator
//===----------------------------------------------------------------------===//
// This is a utility allocator used to allocate memory for instances of derived
// Types.
using TypeStorageAllocator = StorageUniquer::StorageAllocator;
//===----------------------------------------------------------------------===//
// TypeUniquer
//===----------------------------------------------------------------------===//
namespace detail {
// A utility class to get, or create, unique instances of types within an
// MLIRContext. This class manages all creation and uniquing of types.
class TypeUniquer {
public:
/// Get an uniqued instance of a type T.
template <typename T, typename... Args>
static T get(MLIRContext *ctx, unsigned kind, Args &&... args) {
return ctx->getTypeUniquer().get<typename T::ImplType>(
[&](TypeStorage *storage) {
storage->initializeDialect(lookupDialectForType<T>(ctx));
},
kind, std::forward<Args>(args)...);
}
private:
/// Get the dialect that the type 'T' was registered with.
template <typename T> static Dialect &lookupDialectForType(MLIRContext *ctx) {
return lookupDialectForType(ctx, T::getClassID());
}
/// Get the dialect that registered the type with the provided typeid.
static Dialect &lookupDialectForType(MLIRContext *ctx,
const ClassID *const typeID);
};
} // namespace detail
} // end namespace mlir
#endif