1 //===- TypeConverter.h - Convert builtin to LLVM dialect types --*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Provides a type converter configuration for converting most builtin types to
10 // LLVM dialect types.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_CONVERSION_LLVMCOMMON_TYPECONVERTER_H
15 #define MLIR_CONVERSION_LLVMCOMMON_TYPECONVERTER_H
16 
17 #include "mlir/Conversion/LLVMCommon/LoweringOptions.h"
18 #include "mlir/Transforms/DialectConversion.h"
19 
20 namespace mlir {
21 
22 class DataLayoutAnalysis;
23 class LowerToLLVMOptions;
24 
25 namespace LLVM {
26 class LLVMDialect;
27 } // namespace LLVM
28 
29 /// Conversion from types to the LLVM IR dialect.
30 class LLVMTypeConverter : public TypeConverter {
31   /// Give structFuncArgTypeConverter access to memref-specific functions.
32   friend LogicalResult
33   structFuncArgTypeConverter(LLVMTypeConverter &converter, Type type,
34                              SmallVectorImpl<Type> &result);
35 
36 public:
37   using TypeConverter::convertType;
38 
39   /// Create an LLVMTypeConverter using the default LowerToLLVMOptions.
40   /// Optionally takes a data layout analysis to use in conversions.
41   LLVMTypeConverter(MLIRContext *ctx,
42                     const DataLayoutAnalysis *analysis = nullptr);
43 
44   /// Create an LLVMTypeConverter using custom LowerToLLVMOptions. Optionally
45   /// takes a data layout analysis to use in conversions.
46   LLVMTypeConverter(MLIRContext *ctx, const LowerToLLVMOptions &options,
47                     const DataLayoutAnalysis *analysis = nullptr);
48 
49   /// Convert a function type.  The arguments and results are converted one by
50   /// one and results are packed into a wrapped LLVM IR structure type. `result`
51   /// is populated with argument mapping.
52   Type convertFunctionSignature(FunctionType funcTy, bool isVariadic,
53                                 SignatureConversion &result);
54 
55   /// Convert a non-empty list of types to be returned from a function into a
56   /// supported LLVM IR type.  In particular, if more than one value is
57   /// returned, create an LLVM IR structure type with elements that correspond
58   /// to each of the MLIR types converted with `convertType`.
59   Type packFunctionResults(TypeRange types);
60 
61   /// Convert a type in the context of the default or bare pointer calling
62   /// convention. Calling convention sensitive types, such as MemRefType and
63   /// UnrankedMemRefType, are converted following the specific rules for the
64   /// calling convention. Calling convention independent types are converted
65   /// following the default LLVM type conversions.
66   Type convertCallingConventionType(Type type);
67 
68   /// Promote the bare pointers in 'values' that resulted from memrefs to
69   /// descriptors. 'stdTypes' holds the types of 'values' before the conversion
70   /// to the LLVM-IR dialect (i.e., MemRefType, or any other builtin type).
71   void promoteBarePtrsToDescriptors(ConversionPatternRewriter &rewriter,
72                                     Location loc, ArrayRef<Type> stdTypes,
73                                     SmallVectorImpl<Value> &values);
74 
75   /// Returns the MLIR context.
76   MLIRContext &getContext();
77 
78   /// Returns the LLVM dialect.
getDialect()79   LLVM::LLVMDialect *getDialect() { return llvmDialect; }
80 
getOptions()81   const LowerToLLVMOptions &getOptions() const { return options; }
82 
83   /// Promote the LLVM representation of all operands including promoting MemRef
84   /// descriptors to stack and use pointers to struct to avoid the complexity
85   /// of the platform-specific C/C++ ABI lowering related to struct argument
86   /// passing.
87   SmallVector<Value, 4> promoteOperands(Location loc, ValueRange opOperands,
88                                         ValueRange operands,
89                                         OpBuilder &builder);
90 
91   /// Promote the LLVM struct representation of one MemRef descriptor to stack
92   /// and use pointer to struct to avoid the complexity of the platform-specific
93   /// C/C++ ABI lowering related to struct argument passing.
94   Value promoteOneMemRefDescriptor(Location loc, Value operand,
95                                    OpBuilder &builder);
96 
97   /// Converts the function type to a C-compatible format, in particular using
98   /// pointers to memref descriptors for arguments. Also converts the return
99   /// type to a pointer argument if it is a struct. Returns true if this
100   /// was the case.
101   std::pair<Type, bool> convertFunctionTypeCWrapper(FunctionType type);
102 
103   /// Returns the data layout to use during and after conversion.
getDataLayout()104   const llvm::DataLayout &getDataLayout() { return options.dataLayout; }
105 
106   /// Returns the data layout analysis to query during conversion.
getDataLayoutAnalysis()107   const DataLayoutAnalysis *getDataLayoutAnalysis() const {
108     return dataLayoutAnalysis;
109   }
110 
111   /// Gets the LLVM representation of the index type. The returned type is an
112   /// integer type with the size configured for this type converter.
113   Type getIndexType();
114 
115   /// Gets the bitwidth of the index type when converted to LLVM.
getIndexTypeBitwidth()116   unsigned getIndexTypeBitwidth() { return options.getIndexBitwidth(); }
117 
118   /// Gets the pointer bitwidth.
119   unsigned getPointerBitwidth(unsigned addressSpace = 0);
120 
121   /// Returns the size of the memref descriptor object in bytes.
122   unsigned getMemRefDescriptorSize(MemRefType type, const DataLayout &layout);
123 
124   /// Returns the size of the unranked memref descriptor object in bytes.
125   unsigned getUnrankedMemRefDescriptorSize(UnrankedMemRefType type,
126                                            const DataLayout &layout);
127 
128   /// Check if a memref type can be converted to a bare pointer.
129   bool canConvertToBarePtr(BaseMemRefType type);
130 
131 protected:
132   /// Pointer to the LLVM dialect.
133   LLVM::LLVMDialect *llvmDialect;
134 
135 private:
136   /// Convert a function type.  The arguments and results are converted one by
137   /// one.  Additionally, if the function returns more than one value, pack the
138   /// results into an LLVM IR structure type so that the converted function type
139   /// returns at most one result.
140   Type convertFunctionType(FunctionType type);
141 
142   /// Convert the index type.  Uses llvmModule data layout to create an integer
143   /// of the pointer bitwidth.
144   Type convertIndexType(IndexType type);
145 
146   /// Convert an integer type `i*` to `!llvm<"i*">`.
147   Type convertIntegerType(IntegerType type);
148 
149   /// Convert a floating point type: `f16` to `f16`, `f32` to
150   /// `f32` and `f64` to `f64`.  `bf16` is not supported
151   /// by LLVM.
152   Type convertFloatType(FloatType type);
153 
154   /// Convert complex number type: `complex<f16>` to `!llvm<"{ half, half }">`,
155   /// `complex<f32>` to `!llvm<"{ float, float }">`, and `complex<f64>` to
156   /// `!llvm<"{ double, double }">`. `complex<bf16>` is not supported.
157   Type convertComplexType(ComplexType type);
158 
159   /// Convert a memref type into an LLVM type that captures the relevant data.
160   Type convertMemRefType(MemRefType type);
161 
162   /// Convert a memref type into a list of LLVM IR types that will form the
163   /// memref descriptor. If `unpackAggregates` is true the `sizes` and `strides`
164   /// arrays in the descriptors are unpacked to individual index-typed elements,
165   /// else they are are kept as rank-sized arrays of index type. In particular,
166   /// the list will contain:
167   /// - two pointers to the memref element type, followed by
168   /// - an index-typed offset, followed by
169   /// - (if unpackAggregates = true)
170   ///    - one index-typed size per dimension of the memref, followed by
171   ///    - one index-typed stride per dimension of the memref.
172   /// - (if unpackArrregates = false)
173   ///   - one rank-sized array of index-type for the size of each dimension
174   ///   - one rank-sized array of index-type for the stride of each dimension
175   ///
176   /// For example, memref<?x?xf32> is converted to the following list:
177   /// - `!llvm<"float*">` (allocated pointer),
178   /// - `!llvm<"float*">` (aligned pointer),
179   /// - `i64` (offset),
180   /// - `i64`, `i64` (sizes),
181   /// - `i64`, `i64` (strides).
182   /// These types can be recomposed to a memref descriptor struct.
183   SmallVector<Type, 5> getMemRefDescriptorFields(MemRefType type,
184                                                  bool unpackAggregates);
185 
186   /// Convert an unranked memref type into a list of non-aggregate LLVM IR types
187   /// that will form the unranked memref descriptor. In particular, this list
188   /// contains:
189   /// - an integer rank, followed by
190   /// - a pointer to the memref descriptor struct.
191   /// For example, memref<*xf32> is converted to the following list:
192   /// i64 (rank)
193   /// !llvm<"i8*"> (type-erased pointer).
194   /// These types can be recomposed to a unranked memref descriptor struct.
195   SmallVector<Type, 2> getUnrankedMemRefDescriptorFields();
196 
197   /// Convert an unranked memref type to an LLVM type that captures the
198   /// runtime rank and a pointer to the static ranked memref desc
199   Type convertUnrankedMemRefType(UnrankedMemRefType type);
200 
201   /// Convert a memref type to a bare pointer to the memref element type.
202   Type convertMemRefToBarePtr(BaseMemRefType type);
203 
204   /// Convert a 1D vector type into an LLVM vector type.
205   Type convertVectorType(VectorType type);
206 
207   /// Options for customizing the llvm lowering.
208   LowerToLLVMOptions options;
209 
210   /// Data layout analysis mapping scopes to layouts active in them.
211   const DataLayoutAnalysis *dataLayoutAnalysis;
212 };
213 
214 /// Callback to convert function argument types. It converts a MemRef function
215 /// argument to a list of non-aggregate types containing descriptor
216 /// information, and an UnrankedmemRef function argument to a list containing
217 /// the rank and a pointer to a descriptor struct.
218 LogicalResult structFuncArgTypeConverter(LLVMTypeConverter &converter,
219                                          Type type,
220                                          SmallVectorImpl<Type> &result);
221 
222 /// Callback to convert function argument types. It converts MemRef function
223 /// arguments to bare pointers to the MemRef element type.
224 LogicalResult barePtrFuncArgTypeConverter(LLVMTypeConverter &converter,
225                                           Type type,
226                                           SmallVectorImpl<Type> &result);
227 
228 } // namespace mlir
229 
230 #endif // MLIR_CONVERSION_LLVMCOMMON_TYPECONVERTER_H
231