MLIR  20.0.0git
LLVMTypes.cpp
Go to the documentation of this file.
1 //===- LLVMTypes.cpp - 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 implements the types for the LLVM dialect in MLIR. These MLIR types
10 // correspond to the LLVM IR type system.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "TypeDetail.h"
15 
18 #include "mlir/IR/BuiltinTypes.h"
20 #include "mlir/IR/TypeSupport.h"
21 
22 #include "llvm/ADT/ScopeExit.h"
23 #include "llvm/ADT/TypeSwitch.h"
24 #include "llvm/Support/TypeSize.h"
25 #include <optional>
26 
27 using namespace mlir;
28 using namespace mlir::LLVM;
29 
30 constexpr const static uint64_t kBitsInByte = 8;
31 
32 //===----------------------------------------------------------------------===//
33 // custom<FunctionTypes>
34 //===----------------------------------------------------------------------===//
35 
36 static ParseResult parseFunctionTypes(AsmParser &p, SmallVector<Type> &params,
37  bool &isVarArg) {
38  isVarArg = false;
39  // `(` `)`
40  if (succeeded(p.parseOptionalRParen()))
41  return success();
42 
43  // `(` `...` `)`
44  if (succeeded(p.parseOptionalEllipsis())) {
45  isVarArg = true;
46  return p.parseRParen();
47  }
48 
49  // type (`,` type)* (`,` `...`)?
50  Type type;
51  if (parsePrettyLLVMType(p, type))
52  return failure();
53  params.push_back(type);
54  while (succeeded(p.parseOptionalComma())) {
55  if (succeeded(p.parseOptionalEllipsis())) {
56  isVarArg = true;
57  return p.parseRParen();
58  }
59  if (parsePrettyLLVMType(p, type))
60  return failure();
61  params.push_back(type);
62  }
63  return p.parseRParen();
64 }
65 
67  bool isVarArg) {
68  llvm::interleaveComma(params, p,
69  [&](Type type) { printPrettyLLVMType(p, type); });
70  if (isVarArg) {
71  if (!params.empty())
72  p << ", ";
73  p << "...";
74  }
75  p << ')';
76 }
77 
78 //===----------------------------------------------------------------------===//
79 // custom<ExtTypeParams>
80 //===----------------------------------------------------------------------===//
81 
82 /// Parses the parameter list for a target extension type. The parameter list
83 /// contains an optional list of type parameters, followed by an optional list
84 /// of integer parameters. Type and integer parameters cannot be interleaved in
85 /// the list.
86 /// extTypeParams ::= typeList? | intList? | (typeList "," intList)
87 /// typeList ::= type ("," type)*
88 /// intList ::= integer ("," integer)*
89 static ParseResult
91  SmallVectorImpl<unsigned int> &intParams) {
92  bool parseType = true;
93  auto typeOrIntParser = [&]() -> ParseResult {
94  unsigned int i;
95  auto intResult = p.parseOptionalInteger(i);
96  if (intResult.has_value() && !failed(*intResult)) {
97  // Successfully parsed an integer.
98  intParams.push_back(i);
99  // After the first integer was successfully parsed, no
100  // more types can be parsed.
101  parseType = false;
102  return success();
103  }
104  if (parseType) {
105  Type t;
106  if (!parsePrettyLLVMType(p, t)) {
107  // Successfully parsed a type.
108  typeParams.push_back(t);
109  return success();
110  }
111  }
112  return failure();
113  };
114  if (p.parseCommaSeparatedList(typeOrIntParser)) {
116  "failed to parse parameter list for target extension type");
117  return failure();
118  }
119  return success();
120 }
121 
122 static void printExtTypeParams(AsmPrinter &p, ArrayRef<Type> typeParams,
123  ArrayRef<unsigned int> intParams) {
124  p << typeParams;
125  if (!typeParams.empty() && !intParams.empty())
126  p << ", ";
127 
128  p << intParams;
129 }
130 
131 //===----------------------------------------------------------------------===//
132 // ODS-Generated Definitions
133 //===----------------------------------------------------------------------===//
134 
135 /// These are unused for now.
136 /// TODO: Move over to these once more types have been migrated to TypeDef.
137 LLVM_ATTRIBUTE_UNUSED static OptionalParseResult
138 generatedTypeParser(AsmParser &parser, StringRef *mnemonic, Type &value);
139 LLVM_ATTRIBUTE_UNUSED static LogicalResult
141 
142 #include "mlir/Dialect/LLVMIR/LLVMTypeInterfaces.cpp.inc"
143 
144 #define GET_TYPEDEF_CLASSES
145 #include "mlir/Dialect/LLVMIR/LLVMTypes.cpp.inc"
146 
147 //===----------------------------------------------------------------------===//
148 // LLVMArrayType
149 //===----------------------------------------------------------------------===//
150 
151 bool LLVMArrayType::isValidElementType(Type type) {
152  return !llvm::isa<LLVMVoidType, LLVMLabelType, LLVMMetadataType,
153  LLVMFunctionType, LLVMTokenType, LLVMScalableVectorType>(
154  type);
155 }
156 
157 LLVMArrayType LLVMArrayType::get(Type elementType, uint64_t numElements) {
158  assert(elementType && "expected non-null subtype");
159  return Base::get(elementType.getContext(), elementType, numElements);
160 }
161 
162 LLVMArrayType
163 LLVMArrayType::getChecked(function_ref<InFlightDiagnostic()> emitError,
164  Type elementType, uint64_t numElements) {
165  assert(elementType && "expected non-null subtype");
166  return Base::getChecked(emitError, elementType.getContext(), elementType,
167  numElements);
168 }
169 
170 LogicalResult
172  Type elementType, uint64_t numElements) {
173  if (!isValidElementType(elementType))
174  return emitError() << "invalid array element type: " << elementType;
175  return success();
176 }
177 
178 //===----------------------------------------------------------------------===//
179 // DataLayoutTypeInterface
180 
181 llvm::TypeSize
182 LLVMArrayType::getTypeSizeInBits(const DataLayout &dataLayout,
183  DataLayoutEntryListRef params) const {
184  return llvm::TypeSize::getFixed(kBitsInByte *
185  getTypeSize(dataLayout, params));
186 }
187 
188 llvm::TypeSize LLVMArrayType::getTypeSize(const DataLayout &dataLayout,
189  DataLayoutEntryListRef params) const {
190  return llvm::alignTo(dataLayout.getTypeSize(getElementType()),
191  dataLayout.getTypeABIAlignment(getElementType())) *
192  getNumElements();
193 }
194 
195 uint64_t LLVMArrayType::getABIAlignment(const DataLayout &dataLayout,
196  DataLayoutEntryListRef params) const {
197  return dataLayout.getTypeABIAlignment(getElementType());
198 }
199 
200 uint64_t
201 LLVMArrayType::getPreferredAlignment(const DataLayout &dataLayout,
202  DataLayoutEntryListRef params) const {
203  return dataLayout.getTypePreferredAlignment(getElementType());
204 }
205 
206 //===----------------------------------------------------------------------===//
207 // Function type.
208 //===----------------------------------------------------------------------===//
209 
210 bool LLVMFunctionType::isValidArgumentType(Type type) {
211  return !llvm::isa<LLVMVoidType, LLVMFunctionType>(type);
212 }
213 
214 bool LLVMFunctionType::isValidResultType(Type type) {
215  return !llvm::isa<LLVMFunctionType, LLVMMetadataType, LLVMLabelType>(type);
216 }
217 
218 LLVMFunctionType LLVMFunctionType::get(Type result, ArrayRef<Type> arguments,
219  bool isVarArg) {
220  assert(result && "expected non-null result");
221  return Base::get(result.getContext(), result, arguments, isVarArg);
222 }
223 
224 LLVMFunctionType
225 LLVMFunctionType::getChecked(function_ref<InFlightDiagnostic()> emitError,
226  Type result, ArrayRef<Type> arguments,
227  bool isVarArg) {
228  assert(result && "expected non-null result");
229  return Base::getChecked(emitError, result.getContext(), result, arguments,
230  isVarArg);
231 }
232 
233 LLVMFunctionType LLVMFunctionType::clone(TypeRange inputs,
234  TypeRange results) const {
235  assert(results.size() == 1 && "expected a single result type");
236  return get(results[0], llvm::to_vector(inputs), isVarArg());
237 }
238 
239 ArrayRef<Type> LLVMFunctionType::getReturnTypes() const {
240  return static_cast<detail::LLVMFunctionTypeStorage *>(getImpl())->returnType;
241 }
242 
243 LogicalResult
245  Type result, ArrayRef<Type> arguments, bool) {
246  if (!isValidResultType(result))
247  return emitError() << "invalid function result type: " << result;
248 
249  for (Type arg : arguments)
250  if (!isValidArgumentType(arg))
251  return emitError() << "invalid function argument type: " << arg;
252 
253  return success();
254 }
255 
256 //===----------------------------------------------------------------------===//
257 // DataLayoutTypeInterface
258 
259 constexpr const static uint64_t kDefaultPointerSizeBits = 64;
260 constexpr const static uint64_t kDefaultPointerAlignment = 8;
261 
262 std::optional<uint64_t> mlir::LLVM::extractPointerSpecValue(Attribute attr,
263  PtrDLEntryPos pos) {
264  auto spec = cast<DenseIntElementsAttr>(attr);
265  auto idx = static_cast<int64_t>(pos);
266  if (idx >= spec.size())
267  return std::nullopt;
268  return spec.getValues<uint64_t>()[idx];
269 }
270 
271 /// Returns the part of the data layout entry that corresponds to `pos` for the
272 /// given `type` by interpreting the list of entries `params`. For the pointer
273 /// type in the default address space, returns the default value if the entries
274 /// do not provide a custom one, for other address spaces returns std::nullopt.
275 static std::optional<uint64_t>
277  PtrDLEntryPos pos) {
278  // First, look for the entry for the pointer in the current address space.
279  Attribute currentEntry;
280  for (DataLayoutEntryInterface entry : params) {
281  if (!entry.isTypeEntry())
282  continue;
283  if (cast<LLVMPointerType>(entry.getKey().get<Type>()).getAddressSpace() ==
284  type.getAddressSpace()) {
285  currentEntry = entry.getValue();
286  break;
287  }
288  }
289  if (currentEntry) {
290  std::optional<uint64_t> value = extractPointerSpecValue(currentEntry, pos);
291  // If the optional `PtrDLEntryPos::Index` entry is not available, use the
292  // pointer size as the index bitwidth.
293  if (!value && pos == PtrDLEntryPos::Index)
294  value = extractPointerSpecValue(currentEntry, PtrDLEntryPos::Size);
295  bool isSizeOrIndex =
296  pos == PtrDLEntryPos::Size || pos == PtrDLEntryPos::Index;
297  return *value / (isSizeOrIndex ? 1 : kBitsInByte);
298  }
299 
300  // If not found, and this is the pointer to the default memory space, assume
301  // 64-bit pointers.
302  if (type.getAddressSpace() == 0) {
303  bool isSizeOrIndex =
304  pos == PtrDLEntryPos::Size || pos == PtrDLEntryPos::Index;
305  return isSizeOrIndex ? kDefaultPointerSizeBits : kDefaultPointerAlignment;
306  }
307 
308  return std::nullopt;
309 }
310 
311 llvm::TypeSize
312 LLVMPointerType::getTypeSizeInBits(const DataLayout &dataLayout,
313  DataLayoutEntryListRef params) const {
314  if (std::optional<uint64_t> size =
316  return llvm::TypeSize::getFixed(*size);
317 
318  // For other memory spaces, use the size of the pointer to the default memory
319  // space.
320  return dataLayout.getTypeSizeInBits(get(getContext()));
321 }
322 
323 uint64_t LLVMPointerType::getABIAlignment(const DataLayout &dataLayout,
324  DataLayoutEntryListRef params) const {
325  if (std::optional<uint64_t> alignment =
327  return *alignment;
328 
329  return dataLayout.getTypeABIAlignment(get(getContext()));
330 }
331 
332 uint64_t
333 LLVMPointerType::getPreferredAlignment(const DataLayout &dataLayout,
334  DataLayoutEntryListRef params) const {
335  if (std::optional<uint64_t> alignment =
337  return *alignment;
338 
339  return dataLayout.getTypePreferredAlignment(get(getContext()));
340 }
341 
342 std::optional<uint64_t>
344  DataLayoutEntryListRef params) const {
345  if (std::optional<uint64_t> indexBitwidth =
347  return *indexBitwidth;
348 
349  return dataLayout.getTypeIndexBitwidth(get(getContext()));
350 }
351 
352 bool LLVMPointerType::areCompatible(DataLayoutEntryListRef oldLayout,
353  DataLayoutEntryListRef newLayout) const {
354  for (DataLayoutEntryInterface newEntry : newLayout) {
355  if (!newEntry.isTypeEntry())
356  continue;
357  uint64_t size = kDefaultPointerSizeBits;
358  uint64_t abi = kDefaultPointerAlignment;
359  auto newType = llvm::cast<LLVMPointerType>(newEntry.getKey().get<Type>());
360  const auto *it =
361  llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
362  if (auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
363  return llvm::cast<LLVMPointerType>(type).getAddressSpace() ==
364  newType.getAddressSpace();
365  }
366  return false;
367  });
368  if (it == oldLayout.end()) {
369  llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
370  if (auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
371  return llvm::cast<LLVMPointerType>(type).getAddressSpace() == 0;
372  }
373  return false;
374  });
375  }
376  if (it != oldLayout.end()) {
379  }
380 
381  Attribute newSpec = llvm::cast<DenseIntElementsAttr>(newEntry.getValue());
382  uint64_t newSize = *extractPointerSpecValue(newSpec, PtrDLEntryPos::Size);
383  uint64_t newAbi = *extractPointerSpecValue(newSpec, PtrDLEntryPos::Abi);
384  if (size != newSize || abi < newAbi || abi % newAbi != 0)
385  return false;
386  }
387  return true;
388 }
389 
390 LogicalResult LLVMPointerType::verifyEntries(DataLayoutEntryListRef entries,
391  Location loc) const {
392  for (DataLayoutEntryInterface entry : entries) {
393  if (!entry.isTypeEntry())
394  continue;
395  auto key = entry.getKey().get<Type>();
396  auto values = llvm::dyn_cast<DenseIntElementsAttr>(entry.getValue());
397  if (!values || (values.size() != 3 && values.size() != 4)) {
398  return emitError(loc)
399  << "expected layout attribute for " << key
400  << " to be a dense integer elements attribute with 3 or 4 "
401  "elements";
402  }
403  if (!values.getElementType().isInteger(64))
404  return emitError(loc) << "expected i64 parameters for " << key;
405 
408  return emitError(loc) << "preferred alignment is expected to be at least "
409  "as large as ABI alignment";
410  }
411  }
412  return success();
413 }
414 
415 //===----------------------------------------------------------------------===//
416 // Struct type.
417 //===----------------------------------------------------------------------===//
418 
420  return !llvm::isa<LLVMVoidType, LLVMLabelType, LLVMMetadataType,
421  LLVMFunctionType, LLVMTokenType, LLVMScalableVectorType>(
422  type);
423 }
424 
426  StringRef name) {
427  return Base::get(context, name, /*opaque=*/false);
428 }
429 
432  StringRef name) {
433  return Base::getChecked(emitError, context, name, /*opaque=*/false);
434 }
435 
437  StringRef name,
438  ArrayRef<Type> elements,
439  bool isPacked) {
440  std::string stringName = name.str();
441  unsigned counter = 0;
442  do {
443  auto type = LLVMStructType::getIdentified(context, stringName);
444  if (type.isInitialized() || failed(type.setBody(elements, isPacked))) {
445  counter += 1;
446  stringName = (Twine(name) + "." + std::to_string(counter)).str();
447  continue;
448  }
449  return type;
450  } while (true);
451 }
452 
454  ArrayRef<Type> types, bool isPacked) {
455  return Base::get(context, types, isPacked);
456 }
457 
460  MLIRContext *context, ArrayRef<Type> types,
461  bool isPacked) {
462  return Base::getChecked(emitError, context, types, isPacked);
463 }
464 
466  return Base::get(context, name, /*opaque=*/true);
467 }
468 
471  MLIRContext *context, StringRef name) {
472  return Base::getChecked(emitError, context, name, /*opaque=*/true);
473 }
474 
475 LogicalResult LLVMStructType::setBody(ArrayRef<Type> types, bool isPacked) {
476  assert(isIdentified() && "can only set bodies of identified structs");
477  assert(llvm::all_of(types, LLVMStructType::isValidElementType) &&
478  "expected valid body types");
479  return Base::mutate(types, isPacked);
480 }
481 
482 bool LLVMStructType::isPacked() const { return getImpl()->isPacked(); }
483 bool LLVMStructType::isIdentified() const { return getImpl()->isIdentified(); }
485  return getImpl()->isIdentified() &&
486  (getImpl()->isOpaque() || !getImpl()->isInitialized());
487 }
488 bool LLVMStructType::isInitialized() { return getImpl()->isInitialized(); }
489 StringRef LLVMStructType::getName() { return getImpl()->getIdentifier(); }
491  return isIdentified() ? getImpl()->getIdentifiedStructBody()
492  : getImpl()->getTypeList();
493 }
494 
496  StringRef, bool) {
497  return success();
498 }
499 
500 LogicalResult
502  ArrayRef<Type> types, bool) {
503  for (Type t : types)
504  if (!isValidElementType(t))
505  return emitError() << "invalid LLVM structure element type: " << t;
506 
507  return success();
508 }
509 
510 llvm::TypeSize
512  DataLayoutEntryListRef params) const {
513  auto structSize = llvm::TypeSize::getFixed(0);
514  uint64_t structAlignment = 1;
515  for (Type element : getBody()) {
516  uint64_t elementAlignment =
517  isPacked() ? 1 : dataLayout.getTypeABIAlignment(element);
518  // Add padding to the struct size to align it to the abi alignment of the
519  // element type before than adding the size of the element.
520  structSize = llvm::alignTo(structSize, elementAlignment);
521  structSize += dataLayout.getTypeSize(element);
522 
523  // The alignment requirement of a struct is equal to the strictest alignment
524  // requirement of its elements.
525  structAlignment = std::max(elementAlignment, structAlignment);
526  }
527  // At the end, add padding to the struct to satisfy its own alignment
528  // requirement. Otherwise structs inside of arrays would be misaligned.
529  structSize = llvm::alignTo(structSize, structAlignment);
530  return structSize * kBitsInByte;
531 }
532 
533 namespace {
534 enum class StructDLEntryPos { Abi = 0, Preferred = 1 };
535 } // namespace
536 
537 static std::optional<uint64_t>
539  StructDLEntryPos pos) {
540  const auto *currentEntry =
541  llvm::find_if(params, [](DataLayoutEntryInterface entry) {
542  return entry.isTypeEntry();
543  });
544  if (currentEntry == params.end())
545  return std::nullopt;
546 
547  auto attr = llvm::cast<DenseIntElementsAttr>(currentEntry->getValue());
548  if (pos == StructDLEntryPos::Preferred &&
549  attr.size() <= static_cast<int64_t>(StructDLEntryPos::Preferred))
550  // If no preferred was specified, fall back to abi alignment
551  pos = StructDLEntryPos::Abi;
552 
553  return attr.getValues<uint64_t>()[static_cast<size_t>(pos)];
554 }
555 
556 static uint64_t calculateStructAlignment(const DataLayout &dataLayout,
557  DataLayoutEntryListRef params,
558  LLVMStructType type,
559  StructDLEntryPos pos) {
560  // Packed structs always have an abi alignment of 1
561  if (pos == StructDLEntryPos::Abi && type.isPacked()) {
562  return 1;
563  }
564 
565  // The alignment requirement of a struct is equal to the strictest alignment
566  // requirement of its elements.
567  uint64_t structAlignment = 1;
568  for (Type iter : type.getBody()) {
569  structAlignment =
570  std::max(dataLayout.getTypeABIAlignment(iter), structAlignment);
571  }
572 
573  // Entries are only allowed to be stricter than the required alignment
574  if (std::optional<uint64_t> entryResult =
575  getStructDataLayoutEntry(params, type, pos))
576  return std::max(*entryResult / kBitsInByte, structAlignment);
577 
578  return structAlignment;
579 }
580 
581 uint64_t LLVMStructType::getABIAlignment(const DataLayout &dataLayout,
582  DataLayoutEntryListRef params) const {
583  return calculateStructAlignment(dataLayout, params, *this,
584  StructDLEntryPos::Abi);
585 }
586 
587 uint64_t
589  DataLayoutEntryListRef params) const {
590  return calculateStructAlignment(dataLayout, params, *this,
591  StructDLEntryPos::Preferred);
592 }
593 
594 static uint64_t extractStructSpecValue(Attribute attr, StructDLEntryPos pos) {
595  return llvm::cast<DenseIntElementsAttr>(attr)
596  .getValues<uint64_t>()[static_cast<size_t>(pos)];
597 }
598 
600  DataLayoutEntryListRef newLayout) const {
601  for (DataLayoutEntryInterface newEntry : newLayout) {
602  if (!newEntry.isTypeEntry())
603  continue;
604 
605  const auto *previousEntry =
606  llvm::find_if(oldLayout, [](DataLayoutEntryInterface entry) {
607  return entry.isTypeEntry();
608  });
609  if (previousEntry == oldLayout.end())
610  continue;
611 
612  uint64_t abi = extractStructSpecValue(previousEntry->getValue(),
613  StructDLEntryPos::Abi);
614  uint64_t newAbi =
615  extractStructSpecValue(newEntry.getValue(), StructDLEntryPos::Abi);
616  if (abi < newAbi || abi % newAbi != 0)
617  return false;
618  }
619  return true;
620 }
621 
623  Location loc) const {
624  for (DataLayoutEntryInterface entry : entries) {
625  if (!entry.isTypeEntry())
626  continue;
627 
628  auto key = llvm::cast<LLVMStructType>(entry.getKey().get<Type>());
629  auto values = llvm::dyn_cast<DenseIntElementsAttr>(entry.getValue());
630  if (!values || (values.size() != 2 && values.size() != 1)) {
631  return emitError(loc)
632  << "expected layout attribute for " << entry.getKey().get<Type>()
633  << " to be a dense integer elements attribute of 1 or 2 elements";
634  }
635  if (!values.getElementType().isInteger(64))
636  return emitError(loc) << "expected i64 entries for " << key;
637 
638  if (key.isIdentified() || !key.getBody().empty()) {
639  return emitError(loc) << "unexpected layout attribute for struct " << key;
640  }
641 
642  if (values.size() == 1)
643  continue;
644 
645  if (extractStructSpecValue(values, StructDLEntryPos::Abi) >
646  extractStructSpecValue(values, StructDLEntryPos::Preferred)) {
647  return emitError(loc) << "preferred alignment is expected to be at least "
648  "as large as ABI alignment";
649  }
650  }
651  return mlir::success();
652 }
653 
654 //===----------------------------------------------------------------------===//
655 // Vector types.
656 //===----------------------------------------------------------------------===//
657 
658 /// Verifies that the type about to be constructed is well-formed.
659 template <typename VecTy>
660 static LogicalResult
662  Type elementType, unsigned numElements) {
663  if (numElements == 0)
664  return emitError() << "the number of vector elements must be positive";
665 
666  if (!VecTy::isValidElementType(elementType))
667  return emitError() << "invalid vector element type";
668 
669  return success();
670 }
671 
672 LLVMFixedVectorType LLVMFixedVectorType::get(Type elementType,
673  unsigned numElements) {
674  assert(elementType && "expected non-null subtype");
675  return Base::get(elementType.getContext(), elementType, numElements);
676 }
677 
678 LLVMFixedVectorType
679 LLVMFixedVectorType::getChecked(function_ref<InFlightDiagnostic()> emitError,
680  Type elementType, unsigned numElements) {
681  assert(elementType && "expected non-null subtype");
682  return Base::getChecked(emitError, elementType.getContext(), elementType,
683  numElements);
684 }
685 
686 bool LLVMFixedVectorType::isValidElementType(Type type) {
687  return llvm::isa<LLVMPointerType, LLVMPPCFP128Type>(type);
688 }
689 
690 LogicalResult
692  Type elementType, unsigned numElements) {
693  return verifyVectorConstructionInvariants<LLVMFixedVectorType>(
694  emitError, elementType, numElements);
695 }
696 
697 //===----------------------------------------------------------------------===//
698 // LLVMScalableVectorType.
699 //===----------------------------------------------------------------------===//
700 
701 LLVMScalableVectorType LLVMScalableVectorType::get(Type elementType,
702  unsigned minNumElements) {
703  assert(elementType && "expected non-null subtype");
704  return Base::get(elementType.getContext(), elementType, minNumElements);
705 }
706 
707 LLVMScalableVectorType
708 LLVMScalableVectorType::getChecked(function_ref<InFlightDiagnostic()> emitError,
709  Type elementType, unsigned minNumElements) {
710  assert(elementType && "expected non-null subtype");
711  return Base::getChecked(emitError, elementType.getContext(), elementType,
712  minNumElements);
713 }
714 
715 bool LLVMScalableVectorType::isValidElementType(Type type) {
716  if (auto intType = llvm::dyn_cast<IntegerType>(type))
717  return intType.isSignless();
718 
719  return isCompatibleFloatingPointType(type) ||
720  llvm::isa<LLVMPointerType>(type);
721 }
722 
723 LogicalResult
725  Type elementType, unsigned numElements) {
726  return verifyVectorConstructionInvariants<LLVMScalableVectorType>(
727  emitError, elementType, numElements);
728 }
729 
730 //===----------------------------------------------------------------------===//
731 // LLVMTargetExtType.
732 //===----------------------------------------------------------------------===//
733 
734 static constexpr llvm::StringRef kSpirvPrefix = "spirv.";
735 static constexpr llvm::StringRef kArmSVCount = "aarch64.svcount";
736 
737 bool LLVM::LLVMTargetExtType::hasProperty(Property prop) const {
738  // See llvm/lib/IR/Type.cpp for reference.
739  uint64_t properties = 0;
740 
741  if (getExtTypeName().starts_with(kSpirvPrefix))
742  properties |=
743  (LLVMTargetExtType::HasZeroInit | LLVM::LLVMTargetExtType::CanBeGlobal);
744 
745  return (properties & prop) == prop;
746 }
747 
748 bool LLVM::LLVMTargetExtType::supportsMemOps() const {
749  // See llvm/lib/IR/Type.cpp for reference.
750  if (getExtTypeName().starts_with(kSpirvPrefix))
751  return true;
752 
753  if (getExtTypeName() == kArmSVCount)
754  return true;
755 
756  return false;
757 }
758 
759 //===----------------------------------------------------------------------===//
760 // Utility functions.
761 //===----------------------------------------------------------------------===//
762 
764  // clang-format off
765  if (llvm::isa<
766  BFloat16Type,
767  Float16Type,
768  Float32Type,
769  Float64Type,
770  Float80Type,
771  Float128Type,
772  LLVMArrayType,
773  LLVMFunctionType,
774  LLVMLabelType,
775  LLVMMetadataType,
776  LLVMPPCFP128Type,
777  LLVMPointerType,
779  LLVMTokenType,
780  LLVMFixedVectorType,
781  LLVMScalableVectorType,
782  LLVMTargetExtType,
783  LLVMVoidType
784  >(type)) {
785  // clang-format on
786  return true;
787  }
788 
789  // Only signless integers are compatible.
790  if (auto intType = llvm::dyn_cast<IntegerType>(type))
791  return intType.isSignless();
792 
793  // 1D vector types are compatible.
794  if (auto vecType = llvm::dyn_cast<VectorType>(type))
795  return vecType.getRank() == 1;
796 
797  return false;
798 }
799 
800 static bool isCompatibleImpl(Type type, DenseSet<Type> &compatibleTypes) {
801  if (!compatibleTypes.insert(type).second)
802  return true;
803 
804  auto isCompatible = [&](Type type) {
805  return isCompatibleImpl(type, compatibleTypes);
806  };
807 
808  bool result =
810  .Case<LLVMStructType>([&](auto structType) {
811  return llvm::all_of(structType.getBody(), isCompatible);
812  })
813  .Case<LLVMFunctionType>([&](auto funcType) {
814  return isCompatible(funcType.getReturnType()) &&
815  llvm::all_of(funcType.getParams(), isCompatible);
816  })
817  .Case<IntegerType>([](auto intType) { return intType.isSignless(); })
818  .Case<VectorType>([&](auto vecType) {
819  return vecType.getRank() == 1 &&
820  isCompatible(vecType.getElementType());
821  })
822  .Case<LLVMPointerType>([&](auto pointerType) { return true; })
823  .Case<LLVMTargetExtType>([&](auto extType) {
824  return llvm::all_of(extType.getTypeParams(), isCompatible);
825  })
826  // clang-format off
827  .Case<
828  LLVMFixedVectorType,
829  LLVMScalableVectorType,
830  LLVMArrayType
831  >([&](auto containerType) {
832  return isCompatible(containerType.getElementType());
833  })
834  .Case<
835  BFloat16Type,
836  Float16Type,
837  Float32Type,
838  Float64Type,
839  Float80Type,
840  Float128Type,
841  LLVMLabelType,
842  LLVMMetadataType,
843  LLVMPPCFP128Type,
844  LLVMTokenType,
845  LLVMVoidType
846  >([](Type) { return true; })
847  // clang-format on
848  .Default([](Type) { return false; });
849 
850  if (!result)
851  compatibleTypes.erase(type);
852 
853  return result;
854 }
855 
857  if (auto *llvmDialect =
858  type.getContext()->getLoadedDialect<LLVM::LLVMDialect>())
859  return isCompatibleImpl(type, llvmDialect->compatibleTypes.get());
860 
861  DenseSet<Type> localCompatibleTypes;
862  return isCompatibleImpl(type, localCompatibleTypes);
863 }
864 
866  return LLVMDialect::isCompatibleType(type);
867 }
868 
870  return llvm::isa<BFloat16Type, Float16Type, Float32Type, Float64Type,
871  Float80Type, Float128Type, LLVMPPCFP128Type>(type);
872 }
873 
875  if (llvm::isa<LLVMFixedVectorType, LLVMScalableVectorType>(type))
876  return true;
877 
878  if (auto vecType = llvm::dyn_cast<VectorType>(type)) {
879  if (vecType.getRank() != 1)
880  return false;
881  Type elementType = vecType.getElementType();
882  if (auto intType = llvm::dyn_cast<IntegerType>(elementType))
883  return intType.isSignless();
884  return llvm::isa<BFloat16Type, Float16Type, Float32Type, Float64Type,
885  Float80Type, Float128Type>(elementType);
886  }
887  return false;
888 }
889 
891  return llvm::TypeSwitch<Type, Type>(type)
892  .Case<LLVMFixedVectorType, LLVMScalableVectorType, VectorType>(
893  [](auto ty) { return ty.getElementType(); })
894  .Default([](Type) -> Type {
895  llvm_unreachable("incompatible with LLVM vector type");
896  });
897 }
898 
899 llvm::ElementCount mlir::LLVM::getVectorNumElements(Type type) {
901  .Case([](VectorType ty) {
902  if (ty.isScalable())
903  return llvm::ElementCount::getScalable(ty.getNumElements());
904  return llvm::ElementCount::getFixed(ty.getNumElements());
905  })
906  .Case([](LLVMFixedVectorType ty) {
907  return llvm::ElementCount::getFixed(ty.getNumElements());
908  })
909  .Case([](LLVMScalableVectorType ty) {
910  return llvm::ElementCount::getScalable(ty.getMinNumElements());
911  })
912  .Default([](Type) -> llvm::ElementCount {
913  llvm_unreachable("incompatible with LLVM vector type");
914  });
915 }
916 
918  assert((llvm::isa<LLVMFixedVectorType, LLVMScalableVectorType, VectorType>(
919  vectorType)) &&
920  "expected LLVM-compatible vector type");
921  return !llvm::isa<LLVMFixedVectorType>(vectorType) &&
922  (llvm::isa<LLVMScalableVectorType>(vectorType) ||
923  llvm::cast<VectorType>(vectorType).isScalable());
924 }
925 
926 Type mlir::LLVM::getVectorType(Type elementType, unsigned numElements,
927  bool isScalable) {
928  bool useLLVM = LLVMFixedVectorType::isValidElementType(elementType);
929  bool useBuiltIn = VectorType::isValidElementType(elementType);
930  (void)useBuiltIn;
931  assert((useLLVM ^ useBuiltIn) && "expected LLVM-compatible fixed-vector type "
932  "to be either builtin or LLVM dialect type");
933  if (useLLVM) {
934  if (isScalable)
935  return LLVMScalableVectorType::get(elementType, numElements);
936  return LLVMFixedVectorType::get(elementType, numElements);
937  }
938 
939  // LLVM vectors are always 1-D, hence only 1 bool is required to mark it as
940  // scalable/non-scalable.
941  return VectorType::get(numElements, elementType, {isScalable});
942 }
943 
945  const llvm::ElementCount &numElements) {
946  if (numElements.isScalable())
947  return getVectorType(elementType, numElements.getKnownMinValue(),
948  /*isScalable=*/true);
949  return getVectorType(elementType, numElements.getFixedValue(),
950  /*isScalable=*/false);
951 }
952 
953 Type mlir::LLVM::getFixedVectorType(Type elementType, unsigned numElements) {
954  bool useLLVM = LLVMFixedVectorType::isValidElementType(elementType);
955  bool useBuiltIn = VectorType::isValidElementType(elementType);
956  (void)useBuiltIn;
957  assert((useLLVM ^ useBuiltIn) && "expected LLVM-compatible fixed-vector type "
958  "to be either builtin or LLVM dialect type");
959  if (useLLVM)
960  return LLVMFixedVectorType::get(elementType, numElements);
961  return VectorType::get(numElements, elementType);
962 }
963 
964 Type mlir::LLVM::getScalableVectorType(Type elementType, unsigned numElements) {
965  bool useLLVM = LLVMScalableVectorType::isValidElementType(elementType);
966  bool useBuiltIn = VectorType::isValidElementType(elementType);
967  (void)useBuiltIn;
968  assert((useLLVM ^ useBuiltIn) && "expected LLVM-compatible scalable-vector "
969  "type to be either builtin or LLVM dialect "
970  "type");
971  if (useLLVM)
972  return LLVMScalableVectorType::get(elementType, numElements);
973 
974  // LLVM vectors are always 1-D, hence only 1 bool is required to mark it as
975  // scalable/non-scalable.
976  return VectorType::get(numElements, elementType, /*scalableDims=*/true);
977 }
978 
980  assert(isCompatibleType(type) &&
981  "expected a type compatible with the LLVM dialect");
982 
984  .Case<BFloat16Type, Float16Type>(
985  [](Type) { return llvm::TypeSize::getFixed(16); })
986  .Case<Float32Type>([](Type) { return llvm::TypeSize::getFixed(32); })
987  .Case<Float64Type>([](Type) { return llvm::TypeSize::getFixed(64); })
988  .Case<Float80Type>([](Type) { return llvm::TypeSize::getFixed(80); })
989  .Case<Float128Type>([](Type) { return llvm::TypeSize::getFixed(128); })
990  .Case<IntegerType>([](IntegerType intTy) {
991  return llvm::TypeSize::getFixed(intTy.getWidth());
992  })
993  .Case<LLVMPPCFP128Type>(
994  [](Type) { return llvm::TypeSize::getFixed(128); })
995  .Case<LLVMFixedVectorType>([](LLVMFixedVectorType t) {
996  llvm::TypeSize elementSize =
997  getPrimitiveTypeSizeInBits(t.getElementType());
998  return llvm::TypeSize(elementSize.getFixedValue() * t.getNumElements(),
999  elementSize.isScalable());
1000  })
1001  .Case<VectorType>([](VectorType t) {
1002  assert(isCompatibleVectorType(t) &&
1003  "unexpected incompatible with LLVM vector type");
1004  llvm::TypeSize elementSize =
1005  getPrimitiveTypeSizeInBits(t.getElementType());
1006  return llvm::TypeSize(elementSize.getFixedValue() * t.getNumElements(),
1007  elementSize.isScalable());
1008  })
1009  .Default([](Type ty) {
1010  assert((llvm::isa<LLVMVoidType, LLVMLabelType, LLVMMetadataType,
1011  LLVMTokenType, LLVMStructType, LLVMArrayType,
1012  LLVMPointerType, LLVMFunctionType, LLVMTargetExtType>(
1013  ty)) &&
1014  "unexpected missing support for primitive type");
1015  return llvm::TypeSize::getFixed(0);
1016  });
1017 }
1018 
1019 //===----------------------------------------------------------------------===//
1020 // LLVMDialect
1021 //===----------------------------------------------------------------------===//
1022 
1023 void LLVMDialect::registerTypes() {
1024  addTypes<
1025 #define GET_TYPEDEF_LIST
1026 #include "mlir/Dialect/LLVMIR/LLVMTypes.cpp.inc"
1027  >();
1028 }
1029 
1031  return detail::parseType(parser);
1032 }
1033 
1034 void LLVMDialect::printType(Type type, DialectAsmPrinter &os) const {
1035  return detail::printType(type, os);
1036 }
static uint64_t getIndexBitwidth(DataLayoutEntryListRef params)
Returns the bitwidth of the index type if specified in the param list.
static MLIRContext * getContext(OpFoldResult val)
constexpr static const uint64_t kDefaultPointerAlignment
Definition: LLVMTypes.cpp:260
static void printExtTypeParams(AsmPrinter &p, ArrayRef< Type > typeParams, ArrayRef< unsigned int > intParams)
Definition: LLVMTypes.cpp:122
constexpr static const uint64_t kDefaultPointerSizeBits
Definition: LLVMTypes.cpp:259
static LLVM_ATTRIBUTE_UNUSED OptionalParseResult generatedTypeParser(AsmParser &parser, StringRef *mnemonic, Type &value)
These are unused for now.
static void printFunctionTypes(AsmPrinter &p, ArrayRef< Type > params, bool isVarArg)
Definition: LLVMTypes.cpp:66
static bool isCompatibleImpl(Type type, DenseSet< Type > &compatibleTypes)
Definition: LLVMTypes.cpp:800
static ParseResult parseExtTypeParams(AsmParser &p, SmallVectorImpl< Type > &typeParams, SmallVectorImpl< unsigned int > &intParams)
Parses the parameter list for a target extension type.
Definition: LLVMTypes.cpp:90
static LLVM_ATTRIBUTE_UNUSED LogicalResult generatedTypePrinter(Type def, AsmPrinter &printer)
static constexpr llvm::StringRef kSpirvPrefix
Definition: LLVMTypes.cpp:734
static LogicalResult verifyVectorConstructionInvariants(function_ref< InFlightDiagnostic()> emitError, Type elementType, unsigned numElements)
Verifies that the type about to be constructed is well-formed.
Definition: LLVMTypes.cpp:661
static ParseResult parseFunctionTypes(AsmParser &p, SmallVector< Type > &params, bool &isVarArg)
Definition: LLVMTypes.cpp:36
constexpr static const uint64_t kBitsInByte
Definition: LLVMTypes.cpp:30
static constexpr llvm::StringRef kArmSVCount
Definition: LLVMTypes.cpp:735
static std::optional< uint64_t > getPointerDataLayoutEntry(DataLayoutEntryListRef params, LLVMPointerType type, PtrDLEntryPos pos)
Returns the part of the data layout entry that corresponds to pos for the given type by interpreting ...
Definition: LLVMTypes.cpp:276
static std::optional< uint64_t > getStructDataLayoutEntry(DataLayoutEntryListRef params, LLVMStructType type, StructDLEntryPos pos)
Definition: LLVMTypes.cpp:538
static uint64_t extractStructSpecValue(Attribute attr, StructDLEntryPos pos)
Definition: LLVMTypes.cpp:594
static uint64_t calculateStructAlignment(const DataLayout &dataLayout, DataLayoutEntryListRef params, LLVMStructType type, StructDLEntryPos pos)
Definition: LLVMTypes.cpp:556
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
Definition: SPIRVOps.cpp:215
static int64_t getNumElements(ShapedType type)
Definition: TensorOps.cpp:1545
This base class exposes generic asm parser hooks, usable across the various derived parsers.
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseOptionalRParen()=0
Parse a ) token if present.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalComma()=0
Parse a , token if present.
virtual ParseResult parseOptionalEllipsis()=0
Parse a ... token if present;.
This base class exposes generic asm printer hooks, usable across the various derived printers.
Attributes are known-constant values of operations.
Definition: Attributes.h:25
The main mechanism for performing data layout queries.
std::optional< uint64_t > getTypeIndexBitwidth(Type t) const
Returns the bitwidth that should be used when performing index computations for the given pointer-lik...
llvm::TypeSize getTypeSize(Type t) const
Returns the size of the given type in the current scope.
uint64_t getTypePreferredAlignment(Type t) const
Returns the preferred of the given type in the current scope.
uint64_t getTypeABIAlignment(Type t) const
Returns the required alignment of the given type in the current scope.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
The DialectAsmParser has methods for interacting with the asm parser when parsing attributes and type...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:313
LLVM dialect structure type representing a collection of different-typed elements manipulated togethe...
Definition: LLVMTypes.h:108
static LLVMStructType getLiteralChecked(function_ref< InFlightDiagnostic()> emitError, MLIRContext *context, ArrayRef< Type > types, bool isPacked=false)
Definition: LLVMTypes.cpp:459
LogicalResult setBody(ArrayRef< Type > types, bool isPacked)
Set the body of an identified struct.
Definition: LLVMTypes.cpp:475
static bool isValidElementType(Type type)
Checks if the given type can be contained in a structure type.
Definition: LLVMTypes.cpp:419
uint64_t getABIAlignment(const DataLayout &dataLayout, DataLayoutEntryListRef params) const
Definition: LLVMTypes.cpp:581
StringRef getName()
Returns the name of an identified struct.
Definition: LLVMTypes.cpp:489
static LLVMStructType getOpaqueChecked(function_ref< InFlightDiagnostic()> emitError, MLIRContext *context, StringRef name)
Definition: LLVMTypes.cpp:470
LogicalResult verifyEntries(DataLayoutEntryListRef entries, Location loc) const
Definition: LLVMTypes.cpp:622
bool isPacked() const
Checks if a struct is packed.
Definition: LLVMTypes.cpp:482
static LLVMStructType getIdentifiedChecked(function_ref< InFlightDiagnostic()> emitError, MLIRContext *context, StringRef name)
Definition: LLVMTypes.cpp:430
ArrayRef< Type > getBody() const
Returns the list of element types contained in a non-opaque struct.
Definition: LLVMTypes.cpp:490
bool isInitialized()
Checks if a struct is initialized.
Definition: LLVMTypes.cpp:488
bool isOpaque()
Checks if a struct is opaque.
Definition: LLVMTypes.cpp:484
static LogicalResult verify(function_ref< InFlightDiagnostic()> emitError, StringRef, bool)
Verifies that the type about to be constructed is well-formed.
Definition: LLVMTypes.cpp:495
bool areCompatible(DataLayoutEntryListRef oldLayout, DataLayoutEntryListRef newLayout) const
Definition: LLVMTypes.cpp:599
llvm::TypeSize getTypeSizeInBits(const DataLayout &dataLayout, DataLayoutEntryListRef params) const
Hooks for DataLayoutTypeInterface.
Definition: LLVMTypes.cpp:511
static LLVMStructType getLiteral(MLIRContext *context, ArrayRef< Type > types, bool isPacked=false)
Gets or creates a literal struct with the given body in the provided context.
Definition: LLVMTypes.cpp:453
static LLVMStructType getNewIdentified(MLIRContext *context, StringRef name, ArrayRef< Type > elements, bool isPacked=false)
Gets a new identified struct with the given body.
Definition: LLVMTypes.cpp:436
static LLVMStructType getIdentified(MLIRContext *context, StringRef name)
Gets or creates an identified struct with the given name in the provided context.
Definition: LLVMTypes.cpp:425
static LLVMStructType getOpaque(StringRef name, MLIRContext *context)
Gets or creates an intentionally-opaque identified struct.
Definition: LLVMTypes.cpp:465
uint64_t getPreferredAlignment(const DataLayout &dataLayout, DataLayoutEntryListRef params) const
Definition: LLVMTypes.cpp:588
bool isIdentified() const
Checks if a struct is identified.
Definition: LLVMTypes.cpp:483
static constexpr StringLiteral name
Definition: LLVMTypes.h:113
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
This class implements Optional functionality for ParseResult.
Definition: OpDefinition.h:39
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:36
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
Definition: Types.cpp:35
bool isInteger() const
Return true if this is an integer type (with the specified width).
Definition: Types.cpp:59
ImplType * getImpl() const
Utility for easy access to the storage instance.
void printType(Type type, AsmPrinter &printer)
Prints an LLVM Dialect type.
Type parseType(DialectAsmParser &parser)
Parses an LLVM dialect type.
Type getVectorType(Type elementType, unsigned numElements, bool isScalable=false)
Creates an LLVM dialect-compatible vector type with the given element type and length.
Definition: LLVMTypes.cpp:926
llvm::TypeSize getPrimitiveTypeSizeInBits(Type type)
Returns the size of the given primitive LLVM dialect-compatible type (including vectors) in bits,...
Definition: LLVMTypes.cpp:979
void printPrettyLLVMType(AsmPrinter &p, Type type)
Print any MLIR type or a concise syntax for LLVM types.
bool isScalableVectorType(Type vectorType)
Returns whether a vector type is scalable or not.
Definition: LLVMTypes.cpp:917
ParseResult parsePrettyLLVMType(AsmParser &p, Type &type)
Parse any MLIR type or a concise syntax for LLVM types.
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:874
bool isCompatibleOuterType(Type type)
Returns true if the given outer type is compatible with the LLVM dialect without checking its potenti...
Definition: LLVMTypes.cpp:763
Type getFixedVectorType(Type elementType, unsigned numElements)
Creates an LLVM dialect-compatible type with the given element type and length.
Definition: LLVMTypes.cpp:953
PtrDLEntryPos
The positions of different values in the data layout entry for pointers.
Definition: LLVMTypes.h:286
std::optional< uint64_t > extractPointerSpecValue(Attribute attr, PtrDLEntryPos pos)
Returns the value that corresponds to named position pos from the data layout entry attr assuming it'...
Definition: LLVMTypes.cpp:262
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:856
Type getScalableVectorType(Type elementType, unsigned numElements)
Creates an LLVM dialect-compatible type with the given element type and length.
Definition: LLVMTypes.cpp:964
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:869
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
Definition: LLVMTypes.cpp:899
Type getVectorElementType(Type type)
Returns the element type of any vector type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:890
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
Operation * clone(OpBuilder &b, Operation *op, TypeRange newResultTypes, ValueRange newOperands)
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
Type parseType(llvm::StringRef typeStr, MLIRContext *context, size_t *numRead=nullptr, bool isKnownNullTerminated=false)
This parses a single MLIR type to an MLIR context if it was valid.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition: Verifier.cpp:421