1//===-- LLVMOps.td - LLVM IR dialect op definition file ----*- tablegen -*-===// 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#ifndef LLVMTYPES_TD 10#define LLVMTYPES_TD 11 12include "mlir/Dialect/LLVMIR/LLVMOpBase.td" 13include "mlir/IR/AttrTypeBase.td" 14include "mlir/Interfaces/DataLayoutInterfaces.td" 15include "mlir/Interfaces/MemorySlotInterfaces.td" 16 17/// Base class for all LLVM dialect types. 18class LLVMType<string typeName, string typeMnemonic, list<Trait> traits = []> 19 : TypeDef<LLVM_Dialect, typeName, traits> { 20 let mnemonic = typeMnemonic; 21} 22 23//===----------------------------------------------------------------------===// 24// LLVMArrayType 25//===----------------------------------------------------------------------===// 26 27def LLVMArrayType : LLVMType<"LLVMArray", "array", [ 28 DeclareTypeInterfaceMethods<DataLayoutTypeInterface, ["getTypeSize"]>, 29 DeclareTypeInterfaceMethods<DestructurableTypeInterface>]> { 30 let summary = "LLVM array type"; 31 let description = [{ 32 The `!llvm.array` type represents a fixed-size array of element types. 33 It is an aggregate type representing consecutive elements in memory, 34 parameterized by the number of elements and the element type. 35 36 Example: 37 38 ```mlir 39 !llvm.array<4 x i32> 40 ``` 41 }]; 42 43 let parameters = (ins "Type":$elementType, "uint64_t":$numElements); 44 let assemblyFormat = [{ 45 `<` $numElements `x` custom<PrettyLLVMType>($elementType) `>` 46 }]; 47 48 let genVerifyDecl = 1; 49 50 let builders = [ 51 TypeBuilderWithInferredContext<(ins "Type":$elementType, 52 "uint64_t":$numElements)> 53 ]; 54 55 let extraClassDeclaration = [{ 56 /// Checks if the given type can be used inside an array type. 57 static bool isValidElementType(Type type); 58 }]; 59} 60 61//===----------------------------------------------------------------------===// 62// LLVMFunctionType 63//===----------------------------------------------------------------------===// 64 65def LLVMFunctionType : LLVMType<"LLVMFunction", "func"> { 66 let summary = "LLVM function type"; 67 let description = [{ 68 The `!llvm.func` is a function type. It consists of a single return type 69 (unlike MLIR which can have multiple), a list of parameter types and can 70 optionally be variadic. 71 72 Example: 73 74 ```mlir 75 !llvm.func<i32 (i32)> 76 ``` 77 }]; 78 79 let parameters = (ins "Type":$returnType, ArrayRefParameter<"Type">:$params, 80 "bool":$varArg); 81 let assemblyFormat = [{ 82 `<` custom<PrettyLLVMType>($returnType) ` ` `(` 83 custom<FunctionTypes>($params, $varArg) `>` 84 }]; 85 86 let genVerifyDecl = 1; 87 88 let builders = [ 89 TypeBuilderWithInferredContext<(ins 90 "Type":$result, "ArrayRef<Type>":$arguments, 91 CArg<"bool", "false">:$isVarArg)> 92 ]; 93 94 let extraClassDeclaration = [{ 95 /// Checks if the given type can be used an argument in a function type. 96 static bool isValidArgumentType(Type type); 97 98 /// Checks if the given type can be used as a result in a function type. 99 static bool isValidResultType(Type type); 100 101 /// Returns whether the function is variadic. 102 bool isVarArg() const { return getVarArg(); } 103 104 /// Returns a clone of this function type with the given argument 105 /// and result types. 106 LLVMFunctionType clone(TypeRange inputs, TypeRange results) const; 107 108 /// Returns the result type of the function as an ArrayRef, enabling better 109 /// integration with generic MLIR utilities. 110 ArrayRef<Type> getReturnTypes() const; 111 112 /// Returns the number of arguments to the function. 113 unsigned getNumParams() const { return getParams().size(); } 114 115 /// Returns `i`-th argument of the function. Asserts on out-of-bounds. 116 Type getParamType(unsigned i) { return getParams()[i]; } 117 }]; 118} 119 120//===----------------------------------------------------------------------===// 121// LLVMStructType 122//===----------------------------------------------------------------------===// 123 124def LLVMStructType : LLVMType<"LLVMStruct", "struct", [ 125 MutableType, 126 DeclareTypeInterfaceMethods<DataLayoutTypeInterface, 127 ["areCompatible", "verifyEntries"]>, 128 DeclareTypeInterfaceMethods<DestructurableTypeInterface, 129 ["getSubelementIndexMap", "getTypeAtIndex"]> 130]> { 131 let summary = "LLVM struct type"; 132 133 let description = [{ 134 LLVM dialect structure type representing a collection of different-typed 135 elements manipulated together. Struct types can optionally be packed, meaning 136 that their elements immediately follow each other in memory without 137 accounting for potential alignment. 138 139 Structure types can be identified (named) or literal. Literal structures 140 are uniquely represented by the list of types they contain and packedness. 141 Literal structure types are immutable after construction. 142 143 Identified structures are uniquely represented by their name, a string. They 144 have a mutable component, consisting of the list of types they contain, 145 the packedness and the opacity bits. Identified structs can be created 146 without providing the lists of element types, making them suitable to 147 represent recursive, i.e. self-referring, structures. Identified structs 148 without body are considered opaque. For such structs, one can set the body. 149 Identified structs can be created as intentionally-opaque, implying that the 150 caller does not intend to ever set the body (e.g. forward-declarations of 151 structs from another module) and wants to disallow further modification of 152 the body. For intentionally-opaque structs or non-opaque structs with the 153 body, one is not allowed to set another body (however, one can set exactly 154 the same body). 155 156 Note that the packedness of the struct takes place in uniquing of literal 157 structs, but does not in uniquing of identified structs. 158 }]; 159 160 // Specify parameters for which TableGen can generate convenient getters for 161 // us. 162 // TODO: Other parameters such as 'packed' or 'opaque' could be added in the 163 // future iff they generate getters prefixed with 'is', instead of 164 // 'get'. Until then there are no advantages in doing so. 165 let parameters = (ins 166 StringRefParameter<"struct name", [{""}]>:$name, 167 OptionalArrayRefParameter<"mlir::Type">:$body 168 ); 169 170 // A custom storage class defined in C++ is required to implement mutability. 171 let storageClass = "LLVMStructTypeStorage"; 172 let genStorageClass = 0; 173 174 // We want users to use the more aptly named custom builders below. 175 let skipDefaultBuilders = 1; 176 177 let extraClassDeclaration = [{ 178 /// Checks if the given type can be contained in a structure type. 179 static bool isValidElementType(Type type); 180 181 /// Gets or creates an identified struct with the given name in the provided 182 /// context. Note that unlike llvm::StructType::create, this function will 183 /// _NOT_ rename a struct in case a struct with the same name already exists 184 /// in the context. Instead, it will just return the existing struct, 185 /// similarly to the rest of MLIR type ::get methods. 186 static LLVMStructType getIdentified(MLIRContext *context, StringRef name); 187 static LLVMStructType 188 getIdentifiedChecked(function_ref<InFlightDiagnostic()> emitError, 189 MLIRContext *context, StringRef name); 190 191 /// Gets a new identified struct with the given body. The body _cannot_ be 192 /// changed later. If a struct with the given name already exists, renames 193 /// the struct by appending a `.` followed by a number to the name. Renaming 194 /// happens even if the existing struct has the same body. 195 static LLVMStructType getNewIdentified(MLIRContext *context, StringRef name, 196 ArrayRef<Type> elements, 197 bool isPacked = false); 198 199 /// Gets or creates a literal struct with the given body in the provided 200 /// context. 201 static LLVMStructType getLiteral(MLIRContext *context, ArrayRef<Type> types, 202 bool isPacked = false); 203 204 static LLVMStructType 205 getLiteralChecked(function_ref<InFlightDiagnostic()> emitError, 206 MLIRContext *context, ArrayRef<Type> types, 207 bool isPacked = false); 208 209 /// Gets or creates an intentionally-opaque identified struct. Such a struct 210 /// cannot have its body set. 211 /// Note that unlike llvm::StructType::create, this function will _NOT_ 212 /// rename a struct in case a struct with the same name 213 /// already exists in the context. Instead, it will just return the existing 214 /// struct, similarly to the rest of MLIR type ::get methods. 215 static LLVMStructType getOpaque(StringRef name, MLIRContext *context); 216 217 static LLVMStructType 218 getOpaqueChecked(function_ref<InFlightDiagnostic()> emitError, 219 MLIRContext *context, StringRef name); 220 221 /// Set the body of an identified struct. Returns failure if the body could 222 /// not be set, e.g. if the struct already has a body or if it was marked as 223 /// intentionally opaque. This might happen in a multi-threaded context when a 224 /// different thread modified the struct after it was created. Most callers 225 /// are likely to assert this always succeeds, but it is possible to implement 226 /// a local renaming scheme based on the result of this call. 227 LogicalResult setBody(ArrayRef<Type> types, bool isPacked); 228 229 /// Checks if a struct is packed. 230 bool isPacked() const; 231 232 /// Checks if a struct is identified. 233 bool isIdentified() const; 234 235 /// Checks if a struct is opaque. 236 bool isOpaque() const; 237 238 /// Checks if a struct is initialized. 239 bool isInitialized(); 240 241 /// Verifies that the type about to be constructed is well-formed. 242 static LogicalResult 243 verifyInvariants(function_ref<InFlightDiagnostic()> emitError, StringRef, 244 bool); 245 static LogicalResult 246 verifyInvariants(function_ref<InFlightDiagnostic()> emitError, 247 ArrayRef<Type> types, bool); 248 using Base::verifyInvariants; 249 }]; 250 251 let hasCustomAssemblyFormat = 1; 252} 253 254//===----------------------------------------------------------------------===// 255// LLVMPointerType 256//===----------------------------------------------------------------------===// 257 258def LLVMPointerType : LLVMType<"LLVMPointer", "ptr", [ 259 DeclareTypeInterfaceMethods<DataLayoutTypeInterface, [ 260 "getIndexBitwidth", "areCompatible", "verifyEntries"]>]> { 261 let summary = "LLVM pointer type"; 262 let description = [{ 263 The `!llvm.ptr` type is an LLVM pointer type. This type typically represents 264 a reference to an object in memory. Pointers are optionally parameterized 265 by the address space. 266 267 Example: 268 269 ```mlir 270 !llvm.ptr 271 ``` 272 }]; 273 274 let parameters = (ins DefaultValuedParameter<"unsigned", "0">:$addressSpace); 275 let assemblyFormat = [{ 276 (`<` $addressSpace^ `>`)? 277 }]; 278 279 let skipDefaultBuilders = 1; 280 let builders = [ 281 TypeBuilder<(ins CArg<"unsigned", "0">:$addressSpace), [{ 282 return $_get($_ctxt, addressSpace); 283 }]> 284 ]; 285} 286 287//===----------------------------------------------------------------------===// 288// LLVMFixedVectorType 289//===----------------------------------------------------------------------===// 290 291def LLVMFixedVectorType : LLVMType<"LLVMFixedVector", "vec"> { 292 let summary = "LLVM fixed vector type"; 293 let description = [{ 294 LLVM dialect scalable vector type, represents a sequence of elements of 295 unknown length that is known to be divisible by some constant. These 296 elements can be processed as one in SIMD context. 297 }]; 298 299 let typeName = "llvm.fixed_vec"; 300 301 let parameters = (ins "Type":$elementType, "unsigned":$numElements); 302 let assemblyFormat = [{ 303 `<` $numElements `x` custom<PrettyLLVMType>($elementType) `>` 304 }]; 305 306 let genVerifyDecl = 1; 307 308 let builders = [ 309 TypeBuilderWithInferredContext<(ins "Type":$elementType, 310 "unsigned":$numElements)> 311 ]; 312 313 let extraClassDeclaration = [{ 314 /// Checks if the given type can be used in a vector type. 315 static bool isValidElementType(Type type); 316 }]; 317} 318 319//===----------------------------------------------------------------------===// 320// LLVMScalableVectorType 321//===----------------------------------------------------------------------===// 322 323def LLVMScalableVectorType : LLVMType<"LLVMScalableVector", "vec"> { 324 let summary = "LLVM scalable vector type"; 325 let description = [{ 326 LLVM dialect scalable vector type, represents a sequence of elements of 327 unknown length that is known to be divisible by some constant. These 328 elements can be processed as one in SIMD context. 329 }]; 330 331 let typeName = "llvm.scalable_vec"; 332 333 let parameters = (ins "Type":$elementType, "unsigned":$minNumElements); 334 let assemblyFormat = [{ 335 `<` `?` `x` $minNumElements `x` ` ` custom<PrettyLLVMType>($elementType) `>` 336 }]; 337 338 let genVerifyDecl = 1; 339 340 let builders = [ 341 TypeBuilderWithInferredContext<(ins "Type":$elementType, 342 "unsigned":$minNumElements)> 343 ]; 344 345 let extraClassDeclaration = [{ 346 /// Checks if the given type can be used in a vector type. 347 static bool isValidElementType(Type type); 348 }]; 349} 350 351//===----------------------------------------------------------------------===// 352// LLVMTargetExtType 353//===----------------------------------------------------------------------===// 354 355def LLVMTargetExtType : LLVMType<"LLVMTargetExt", "target"> { 356 let summary = "LLVM target-specific extension type"; 357 let description = [{ 358 LLVM dialect target extension type, which are generally unintrospectable 359 from target-independent optimizations. 360 361 Target extension types have a string name, and optionally have type and/or 362 integer parameters. The exact meaning of any parameters is dependent on the 363 target. 364 }]; 365 366 let parameters = (ins StringRefParameter<>:$extTypeName, 367 OptionalArrayRefParameter<"Type">:$typeParams, 368 OptionalArrayRefParameter<"unsigned int">:$intParams); 369 370 let assemblyFormat = [{ 371 `<` $extTypeName (`,` custom<ExtTypeParams>($typeParams, $intParams)^ )? `>` 372 }]; 373 374 let extraClassDeclaration = [{ 375 enum Property { 376 /// zeroinitializer is valid for this target extension type. 377 HasZeroInit = 1U << 0, 378 /// This type may be used as the value type of a global variable. 379 CanBeGlobal = 1U << 1, 380 }; 381 382 bool hasProperty(Property Prop) const; 383 bool supportsMemOps() const; 384 }]; 385} 386 387//===----------------------------------------------------------------------===// 388// LLVMX86AMXType 389//===----------------------------------------------------------------------===// 390 391def LLVMX86AMXType : LLVMType<"LLVMX86AMX", "x86_amx"> { 392 let summary = "LLVM x86_amx type."; 393 let description = [{ 394 The x86_amx type represents a value held in an AMX tile register on an x86 395 machine. Can only be used in AMX intrinsics calls. 396 }]; 397} 398 399#endif // LLVMTYPES_TD 400