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
39namespace llvm {
40class Type;
41class LLVMContext;
42namespace sys {
43template <bool mt_only>
44class SmartMutex;
45} // namespace sys
46} // namespace llvm
47
48namespace mlir {
49namespace LLVM {
50class LLVMDialect;
51
52namespace detail {
53struct LLVMTypeStorage;
54struct LLVMDialectImpl;
55} // namespace detail
56} // namespace LLVM
57} // namespace mlir
58
59namespace mlir {
60namespace LLVM {
61template <typename Values>
62class GEPIndicesAdaptor;
63
64/// Bit-width of a 'GEPConstantIndex' within GEPArg.
65constexpr int kGEPConstantBitWidth = 29;
66/// Wrapper around a int32_t for use in a PointerUnion.
67using 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.
74class GEPArg : public PointerUnion<Value, GEPConstantIndex> {
75 using BaseT = PointerUnion<Value, GEPConstantIndex>;
76
77public:
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
97namespace mlir {
98namespace 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>>'.
113template <typename DynamicRange>
114class GEPIndicesAdaptor {
115public:
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
201private:
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).
210Value 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.
215bool 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.
219template <typename IntT = int64_t>
220SmallVector<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.
230template <typename IntT = int64_t>
231SmallVector<IntT> convertArrayToIndices(ArrayAttr attrs) {
232 return convertArrayToIndices<IntT>(attrs.getValue());
233}
234
235} // namespace LLVM
236} // namespace mlir
237
238namespace llvm {
239
240// Allow llvm::cast style functions.
241template <typename To>
242struct CastInfo<To, mlir::LLVM::GEPArg>
243 : public CastInfo<To, mlir::LLVM::GEPArg::PointerUnion> {};
244
245template <typename To>
246struct 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

source code of mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h