blob: 3de4f3ab60dbe5c8319ef29fdea5baa101734813 [file] [log] [blame]
//===- LLVMDialect.h - MLIR LLVM dialect types ------------------*- 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 the types for the LLVM dialect in MLIR. These MLIR types
// correspond to the LLVM IR type system.
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_DIALECT_LLVMIR_LLVMTYPES_H_
#define MLIR_DIALECT_LLVMIR_LLVMTYPES_H_
#include "mlir/IR/Types.h"
#include "mlir/Interfaces/DataLayoutInterfaces.h"
namespace llvm {
class ElementCount;
class TypeSize;
} // namespace llvm
namespace mlir {
class AsmParser;
class AsmPrinter;
namespace LLVM {
class LLVMDialect;
namespace detail {
struct LLVMFunctionTypeStorage;
struct LLVMPointerTypeStorage;
struct LLVMStructTypeStorage;
struct LLVMTypeAndSizeStorage;
} // namespace detail
} // namespace LLVM
} // namespace mlir
#include "mlir/Dialect/LLVMIR/LLVMTypeInterfaces.h.inc"
namespace mlir {
namespace LLVM {
//===----------------------------------------------------------------------===//
// Trivial types.
//===----------------------------------------------------------------------===//
// Batch-define trivial types.
#define DEFINE_TRIVIAL_LLVM_TYPE(ClassName) \
class ClassName : public Type::TypeBase<ClassName, Type, TypeStorage> { \
public: \
using Base::Base; \
}
DEFINE_TRIVIAL_LLVM_TYPE(LLVMVoidType);
DEFINE_TRIVIAL_LLVM_TYPE(LLVMPPCFP128Type);
DEFINE_TRIVIAL_LLVM_TYPE(LLVMX86MMXType);
DEFINE_TRIVIAL_LLVM_TYPE(LLVMTokenType);
DEFINE_TRIVIAL_LLVM_TYPE(LLVMLabelType);
DEFINE_TRIVIAL_LLVM_TYPE(LLVMMetadataType);
#undef DEFINE_TRIVIAL_LLVM_TYPE
//===----------------------------------------------------------------------===//
// LLVMArrayType.
//===----------------------------------------------------------------------===//
/// LLVM dialect array type. It is an aggregate type representing consecutive
/// elements in memory, parameterized by the number of elements and the element
/// type.
class LLVMArrayType : public Type::TypeBase<LLVMArrayType, Type,
detail::LLVMTypeAndSizeStorage> {
public:
/// Inherit base constructors.
using Base::Base;
using Base::getChecked;
/// Checks if the given type can be used inside an array type.
static bool isValidElementType(Type type);
/// Gets or creates an instance of LLVM dialect array type containing
/// `numElements` of `elementType`, in the same context as `elementType`.
static LLVMArrayType get(Type elementType, unsigned numElements);
static LLVMArrayType getChecked(function_ref<InFlightDiagnostic()> emitError,
Type elementType, unsigned numElements);
/// Returns the element type of the array.
Type getElementType();
/// Returns the number of elements in the array type.
unsigned getNumElements();
/// Verifies that the type about to be constructed is well-formed.
static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
Type elementType, unsigned numElements);
};
//===----------------------------------------------------------------------===//
// LLVMFunctionType.
//===----------------------------------------------------------------------===//
/// LLVM dialect function type. It consists of a single return type (unlike MLIR
/// which can have multiple), a list of parameter types and can optionally be
/// variadic.
class LLVMFunctionType
: public Type::TypeBase<LLVMFunctionType, Type,
detail::LLVMFunctionTypeStorage> {
public:
/// Inherit base constructors.
using Base::Base;
using Base::getChecked;
/// Checks if the given type can be used an argument in a function type.
static bool isValidArgumentType(Type type);
/// Checks if the given type can be used as a result in a function type.
static bool isValidResultType(Type type);
/// Returns whether the function is variadic.
bool isVarArg();
/// Gets or creates an instance of LLVM dialect function in the same context
/// as the `result` type.
static LLVMFunctionType get(Type result, ArrayRef<Type> arguments,
bool isVarArg = false);
static LLVMFunctionType
getChecked(function_ref<InFlightDiagnostic()> emitError, Type result,
ArrayRef<Type> arguments, bool isVarArg = false);
/// Returns the result type of the function.
Type getReturnType();
/// Returns the number of arguments to the function.
unsigned getNumParams();
/// Returns `i`-th argument of the function. Asserts on out-of-bounds.
Type getParamType(unsigned i);
/// Returns a list of argument types of the function.
ArrayRef<Type> getParams();
ArrayRef<Type> params() { return getParams(); }
/// Verifies that the type about to be constructed is well-formed.
static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
Type result, ArrayRef<Type> arguments, bool);
};
//===----------------------------------------------------------------------===//
// LLVMPointerType.
//===----------------------------------------------------------------------===//
/// LLVM dialect pointer type. This type typically represents a reference to an
/// object in memory. It is parameterized by the element type and the address
/// space.
class LLVMPointerType : public Type::TypeBase<LLVMPointerType, Type,
detail::LLVMPointerTypeStorage,
DataLayoutTypeInterface::Trait> {
public:
/// Inherit base constructors.
using Base::Base;
using Base::getChecked;
/// Checks if the given type can have a pointer type pointing to it.
static bool isValidElementType(Type type);
/// Gets or creates an instance of LLVM dialect pointer type pointing to an
/// object of `pointee` type in the given address space. The pointer type is
/// created in the same context as `pointee`.
static LLVMPointerType get(Type pointee, unsigned addressSpace = 0);
static LLVMPointerType
getChecked(function_ref<InFlightDiagnostic()> emitError, Type pointee,
unsigned addressSpace = 0);
/// Returns the pointed-to type.
Type getElementType() const;
/// Returns the address space of the pointer.
unsigned getAddressSpace() const;
/// Verifies that the type about to be constructed is well-formed.
static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
Type pointee, unsigned);
/// Hooks for DataLayoutTypeInterface. Should not be called directly. Obtain a
/// DataLayout instance and query it instead.
unsigned getTypeSizeInBits(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const;
unsigned getABIAlignment(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const;
unsigned getPreferredAlignment(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const;
bool areCompatible(DataLayoutEntryListRef oldLayout,
DataLayoutEntryListRef newLayout) const;
LogicalResult verifyEntries(DataLayoutEntryListRef entries,
Location loc) const;
};
//===----------------------------------------------------------------------===//
// LLVMStructType.
//===----------------------------------------------------------------------===//
/// LLVM dialect structure type representing a collection of different-typed
/// elements manipulated together. Structured can optionally be packed, meaning
/// that their elements immediately follow each other in memory without
/// accounting for potential alignment.
///
/// Structure types can be identified (named) or literal. Literal structures
/// are uniquely represented by the list of types they contain and packedness.
/// Literal structure types are immutable after construction.
///
/// Identified structures are uniquely represented by their name, a string. They
/// have a mutable component, consisting of the list of types they contain,
/// the packedness and the opacity bits. Identified structs can be created
/// without providing the lists of element types, making them suitable to
/// represent recursive, i.e. self-referring, structures. Identified structs
/// without body are considered opaque. For such structs, one can set the body.
/// Identified structs can be created as intentionally-opaque, implying that the
/// caller does not intend to ever set the body (e.g. forward-declarations of
/// structs from another module) and wants to disallow further modification of
/// the body. For intentionally-opaque structs or non-opaque structs with the
/// body, one is not allowed to set another body (however, one can set exactly
/// the same body).
///
/// Note that the packedness of the struct takes place in uniquing of literal
/// structs, but does not in uniquing of identified structs.
class LLVMStructType : public Type::TypeBase<LLVMStructType, Type,
detail::LLVMStructTypeStorage> {
public:
/// Inherit base constructors.
using Base::Base;
/// Checks if the given type can be contained in a structure type.
static bool isValidElementType(Type type);
/// Gets or creates an identified struct with the given name in the provided
/// context. Note that unlike llvm::StructType::create, this function will
/// _NOT_ rename a struct in case a struct with the same name already exists
/// in the context. Instead, it will just return the existing struct,
/// similarly to the rest of MLIR type ::get methods.
static LLVMStructType getIdentified(MLIRContext *context, StringRef name);
static LLVMStructType
getIdentifiedChecked(function_ref<InFlightDiagnostic()> emitError,
MLIRContext *context, StringRef name);
/// Gets a new identified struct with the given body. The body _cannot_ be
/// changed later. If a struct with the given name already exists, renames
/// the struct by appending a `.` followed by a number to the name. Renaming
/// happens even if the existing struct has the same body.
static LLVMStructType getNewIdentified(MLIRContext *context, StringRef name,
ArrayRef<Type> elements,
bool isPacked = false);
/// Gets or creates a literal struct with the given body in the provided
/// context.
static LLVMStructType getLiteral(MLIRContext *context, ArrayRef<Type> types,
bool isPacked = false);
static LLVMStructType
getLiteralChecked(function_ref<InFlightDiagnostic()> emitError,
MLIRContext *context, ArrayRef<Type> types,
bool isPacked = false);
/// Gets or creates an intentionally-opaque identified struct. Such a struct
/// cannot have its body set. To create an opaque struct with a mutable body,
/// use `getIdentified`. Note that unlike llvm::StructType::create, this
/// function will _NOT_ rename a struct in case a struct with the same name
/// already exists in the context. Instead, it will just return the existing
/// struct, similarly to the rest of MLIR type ::get methods.
static LLVMStructType getOpaque(StringRef name, MLIRContext *context);
static LLVMStructType
getOpaqueChecked(function_ref<InFlightDiagnostic()> emitError,
MLIRContext *context, StringRef name);
/// Set the body of an identified struct. Returns failure if the body could
/// not be set, e.g. if the struct already has a body or if it was marked as
/// intentionally opaque. This might happen in a multi-threaded context when a
/// different thread modified the struct after it was created. Most callers
/// are likely to assert this always succeeds, but it is possible to implement
/// a local renaming scheme based on the result of this call.
LogicalResult setBody(ArrayRef<Type> types, bool isPacked);
/// Checks if a struct is packed.
bool isPacked();
/// Checks if a struct is identified.
bool isIdentified();
/// Checks if a struct is opaque.
bool isOpaque();
/// Checks if a struct is initialized.
bool isInitialized();
/// Returns the name of an identified struct.
StringRef getName();
/// Returns the list of element types contained in a non-opaque struct.
ArrayRef<Type> getBody();
/// Verifies that the type about to be constructed is well-formed.
static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
StringRef, bool);
static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
ArrayRef<Type> types, bool);
};
//===----------------------------------------------------------------------===//
// LLVMVectorType.
//===----------------------------------------------------------------------===//
/// LLVM dialect vector type, represents a sequence of elements that can be
/// processed as one, typically in SIMD context. This is a base class for fixed
/// and scalable vectors.
class LLVMVectorType : public Type {
public:
/// Inherit base constructor.
using Type::Type;
/// Support type casting functionality.
static bool classof(Type type);
/// Checks if the given type can be used in a vector type.
static bool isValidElementType(Type type);
/// Returns the element type of the vector.
Type getElementType();
/// Returns the number of elements in the vector.
llvm::ElementCount getElementCount();
/// Verifies that the type about to be constructed is well-formed.
static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
Type elementType, unsigned numElements);
};
//===----------------------------------------------------------------------===//
// LLVMFixedVectorType.
//===----------------------------------------------------------------------===//
/// LLVM dialect fixed vector type, represents a sequence of elements of known
/// length that can be processed as one.
class LLVMFixedVectorType
: public Type::TypeBase<LLVMFixedVectorType, Type,
detail::LLVMTypeAndSizeStorage> {
public:
/// Inherit base constructor.
using Base::Base;
using Base::getChecked;
/// Gets or creates a fixed vector type containing `numElements` of
/// `elementType` in the same context as `elementType`.
static LLVMFixedVectorType get(Type elementType, unsigned numElements);
static LLVMFixedVectorType
getChecked(function_ref<InFlightDiagnostic()> emitError, Type elementType,
unsigned numElements);
/// Checks if the given type can be used in a vector type. This type supports
/// only a subset of LLVM dialect types that don't have a built-in
/// counter-part, e.g., pointers.
static bool isValidElementType(Type type);
/// Returns the element type of the vector.
Type getElementType();
/// Returns the number of elements in the fixed vector.
unsigned getNumElements();
/// Verifies that the type about to be constructed is well-formed.
static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
Type elementType, unsigned numElements);
};
//===----------------------------------------------------------------------===//
// LLVMScalableVectorType.
//===----------------------------------------------------------------------===//
/// LLVM dialect scalable vector type, represents a sequence of elements of
/// unknown length that is known to be divisible by some constant. These
/// elements can be processed as one in SIMD context.
class LLVMScalableVectorType
: public Type::TypeBase<LLVMScalableVectorType, Type,
detail::LLVMTypeAndSizeStorage> {
public:
/// Inherit base constructor.
using Base::Base;
using Base::getChecked;
/// Gets or creates a scalable vector type containing a non-zero multiple of
/// `minNumElements` of `elementType` in the same context as `elementType`.
static LLVMScalableVectorType get(Type elementType, unsigned minNumElements);
static LLVMScalableVectorType
getChecked(function_ref<InFlightDiagnostic()> emitError, Type elementType,
unsigned minNumElements);
/// Checks if the given type can be used in a vector type.
static bool isValidElementType(Type type);
/// Returns the element type of the vector.
Type getElementType();
/// Returns the scaling factor of the number of elements in the vector. The
/// vector contains at least the resulting number of elements, or any non-zero
/// multiple of this number.
unsigned getMinNumElements();
/// Verifies that the type about to be constructed is well-formed.
static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
Type elementType, unsigned minNumElements);
};
//===----------------------------------------------------------------------===//
// Printing and parsing.
//===----------------------------------------------------------------------===//
namespace detail {
/// Parses an LLVM dialect type.
Type parseType(DialectAsmParser &parser);
/// Prints an LLVM Dialect type.
void printType(Type type, AsmPrinter &printer);
} // namespace detail
//===----------------------------------------------------------------------===//
// Utility functions.
//===----------------------------------------------------------------------===//
/// Returns `true` if the given type is compatible with the LLVM dialect.
bool isCompatibleType(Type type);
/// Returns `true` if the given type is a floating-point type compatible with
/// the LLVM dialect.
bool isCompatibleFloatingPointType(Type type);
/// Returns `true` if the given type is a vector type compatible with the LLVM
/// dialect. Compatible types include 1D built-in vector types of built-in
/// integers and floating-point values, LLVM dialect fixed vector types of LLVM
/// dialect pointers and LLVM dialect scalable vector types.
bool isCompatibleVectorType(Type type);
/// Returns the element type of any vector type compatible with the LLVM
/// dialect.
Type getVectorElementType(Type type);
/// Returns the element count of any LLVM-compatible vector type.
llvm::ElementCount getVectorNumElements(Type type);
/// Creates an LLVM dialect-compatible type with the given element type and
/// length.
Type getFixedVectorType(Type elementType, unsigned numElements);
/// Returns the size of the given primitive LLVM dialect-compatible type
/// (including vectors) in bits, for example, the size of i16 is 16 and
/// the size of vector<4xi16> is 64. Returns 0 for non-primitive
/// (aggregates such as struct) or types that don't have a size (such as void).
llvm::TypeSize getPrimitiveTypeSizeInBits(Type type);
} // namespace LLVM
} // namespace mlir
#endif // MLIR_DIALECT_LLVMIR_LLVMTYPES_H_