1//===- LLVMTypes.h - MLIR 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// This file defines the types for the LLVM dialect in MLIR. These MLIR types
10// correspond to the LLVM IR type system.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef MLIR_DIALECT_LLVMIR_LLVMTYPES_H_
15#define MLIR_DIALECT_LLVMIR_LLVMTYPES_H_
16
17#include "mlir/IR/Types.h"
18#include "mlir/Interfaces/DataLayoutInterfaces.h"
19#include "mlir/Interfaces/MemorySlotInterfaces.h"
20#include <optional>
21
22namespace llvm {
23class ElementCount;
24class TypeSize;
25} // namespace llvm
26
27namespace mlir {
28
29class AsmParser;
30class AsmPrinter;
31
32namespace LLVM {
33class LLVMDialect;
34
35namespace detail {
36struct LLVMFunctionTypeStorage;
37struct LLVMPointerTypeStorage;
38struct LLVMStructTypeStorage;
39struct LLVMTypeAndSizeStorage;
40} // namespace detail
41} // namespace LLVM
42} // namespace mlir
43
44//===----------------------------------------------------------------------===//
45// ODS-Generated Declarations
46//===----------------------------------------------------------------------===//
47
48#include "mlir/Dialect/LLVMIR/LLVMTypeInterfaces.h.inc"
49
50#define GET_TYPEDEF_CLASSES
51#include "mlir/Dialect/LLVMIR/LLVMTypes.h.inc"
52
53namespace mlir {
54namespace LLVM {
55
56//===----------------------------------------------------------------------===//
57// Trivial types.
58//===----------------------------------------------------------------------===//
59
60// Batch-define trivial types.
61#define DEFINE_TRIVIAL_LLVM_TYPE(ClassName, TypeName) \
62 class ClassName : public Type::TypeBase<ClassName, Type, TypeStorage> { \
63 public: \
64 using Base::Base; \
65 static constexpr StringLiteral name = TypeName; \
66 }
67
68DEFINE_TRIVIAL_LLVM_TYPE(LLVMVoidType, "llvm.void");
69DEFINE_TRIVIAL_LLVM_TYPE(LLVMPPCFP128Type, "llvm.ppc_fp128");
70DEFINE_TRIVIAL_LLVM_TYPE(LLVMX86MMXType, "llvm.x86_mmx");
71DEFINE_TRIVIAL_LLVM_TYPE(LLVMTokenType, "llvm.token");
72DEFINE_TRIVIAL_LLVM_TYPE(LLVMLabelType, "llvm.label");
73DEFINE_TRIVIAL_LLVM_TYPE(LLVMMetadataType, "llvm.metadata");
74
75#undef DEFINE_TRIVIAL_LLVM_TYPE
76
77//===----------------------------------------------------------------------===//
78// LLVMStructType.
79//===----------------------------------------------------------------------===//
80
81/// LLVM dialect structure type representing a collection of different-typed
82/// elements manipulated together. Structured can optionally be packed, meaning
83/// that their elements immediately follow each other in memory without
84/// accounting for potential alignment.
85///
86/// Structure types can be identified (named) or literal. Literal structures
87/// are uniquely represented by the list of types they contain and packedness.
88/// Literal structure types are immutable after construction.
89///
90/// Identified structures are uniquely represented by their name, a string. They
91/// have a mutable component, consisting of the list of types they contain,
92/// the packedness and the opacity bits. Identified structs can be created
93/// without providing the lists of element types, making them suitable to
94/// represent recursive, i.e. self-referring, structures. Identified structs
95/// without body are considered opaque. For such structs, one can set the body.
96/// Identified structs can be created as intentionally-opaque, implying that the
97/// caller does not intend to ever set the body (e.g. forward-declarations of
98/// structs from another module) and wants to disallow further modification of
99/// the body. For intentionally-opaque structs or non-opaque structs with the
100/// body, one is not allowed to set another body (however, one can set exactly
101/// the same body).
102///
103/// Note that the packedness of the struct takes place in uniquing of literal
104/// structs, but does not in uniquing of identified structs.
105class LLVMStructType
106 : public Type::TypeBase<LLVMStructType, Type, detail::LLVMStructTypeStorage,
107 DataLayoutTypeInterface::Trait,
108 DestructurableTypeInterface::Trait,
109 TypeTrait::IsMutable> {
110public:
111 /// Inherit base constructors.
112 using Base::Base;
113
114 static constexpr StringLiteral name = "llvm.struct";
115
116 /// Checks if the given type can be contained in a structure type.
117 static bool isValidElementType(Type type);
118
119 /// Gets or creates an identified struct with the given name in the provided
120 /// context. Note that unlike llvm::StructType::create, this function will
121 /// _NOT_ rename a struct in case a struct with the same name already exists
122 /// in the context. Instead, it will just return the existing struct,
123 /// similarly to the rest of MLIR type ::get methods.
124 static LLVMStructType getIdentified(MLIRContext *context, StringRef name);
125 static LLVMStructType
126 getIdentifiedChecked(function_ref<InFlightDiagnostic()> emitError,
127 MLIRContext *context, StringRef name);
128
129 /// Gets a new identified struct with the given body. The body _cannot_ be
130 /// changed later. If a struct with the given name already exists, renames
131 /// the struct by appending a `.` followed by a number to the name. Renaming
132 /// happens even if the existing struct has the same body.
133 static LLVMStructType getNewIdentified(MLIRContext *context, StringRef name,
134 ArrayRef<Type> elements,
135 bool isPacked = false);
136
137 /// Gets or creates a literal struct with the given body in the provided
138 /// context.
139 static LLVMStructType getLiteral(MLIRContext *context, ArrayRef<Type> types,
140 bool isPacked = false);
141 static LLVMStructType
142 getLiteralChecked(function_ref<InFlightDiagnostic()> emitError,
143 MLIRContext *context, ArrayRef<Type> types,
144 bool isPacked = false);
145
146 /// Gets or creates an intentionally-opaque identified struct. Such a struct
147 /// cannot have its body set. To create an opaque struct with a mutable body,
148 /// use `getIdentified`. Note that unlike llvm::StructType::create, this
149 /// function will _NOT_ rename a struct in case a struct with the same name
150 /// already exists in the context. Instead, it will just return the existing
151 /// struct, similarly to the rest of MLIR type ::get methods.
152 static LLVMStructType getOpaque(StringRef name, MLIRContext *context);
153 static LLVMStructType
154 getOpaqueChecked(function_ref<InFlightDiagnostic()> emitError,
155 MLIRContext *context, StringRef name);
156
157 /// Set the body of an identified struct. Returns failure if the body could
158 /// not be set, e.g. if the struct already has a body or if it was marked as
159 /// intentionally opaque. This might happen in a multi-threaded context when a
160 /// different thread modified the struct after it was created. Most callers
161 /// are likely to assert this always succeeds, but it is possible to implement
162 /// a local renaming scheme based on the result of this call.
163 LogicalResult setBody(ArrayRef<Type> types, bool isPacked);
164
165 /// Checks if a struct is packed.
166 bool isPacked() const;
167
168 /// Checks if a struct is identified.
169 bool isIdentified() const;
170
171 /// Checks if a struct is opaque.
172 bool isOpaque();
173
174 /// Checks if a struct is initialized.
175 bool isInitialized();
176
177 /// Returns the name of an identified struct.
178 StringRef getName();
179
180 /// Returns the list of element types contained in a non-opaque struct.
181 ArrayRef<Type> getBody() const;
182
183 /// Verifies that the type about to be constructed is well-formed.
184 static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
185 StringRef, bool);
186 static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
187 ArrayRef<Type> types, bool);
188 using Base::verify;
189
190 /// Hooks for DataLayoutTypeInterface. Should not be called directly. Obtain a
191 /// DataLayout instance and query it instead.
192 llvm::TypeSize getTypeSizeInBits(const DataLayout &dataLayout,
193 DataLayoutEntryListRef params) const;
194
195 uint64_t getABIAlignment(const DataLayout &dataLayout,
196 DataLayoutEntryListRef params) const;
197
198 uint64_t getPreferredAlignment(const DataLayout &dataLayout,
199 DataLayoutEntryListRef params) const;
200
201 bool areCompatible(DataLayoutEntryListRef oldLayout,
202 DataLayoutEntryListRef newLayout) const;
203
204 LogicalResult verifyEntries(DataLayoutEntryListRef entries,
205 Location loc) const;
206
207 /// Destructs the struct into its indexed field types.
208 std::optional<DenseMap<Attribute, Type>> getSubelementIndexMap();
209
210 /// Returns which type is stored at a given integer index within the struct.
211 Type getTypeAtIndex(Attribute index);
212};
213
214//===----------------------------------------------------------------------===//
215// Printing and parsing.
216//===----------------------------------------------------------------------===//
217
218namespace detail {
219/// Parses an LLVM dialect type.
220Type parseType(DialectAsmParser &parser);
221
222/// Prints an LLVM Dialect type.
223void printType(Type type, AsmPrinter &printer);
224} // namespace detail
225
226/// Parse any MLIR type or a concise syntax for LLVM types.
227ParseResult parsePrettyLLVMType(AsmParser &p, Type &type);
228/// Print any MLIR type or a concise syntax for LLVM types.
229void printPrettyLLVMType(AsmPrinter &p, Type type);
230
231//===----------------------------------------------------------------------===//
232// Utility functions.
233//===----------------------------------------------------------------------===//
234
235/// Returns `true` if the given type is compatible with the LLVM dialect. This
236/// is an alias to `LLVMDialect::isCompatibleType`.
237bool isCompatibleType(Type type);
238
239/// Returns `true` if the given outer type is compatible with the LLVM dialect
240/// without checking its potential nested types such as struct elements.
241bool isCompatibleOuterType(Type type);
242
243/// Returns `true` if the given type is a floating-point type compatible with
244/// the LLVM dialect.
245bool isCompatibleFloatingPointType(Type type);
246
247/// Returns `true` if the given type is a vector type compatible with the LLVM
248/// dialect. Compatible types include 1D built-in vector types of built-in
249/// integers and floating-point values, LLVM dialect fixed vector types of LLVM
250/// dialect pointers and LLVM dialect scalable vector types.
251bool isCompatibleVectorType(Type type);
252
253/// Returns the element type of any vector type compatible with the LLVM
254/// dialect.
255Type getVectorElementType(Type type);
256
257/// Returns the element count of any LLVM-compatible vector type.
258llvm::ElementCount getVectorNumElements(Type type);
259
260/// Returns whether a vector type is scalable or not.
261bool isScalableVectorType(Type vectorType);
262
263/// Creates an LLVM dialect-compatible vector type with the given element type
264/// and length.
265Type getVectorType(Type elementType, unsigned numElements,
266 bool isScalable = false);
267
268/// Creates an LLVM dialect-compatible vector type with the given element type
269/// and length.
270Type getVectorType(Type elementType, const llvm::ElementCount &numElements);
271
272/// Creates an LLVM dialect-compatible type with the given element type and
273/// length.
274Type getFixedVectorType(Type elementType, unsigned numElements);
275
276/// Creates an LLVM dialect-compatible type with the given element type and
277/// length.
278Type getScalableVectorType(Type elementType, unsigned numElements);
279
280/// Returns the size of the given primitive LLVM dialect-compatible type
281/// (including vectors) in bits, for example, the size of i16 is 16 and
282/// the size of vector<4xi16> is 64. Returns 0 for non-primitive
283/// (aggregates such as struct) or types that don't have a size (such as void).
284llvm::TypeSize getPrimitiveTypeSizeInBits(Type type);
285
286/// The positions of different values in the data layout entry for pointers.
287enum class PtrDLEntryPos { Size = 0, Abi = 1, Preferred = 2, Index = 3 };
288
289/// Returns the value that corresponds to named position `pos` from the
290/// data layout entry `attr` assuming it's a dense integer elements attribute.
291/// Returns `std::nullopt` if `pos` is not present in the entry.
292/// Currently only `PtrDLEntryPos::Index` is optional, and all other positions
293/// may be assumed to be present.
294std::optional<uint64_t> extractPointerSpecValue(Attribute attr,
295 PtrDLEntryPos pos);
296
297} // namespace LLVM
298} // namespace mlir
299
300#endif // MLIR_DIALECT_LLVMIR_LLVMTYPES_H_
301

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