blob: 74f9c977b702860d284d6c87b94addb7786e1200 [file] [log] [blame]
//===- TypeConverter.h - Convert builtin to 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
//
//===----------------------------------------------------------------------===//
//
// Provides a type converter configuration for converting most builtin types to
// LLVM dialect types.
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_CONVERSION_LLVMCOMMON_TYPECONVERTER_H
#define MLIR_CONVERSION_LLVMCOMMON_TYPECONVERTER_H
#include "mlir/Conversion/LLVMCommon/LoweringOptions.h"
#include "mlir/Transforms/DialectConversion.h"
namespace mlir {
class DataLayoutAnalysis;
class LowerToLLVMOptions;
namespace LLVM {
class LLVMDialect;
class LLVMPointerType;
class LLVMFunctionType;
class LLVMStructType;
} // namespace LLVM
/// Conversion from types to the LLVM IR dialect.
class LLVMTypeConverter : public TypeConverter {
/// Give structFuncArgTypeConverter access to memref-specific functions.
friend LogicalResult
structFuncArgTypeConverter(const LLVMTypeConverter &converter, Type type,
SmallVectorImpl<Type> &result);
public:
using TypeConverter::convertType;
/// Create an LLVMTypeConverter using the default LowerToLLVMOptions.
/// Optionally takes a data layout analysis to use in conversions.
LLVMTypeConverter(MLIRContext *ctx,
const DataLayoutAnalysis *analysis = nullptr);
/// Create an LLVMTypeConverter using custom LowerToLLVMOptions. Optionally
/// takes a data layout analysis to use in conversions.
LLVMTypeConverter(MLIRContext *ctx, const LowerToLLVMOptions &options,
const DataLayoutAnalysis *analysis = nullptr);
/// Convert a function type. The arguments and results are converted one by
/// one and results are packed into a wrapped LLVM IR structure type. `result`
/// is populated with argument mapping.
Type convertFunctionSignature(FunctionType funcTy, bool isVariadic,
bool useBarePtrCallConv,
SignatureConversion &result) const;
/// Convert a non-empty list of types to be returned from a function into an
/// LLVM-compatible type. In particular, if more than one value is returned,
/// create an LLVM dialect structure type with elements that correspond to
/// each of the types converted with `convertCallingConventionType`.
Type packFunctionResults(TypeRange types,
bool useBarePointerCallConv = false) const;
/// Convert a non-empty list of types of values produced by an operation into
/// an LLVM-compatible type. In particular, if more than one value is
/// produced, create a literal structure with elements that correspond to each
/// of the LLVM-compatible types converted with `convertType`.
Type packOperationResults(TypeRange types) const;
/// Convert a type in the context of the default or bare pointer calling
/// convention. Calling convention sensitive types, such as MemRefType and
/// UnrankedMemRefType, are converted following the specific rules for the
/// calling convention. Calling convention independent types are converted
/// following the default LLVM type conversions.
Type convertCallingConventionType(Type type,
bool useBarePointerCallConv = false) const;
/// Promote the bare pointers in 'values' that resulted from memrefs to
/// descriptors. 'stdTypes' holds the types of 'values' before the conversion
/// to the LLVM-IR dialect (i.e., MemRefType, or any other builtin type).
void promoteBarePtrsToDescriptors(ConversionPatternRewriter &rewriter,
Location loc, ArrayRef<Type> stdTypes,
SmallVectorImpl<Value> &values) const;
/// Returns the MLIR context.
MLIRContext &getContext() const;
/// Returns the LLVM dialect.
LLVM::LLVMDialect *getDialect() const { return llvmDialect; }
const LowerToLLVMOptions &getOptions() const { return options; }
/// Promote the LLVM representation of all operands including promoting MemRef
/// descriptors to stack and use pointers to struct to avoid the complexity
/// of the platform-specific C/C++ ABI lowering related to struct argument
/// passing.
SmallVector<Value, 4> promoteOperands(Location loc, ValueRange opOperands,
ValueRange operands, OpBuilder &builder,
bool useBarePtrCallConv = false) const;
/// Promote the LLVM struct representation of one MemRef descriptor to stack
/// and use pointer to struct to avoid the complexity of the platform-specific
/// C/C++ ABI lowering related to struct argument passing.
Value promoteOneMemRefDescriptor(Location loc, Value operand,
OpBuilder &builder) const;
/// Converts the function type to a C-compatible format, in particular using
/// pointers to memref descriptors for arguments. Also converts the return
/// type to a pointer argument if it is a struct. Returns true if this
/// was the case.
std::pair<LLVM::LLVMFunctionType, LLVM::LLVMStructType>
convertFunctionTypeCWrapper(FunctionType type) const;
/// Returns the data layout to use during and after conversion.
const llvm::DataLayout &getDataLayout() const { return options.dataLayout; }
/// Returns the data layout analysis to query during conversion.
const DataLayoutAnalysis *getDataLayoutAnalysis() const {
return dataLayoutAnalysis;
}
/// Gets the LLVM representation of the index type. The returned type is an
/// integer type with the size configured for this type converter.
Type getIndexType() const;
/// Gets the bitwidth of the index type when converted to LLVM.
unsigned getIndexTypeBitwidth() const { return options.getIndexBitwidth(); }
/// Gets the pointer bitwidth.
unsigned getPointerBitwidth(unsigned addressSpace = 0) const;
/// Returns the size of the memref descriptor object in bytes.
unsigned getMemRefDescriptorSize(MemRefType type,
const DataLayout &layout) const;
/// Returns the size of the unranked memref descriptor object in bytes.
unsigned getUnrankedMemRefDescriptorSize(UnrankedMemRefType type,
const DataLayout &layout) const;
/// Return the LLVM address space corresponding to the memory space of the
/// memref type `type` or failure if the memory space cannot be converted to
/// an integer.
FailureOr<unsigned> getMemRefAddressSpace(BaseMemRefType type) const;
/// Check if a memref type can be converted to a bare pointer.
static bool canConvertToBarePtr(BaseMemRefType type);
protected:
/// Pointer to the LLVM dialect.
LLVM::LLVMDialect *llvmDialect;
// Recursive structure detection.
// We store one entry per thread here, and rely on locking.
DenseMap<uint64_t, std::unique_ptr<SmallVector<Type>>> conversionCallStack;
llvm::sys::SmartRWMutex<true> callStackMutex;
SmallVector<Type> &getCurrentThreadRecursiveStack();
private:
/// Convert a function type. The arguments and results are converted one by
/// one. Additionally, if the function returns more than one value, pack the
/// results into an LLVM IR structure type so that the converted function type
/// returns at most one result.
Type convertFunctionType(FunctionType type) const;
/// Convert the index type. Uses llvmModule data layout to create an integer
/// of the pointer bitwidth.
Type convertIndexType(IndexType type) const;
/// Convert an integer type `i*` to `!llvm<"i*">`.
Type convertIntegerType(IntegerType type) const;
/// Convert a floating point type: `f16` to `f16`, `f32` to
/// `f32` and `f64` to `f64`. `bf16` is not supported
/// by LLVM. 8-bit float types are converted to 8-bit integers as this is how
/// all LLVM backends that support them currently represent them.
Type convertFloatType(FloatType type) const;
/// Convert complex number type: `complex<f16>` to `!llvm<"{ half, half }">`,
/// `complex<f32>` to `!llvm<"{ float, float }">`, and `complex<f64>` to
/// `!llvm<"{ double, double }">`. `complex<bf16>` is not supported.
Type convertComplexType(ComplexType type) const;
/// Convert a memref type into an LLVM type that captures the relevant data.
Type convertMemRefType(MemRefType type) const;
/// Convert a memref type into a list of LLVM IR types that will form the
/// memref descriptor. If `unpackAggregates` is true the `sizes` and `strides`
/// arrays in the descriptors are unpacked to individual index-typed elements,
/// else they are kept as rank-sized arrays of index type. In particular,
/// the list will contain:
/// - two pointers to the memref element type, followed by
/// - an index-typed offset, followed by
/// - (if unpackAggregates = true)
/// - one index-typed size per dimension of the memref, followed by
/// - one index-typed stride per dimension of the memref.
/// - (if unpackArrregates = false)
/// - one rank-sized array of index-type for the size of each dimension
/// - one rank-sized array of index-type for the stride of each dimension
///
/// For example, memref<?x?xf32> is converted to the following list:
/// - `!llvm<"float*">` (allocated pointer),
/// - `!llvm<"float*">` (aligned pointer),
/// - `i64` (offset),
/// - `i64`, `i64` (sizes),
/// - `i64`, `i64` (strides).
/// These types can be recomposed to a memref descriptor struct.
SmallVector<Type, 5> getMemRefDescriptorFields(MemRefType type,
bool unpackAggregates) const;
/// Convert an unranked memref type into a list of non-aggregate LLVM IR types
/// that will form the unranked memref descriptor. In particular, this list
/// contains:
/// - an integer rank, followed by
/// - a pointer to the memref descriptor struct.
/// For example, memref<*xf32> is converted to the following list:
/// i64 (rank)
/// !llvm<"i8*"> (type-erased pointer).
/// These types can be recomposed to a unranked memref descriptor struct.
SmallVector<Type, 2> getUnrankedMemRefDescriptorFields() const;
/// Convert an unranked memref type to an LLVM type that captures the
/// runtime rank and a pointer to the static ranked memref desc
Type convertUnrankedMemRefType(UnrankedMemRefType type) const;
/// Convert a memref type to a bare pointer to the memref element type.
Type convertMemRefToBarePtr(BaseMemRefType type) const;
/// Convert a 1D vector type into an LLVM vector type.
FailureOr<Type> convertVectorType(VectorType type) const;
/// Options for customizing the llvm lowering.
LowerToLLVMOptions options;
/// Data layout analysis mapping scopes to layouts active in them.
const DataLayoutAnalysis *dataLayoutAnalysis;
};
/// Callback to convert function argument types. It converts a MemRef function
/// argument to a list of non-aggregate types containing descriptor
/// information, and an UnrankedmemRef function argument to a list containing
/// the rank and a pointer to a descriptor struct.
LogicalResult structFuncArgTypeConverter(const LLVMTypeConverter &converter,
Type type,
SmallVectorImpl<Type> &result);
/// Callback to convert function argument types. It converts MemRef function
/// arguments to bare pointers to the MemRef element type.
LogicalResult barePtrFuncArgTypeConverter(const LLVMTypeConverter &converter,
Type type,
SmallVectorImpl<Type> &result);
} // namespace mlir
#endif // MLIR_CONVERSION_LLVMCOMMON_TYPECONVERTER_H