blob: 7961dd22d47ddca6375abd9d6e0c14577562bc83 [file] [log] [blame]
//===- TypeSupport.h --------------------------------------------*- 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 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 {
class Dialect;
class MLIRContext;
//===----------------------------------------------------------------------===//
// AbstractType
//===----------------------------------------------------------------------===//
/// This class contains all of the static information common to all instances of
/// a registered Type.
class AbstractType {
public:
/// Look up the specified abstract type in the MLIRContext and return a
/// reference to it.
static const AbstractType &lookup(TypeID typeID, MLIRContext *context);
/// This method is used by Dialect objects when they register the list of
/// types they contain.
template <typename T> static AbstractType get(Dialect &dialect) {
return AbstractType(dialect, T::getInterfaceMap());
}
/// Return the dialect this type was registered to.
Dialect &getDialect() const { return const_cast<Dialect &>(dialect); }
/// Returns an instance of the concept object for the given interface if it
/// was registered to this type, null otherwise. This should not be used
/// directly.
template <typename T> typename T::Concept *getInterface() const {
return interfaceMap.lookup<T>();
}
private:
AbstractType(Dialect &dialect, detail::InterfaceMap &&interfaceMap)
: dialect(dialect), interfaceMap(std::move(interfaceMap)) {}
/// This is the dialect that this type was registered to.
Dialect &dialect;
/// This is a collection of the interfaces registered to this type.
detail::InterfaceMap interfaceMap;
};
//===----------------------------------------------------------------------===//
// TypeStorage
//===----------------------------------------------------------------------===//
namespace detail {
struct TypeUniquer;
} // end namespace detail
/// Base storage class appearing in a Type.
class TypeStorage : public StorageUniquer::BaseStorage {
friend detail::TypeUniquer;
friend StorageUniquer;
public:
/// Return the abstract type descriptor for this type.
const AbstractType &getAbstractType() {
assert(abstractType && "Malformed type storage object.");
return *abstractType;
}
/// Get the subclass data.
unsigned getSubclassData() const { return subclassData; }
/// Set the subclass data.
void setSubclassData(unsigned val) { subclassData = val; }
protected:
/// This constructor is used by derived classes as part of the TypeUniquer.
TypeStorage(unsigned subclassData = 0)
: abstractType(nullptr), subclassData(subclassData) {}
private:
/// Set the abstract type for this storage instance. This is used by the
/// TypeUniquer when initializing a newly constructed type storage object.
void initialize(const AbstractType &abstractTy) {
abstractType = &abstractTy;
}
/// The abstract description for this type.
const AbstractType *abstractType;
/// 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.
struct TypeUniquer {
/// 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->initialize(AbstractType::lookup(T::getTypeID(), ctx));
},
kind, std::forward<Args>(args)...);
}
};
} // namespace detail
} // end namespace mlir
#endif