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