xref: /llvm-project/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h (revision 93da6423af5f00a3bbee4d2ee571ccc7887f444d)
1 //===- LLVMDialect.h - MLIR LLVM IR dialect ---------------------*- 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 // This file defines the LLVM IR dialect in MLIR, containing LLVM operations and
10 // LLVM type system.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_DIALECT_LLVMIR_LLVMDIALECT_H_
15 #define MLIR_DIALECT_LLVMIR_LLVMDIALECT_H_
16 
17 #include "mlir/Bytecode/BytecodeOpInterface.h"
18 #include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
19 #include "mlir/Dialect/LLVMIR/LLVMInterfaces.h"
20 #include "mlir/Dialect/LLVMIR/LLVMTypes.h"
21 #include "mlir/IR/BuiltinOps.h"
22 #include "mlir/IR/Dialect.h"
23 #include "mlir/IR/OpDefinition.h"
24 #include "mlir/IR/OpImplementation.h"
25 #include "mlir/IR/TypeSupport.h"
26 #include "mlir/IR/Types.h"
27 #include "mlir/Interfaces/CallInterfaces.h"
28 #include "mlir/Interfaces/ControlFlowInterfaces.h"
29 #include "mlir/Interfaces/FunctionInterfaces.h"
30 #include "mlir/Interfaces/InferTypeOpInterface.h"
31 #include "mlir/Interfaces/SideEffectInterfaces.h"
32 #include "mlir/Interfaces/ViewLikeInterface.h"
33 #include "mlir/Support/ThreadLocalCache.h"
34 #include "llvm/ADT/PointerEmbeddedInt.h"
35 #include "llvm/IR/DerivedTypes.h"
36 #include "llvm/IR/InstrTypes.h"
37 #include "llvm/IR/LLVMContext.h"
38 #include "llvm/IR/Module.h"
39 #include "llvm/IR/Type.h"
40 
41 namespace llvm {
42 class Type;
43 class LLVMContext;
44 namespace sys {
45 template <bool mt_only>
46 class SmartMutex;
47 } // namespace sys
48 } // namespace llvm
49 
50 namespace mlir {
51 namespace LLVM {
52 class LLVMDialect;
53 
54 namespace detail {
55 struct LLVMTypeStorage;
56 struct LLVMDialectImpl;
57 } // namespace detail
58 } // namespace LLVM
59 } // namespace mlir
60 
61 namespace mlir {
62 namespace LLVM {
63 template <typename Values>
64 class GEPIndicesAdaptor;
65 
66 /// Bit-width of a 'GEPConstantIndex' within GEPArg.
67 constexpr int kGEPConstantBitWidth = 29;
68 /// Wrapper around a int32_t for use in a PointerUnion.
69 using GEPConstantIndex =
70     llvm::PointerEmbeddedInt<int32_t, kGEPConstantBitWidth>;
71 
72 /// Class used for building a 'llvm.getelementptr'. A single instance represents
73 /// a sum type that is either a 'Value' or a constant 'GEPConstantIndex' index.
74 /// The former represents a dynamic index in a GEP operation, while the later is
75 /// a constant index as is required for indices into struct types.
76 class GEPArg : public PointerUnion<Value, GEPConstantIndex> {
77   using BaseT = PointerUnion<Value, GEPConstantIndex>;
78 
79 public:
80   /// Constructs a GEPArg with a constant index.
81   /*implicit*/ GEPArg(int32_t integer) : BaseT(integer) {}
82 
83   /// Constructs a GEPArg with a dynamic index.
84   /*implicit*/ GEPArg(Value value) : BaseT(value) {}
85 
86   using BaseT::operator=;
87 };
88 } // namespace LLVM
89 } // namespace mlir
90 
91 namespace mlir {
92 namespace LLVM {
93 struct AssumeAlignTag {};
94 struct AssumeSeparateStorageTag {};
95 } // namespace LLVM
96 } // namespace mlir
97 
98 ///// Ops /////
99 #define GET_OP_CLASSES
100 #include "mlir/Dialect/LLVMIR/LLVMOps.h.inc"
101 #define GET_OP_CLASSES
102 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.h.inc"
103 
104 #include "mlir/Dialect/LLVMIR/LLVMOpsDialect.h.inc"
105 
106 namespace mlir {
107 namespace LLVM {
108 
109 /// Class used for convenient access and iteration over GEP indices.
110 /// This class is templated to support not only retrieving the dynamic operands
111 /// of a GEP operation, but also as an adaptor during folding or conversion to
112 /// LLVM IR.
113 ///
114 /// GEP indices may either be constant indices or dynamic indices. The
115 /// 'rawConstantIndices' is specially encoded by GEPOp and contains either the
116 /// constant index or the information that an index is a dynamic index.
117 ///
118 /// When an access to such an index is made it is done through the
119 /// 'DynamicRange' of this class. This way it can be used as getter in GEPOp via
120 /// 'GEPIndicesAdaptor<ValueRange>' or during folding via
121 /// 'GEPIndicesAdaptor<ArrayRef<Attribute>>'.
122 template <typename DynamicRange>
123 class GEPIndicesAdaptor {
124 public:
125   /// Return type of 'operator[]' and the iterators 'operator*'. It is depended
126   /// upon the value type of 'DynamicRange'. If 'DynamicRange' contains
127   /// Attributes or subclasses thereof, then value_type is 'Attribute'. In
128   /// all other cases it is a pointer union between the value type of
129   /// 'DynamicRange' and IntegerAttr.
130   using value_type = std::conditional_t<
131       std::is_base_of<Attribute,
132                       llvm::detail::ValueOfRange<DynamicRange>>::value,
133       Attribute,
134       PointerUnion<IntegerAttr, llvm::detail::ValueOfRange<DynamicRange>>>;
135 
136   /// Constructs a GEPIndicesAdaptor with the raw constant indices of a GEPOp
137   /// and the range that is indexed into for retrieving dynamic indices.
138   GEPIndicesAdaptor(DenseI32ArrayAttr rawConstantIndices, DynamicRange values)
139       : rawConstantIndices(rawConstantIndices), values(std::move(values)) {}
140 
141   /// Returns the GEP index at the given position. Note that this operation has
142   /// a linear complexity in regards to the accessed position. To iterate over
143   /// all indices, use the iterators.
144   ///
145   /// This operation is invalid if the index is out of bounds.
146   value_type operator[](size_t index) const {
147     assert(index < size() && "index out of bounds");
148     return *std::next(begin(), index);
149   }
150 
151   /// Returns whether the GEP index at the given position is a dynamic index.
152   bool isDynamicIndex(size_t index) const {
153     return rawConstantIndices[index] == GEPOp::kDynamicIndex;
154   }
155 
156   /// Returns the amount of indices of the GEPOp.
157   size_t size() const { return rawConstantIndices.size(); }
158 
159   /// Returns true if this GEPOp does not have any indices.
160   bool empty() const { return rawConstantIndices.empty(); }
161 
162   class iterator
163       : public llvm::iterator_facade_base<iterator, std::forward_iterator_tag,
164                                           value_type, std::ptrdiff_t,
165                                           value_type *, value_type> {
166   public:
167     iterator(const GEPIndicesAdaptor *base,
168              ArrayRef<int32_t>::iterator rawConstantIter,
169              llvm::detail::IterOfRange<const DynamicRange> valuesIter)
170         : base(base), rawConstantIter(rawConstantIter), valuesIter(valuesIter) {
171     }
172 
173     value_type operator*() const {
174       if (*rawConstantIter == GEPOp::kDynamicIndex)
175         return *valuesIter;
176 
177       return IntegerAttr::get(base->rawConstantIndices.getElementType(),
178                               *rawConstantIter);
179     }
180 
181     iterator &operator++() {
182       if (*rawConstantIter == GEPOp::kDynamicIndex)
183         valuesIter++;
184       rawConstantIter++;
185       return *this;
186     }
187 
188     bool operator==(const iterator &rhs) const {
189       return base == rhs.base && rawConstantIter == rhs.rawConstantIter &&
190              valuesIter == rhs.valuesIter;
191     }
192 
193   private:
194     const GEPIndicesAdaptor *base;
195     ArrayRef<int32_t>::const_iterator rawConstantIter;
196     llvm::detail::IterOfRange<const DynamicRange> valuesIter;
197   };
198 
199   /// Returns the begin iterator, iterating over all GEP indices.
200   iterator begin() const {
201     return iterator(this, rawConstantIndices.asArrayRef().begin(),
202                     values.begin());
203   }
204 
205   /// Returns the end iterator, iterating over all GEP indices.
206   iterator end() const {
207     return iterator(this, rawConstantIndices.asArrayRef().end(), values.end());
208   }
209 
210 private:
211   DenseI32ArrayAttr rawConstantIndices;
212   DynamicRange values;
213 };
214 
215 /// Create an LLVM global containing the string "value" at the module containing
216 /// surrounding the insertion point of builder. Obtain the address of that
217 /// global and use it to compute the address of the first character in the
218 /// string (operations inserted at the builder insertion point).
219 Value createGlobalString(Location loc, OpBuilder &builder, StringRef name,
220                          StringRef value, Linkage linkage);
221 
222 /// LLVM requires some operations to be inside of a Module operation. This
223 /// function confirms that the Operation has the desired properties.
224 bool satisfiesLLVMModule(Operation *op);
225 
226 /// Convert an array of integer attributes to a vector of integers that can be
227 /// used as indices in LLVM operations.
228 template <typename IntT = int64_t>
229 SmallVector<IntT> convertArrayToIndices(ArrayRef<Attribute> attrs) {
230   SmallVector<IntT> indices;
231   indices.reserve(attrs.size());
232   for (Attribute attr : attrs)
233     indices.push_back(cast<IntegerAttr>(attr).getInt());
234   return indices;
235 }
236 
237 /// Convert an `ArrayAttr` of integer attributes to a vector of integers that
238 /// can be used as indices in LLVM operations.
239 template <typename IntT = int64_t>
240 SmallVector<IntT> convertArrayToIndices(ArrayAttr attrs) {
241   return convertArrayToIndices<IntT>(attrs.getValue());
242 }
243 
244 } // namespace LLVM
245 } // namespace mlir
246 
247 namespace llvm {
248 
249 // Allow llvm::cast style functions.
250 template <typename To>
251 struct CastInfo<To, mlir::LLVM::GEPArg>
252     : public CastInfo<To, mlir::LLVM::GEPArg::PointerUnion> {};
253 
254 template <typename To>
255 struct CastInfo<To, const mlir::LLVM::GEPArg>
256     : public CastInfo<To, const mlir::LLVM::GEPArg::PointerUnion> {};
257 
258 } // namespace llvm
259 
260 #endif // MLIR_DIALECT_LLVMIR_LLVMDIALECT_H_
261