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