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 in the Standard dialect 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 protected:
129   /// Pointer to the LLVM dialect.
130   LLVM::LLVMDialect *llvmDialect;
131 
132 private:
133   /// Convert a function type.  The arguments and results are converted one by
134   /// one.  Additionally, if the function returns more than one value, pack the
135   /// results into an LLVM IR structure type so that the converted function type
136   /// returns at most one result.
137   Type convertFunctionType(FunctionType type);
138 
139   /// Convert the index type.  Uses llvmModule data layout to create an integer
140   /// of the pointer bitwidth.
141   Type convertIndexType(IndexType type);
142 
143   /// Convert an integer type `i*` to `!llvm<"i*">`.
144   Type convertIntegerType(IntegerType type);
145 
146   /// Convert a floating point type: `f16` to `f16`, `f32` to
147   /// `f32` and `f64` to `f64`.  `bf16` is not supported
148   /// by LLVM.
149   Type convertFloatType(FloatType type);
150 
151   /// Convert complex number type: `complex<f16>` to `!llvm<"{ half, half }">`,
152   /// `complex<f32>` to `!llvm<"{ float, float }">`, and `complex<f64>` to
153   /// `!llvm<"{ double, double }">`. `complex<bf16>` is not supported.
154   Type convertComplexType(ComplexType type);
155 
156   /// Convert a memref type into an LLVM type that captures the relevant data.
157   Type convertMemRefType(MemRefType type);
158 
159   /// Convert a memref type into a list of LLVM IR types that will form the
160   /// memref descriptor. If `unpackAggregates` is true the `sizes` and `strides`
161   /// arrays in the descriptors are unpacked to individual index-typed elements,
162   /// else they are are kept as rank-sized arrays of index type. In particular,
163   /// the list will contain:
164   /// - two pointers to the memref element type, followed by
165   /// - an index-typed offset, followed by
166   /// - (if unpackAggregates = true)
167   ///    - one index-typed size per dimension of the memref, followed by
168   ///    - one index-typed stride per dimension of the memref.
169   /// - (if unpackArrregates = false)
170   ///   - one rank-sized array of index-type for the size of each dimension
171   ///   - one rank-sized array of index-type for the stride of each dimension
172   ///
173   /// For example, memref<?x?xf32> is converted to the following list:
174   /// - `!llvm<"float*">` (allocated pointer),
175   /// - `!llvm<"float*">` (aligned pointer),
176   /// - `i64` (offset),
177   /// - `i64`, `i64` (sizes),
178   /// - `i64`, `i64` (strides).
179   /// These types can be recomposed to a memref descriptor struct.
180   SmallVector<Type, 5> getMemRefDescriptorFields(MemRefType type,
181                                                  bool unpackAggregates);
182 
183   /// Convert an unranked memref type into a list of non-aggregate LLVM IR types
184   /// that will form the unranked memref descriptor. In particular, this list
185   /// contains:
186   /// - an integer rank, followed by
187   /// - a pointer to the memref descriptor struct.
188   /// For example, memref<*xf32> is converted to the following list:
189   /// i64 (rank)
190   /// !llvm<"i8*"> (type-erased pointer).
191   /// These types can be recomposed to a unranked memref descriptor struct.
192   SmallVector<Type, 2> getUnrankedMemRefDescriptorFields();
193 
194   // Convert an unranked memref type to an LLVM type that captures the
195   // runtime rank and a pointer to the static ranked memref desc
196   Type convertUnrankedMemRefType(UnrankedMemRefType type);
197 
198   /// Convert a memref type to a bare pointer to the memref element type.
199   Type convertMemRefToBarePtr(BaseMemRefType type);
200 
201   /// Convert a 1D vector type into an LLVM vector type.
202   Type convertVectorType(VectorType type);
203 
204   /// Options for customizing the llvm lowering.
205   LowerToLLVMOptions options;
206 
207   /// Data layout analysis mapping scopes to layouts active in them.
208   const DataLayoutAnalysis *dataLayoutAnalysis;
209 };
210 
211 /// Callback to convert function argument types. It converts a MemRef function
212 /// argument to a list of non-aggregate types containing descriptor
213 /// information, and an UnrankedmemRef function argument to a list containing
214 /// the rank and a pointer to a descriptor struct.
215 LogicalResult structFuncArgTypeConverter(LLVMTypeConverter &converter,
216                                          Type type,
217                                          SmallVectorImpl<Type> &result);
218 
219 /// Callback to convert function argument types. It converts MemRef function
220 /// arguments to bare pointers to the MemRef element type.
221 LogicalResult barePtrFuncArgTypeConverter(LLVMTypeConverter &converter,
222                                           Type type,
223                                           SmallVectorImpl<Type> &result);
224 
225 } // namespace mlir
226 
227 #endif // MLIR_CONVERSION_LLVMCOMMON_TYPECONVERTER_H
228