MLIR  19.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 
37  bool &isVarArg) {
38  isVarArg = false;
39  // `(` `)`
41  return success();
42 
43  // `(` `...` `)`
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())) {
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, unsigned 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, unsigned numElements) {
165  assert(elementType && "expected non-null subtype");
166  return Base::getChecked(emitError, elementType.getContext(), elementType,
167  numElements);
168 }
169 
172  Type elementType, unsigned 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 
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 
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 
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 
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 
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  Float8E4M3FNType,
773  Float8E5M2Type,
774  LLVMArrayType,
775  LLVMFunctionType,
776  LLVMLabelType,
777  LLVMMetadataType,
778  LLVMPPCFP128Type,
779  LLVMPointerType,
781  LLVMTokenType,
782  LLVMFixedVectorType,
783  LLVMScalableVectorType,
784  LLVMTargetExtType,
785  LLVMVoidType,
786  LLVMX86MMXType
787  >(type)) {
788  // clang-format on
789  return true;
790  }
791 
792  // Only signless integers are compatible.
793  if (auto intType = llvm::dyn_cast<IntegerType>(type))
794  return intType.isSignless();
795 
796  // 1D vector types are compatible.
797  if (auto vecType = llvm::dyn_cast<VectorType>(type))
798  return vecType.getRank() == 1;
799 
800  return false;
801 }
802 
803 static bool isCompatibleImpl(Type type, DenseSet<Type> &compatibleTypes) {
804  if (!compatibleTypes.insert(type).second)
805  return true;
806 
807  auto isCompatible = [&](Type type) {
808  return isCompatibleImpl(type, compatibleTypes);
809  };
810 
811  bool result =
813  .Case<LLVMStructType>([&](auto structType) {
814  return llvm::all_of(structType.getBody(), isCompatible);
815  })
816  .Case<LLVMFunctionType>([&](auto funcType) {
817  return isCompatible(funcType.getReturnType()) &&
818  llvm::all_of(funcType.getParams(), isCompatible);
819  })
820  .Case<IntegerType>([](auto intType) { return intType.isSignless(); })
821  .Case<VectorType>([&](auto vecType) {
822  return vecType.getRank() == 1 &&
823  isCompatible(vecType.getElementType());
824  })
825  .Case<LLVMPointerType>([&](auto pointerType) { return true; })
826  .Case<LLVMTargetExtType>([&](auto extType) {
827  return llvm::all_of(extType.getTypeParams(), isCompatible);
828  })
829  // clang-format off
830  .Case<
831  LLVMFixedVectorType,
832  LLVMScalableVectorType,
833  LLVMArrayType
834  >([&](auto containerType) {
835  return isCompatible(containerType.getElementType());
836  })
837  .Case<
838  BFloat16Type,
839  Float16Type,
840  Float32Type,
841  Float64Type,
842  Float80Type,
843  Float128Type,
844  Float8E4M3FNType,
845  Float8E5M2Type,
846  LLVMLabelType,
847  LLVMMetadataType,
848  LLVMPPCFP128Type,
849  LLVMTokenType,
850  LLVMVoidType,
851  LLVMX86MMXType
852  >([](Type) { return true; })
853  // clang-format on
854  .Default([](Type) { return false; });
855 
856  if (!result)
857  compatibleTypes.erase(type);
858 
859  return result;
860 }
861 
863  if (auto *llvmDialect =
864  type.getContext()->getLoadedDialect<LLVM::LLVMDialect>())
865  return isCompatibleImpl(type, llvmDialect->compatibleTypes.get());
866 
867  DenseSet<Type> localCompatibleTypes;
868  return isCompatibleImpl(type, localCompatibleTypes);
869 }
870 
872  return LLVMDialect::isCompatibleType(type);
873 }
874 
876  return llvm::isa<BFloat16Type, Float16Type, Float32Type, Float64Type,
877  Float80Type, Float128Type, LLVMPPCFP128Type>(type);
878 }
879 
881  if (llvm::isa<LLVMFixedVectorType, LLVMScalableVectorType>(type))
882  return true;
883 
884  if (auto vecType = llvm::dyn_cast<VectorType>(type)) {
885  if (vecType.getRank() != 1)
886  return false;
887  Type elementType = vecType.getElementType();
888  if (auto intType = llvm::dyn_cast<IntegerType>(elementType))
889  return intType.isSignless();
890  return llvm::isa<BFloat16Type, Float16Type, Float32Type, Float64Type,
891  Float80Type, Float128Type>(elementType);
892  }
893  return false;
894 }
895 
897  return llvm::TypeSwitch<Type, Type>(type)
898  .Case<LLVMFixedVectorType, LLVMScalableVectorType, VectorType>(
899  [](auto ty) { return ty.getElementType(); })
900  .Default([](Type) -> Type {
901  llvm_unreachable("incompatible with LLVM vector type");
902  });
903 }
904 
905 llvm::ElementCount mlir::LLVM::getVectorNumElements(Type type) {
907  .Case([](VectorType ty) {
908  if (ty.isScalable())
909  return llvm::ElementCount::getScalable(ty.getNumElements());
910  return llvm::ElementCount::getFixed(ty.getNumElements());
911  })
912  .Case([](LLVMFixedVectorType ty) {
913  return llvm::ElementCount::getFixed(ty.getNumElements());
914  })
915  .Case([](LLVMScalableVectorType ty) {
916  return llvm::ElementCount::getScalable(ty.getMinNumElements());
917  })
918  .Default([](Type) -> llvm::ElementCount {
919  llvm_unreachable("incompatible with LLVM vector type");
920  });
921 }
922 
924  assert((llvm::isa<LLVMFixedVectorType, LLVMScalableVectorType, VectorType>(
925  vectorType)) &&
926  "expected LLVM-compatible vector type");
927  return !llvm::isa<LLVMFixedVectorType>(vectorType) &&
928  (llvm::isa<LLVMScalableVectorType>(vectorType) ||
929  llvm::cast<VectorType>(vectorType).isScalable());
930 }
931 
932 Type mlir::LLVM::getVectorType(Type elementType, unsigned numElements,
933  bool isScalable) {
934  bool useLLVM = LLVMFixedVectorType::isValidElementType(elementType);
935  bool useBuiltIn = VectorType::isValidElementType(elementType);
936  (void)useBuiltIn;
937  assert((useLLVM ^ useBuiltIn) && "expected LLVM-compatible fixed-vector type "
938  "to be either builtin or LLVM dialect type");
939  if (useLLVM) {
940  if (isScalable)
941  return LLVMScalableVectorType::get(elementType, numElements);
942  return LLVMFixedVectorType::get(elementType, numElements);
943  }
944 
945  // LLVM vectors are always 1-D, hence only 1 bool is required to mark it as
946  // scalable/non-scalable.
947  return VectorType::get(numElements, elementType, {isScalable});
948 }
949 
951  const llvm::ElementCount &numElements) {
952  if (numElements.isScalable())
953  return getVectorType(elementType, numElements.getKnownMinValue(),
954  /*isScalable=*/true);
955  return getVectorType(elementType, numElements.getFixedValue(),
956  /*isScalable=*/false);
957 }
958 
959 Type mlir::LLVM::getFixedVectorType(Type elementType, unsigned numElements) {
960  bool useLLVM = LLVMFixedVectorType::isValidElementType(elementType);
961  bool useBuiltIn = VectorType::isValidElementType(elementType);
962  (void)useBuiltIn;
963  assert((useLLVM ^ useBuiltIn) && "expected LLVM-compatible fixed-vector type "
964  "to be either builtin or LLVM dialect type");
965  if (useLLVM)
966  return LLVMFixedVectorType::get(elementType, numElements);
967  return VectorType::get(numElements, elementType);
968 }
969 
970 Type mlir::LLVM::getScalableVectorType(Type elementType, unsigned numElements) {
971  bool useLLVM = LLVMScalableVectorType::isValidElementType(elementType);
972  bool useBuiltIn = VectorType::isValidElementType(elementType);
973  (void)useBuiltIn;
974  assert((useLLVM ^ useBuiltIn) && "expected LLVM-compatible scalable-vector "
975  "type to be either builtin or LLVM dialect "
976  "type");
977  if (useLLVM)
978  return LLVMScalableVectorType::get(elementType, numElements);
979 
980  // LLVM vectors are always 1-D, hence only 1 bool is required to mark it as
981  // scalable/non-scalable.
982  return VectorType::get(numElements, elementType, /*scalableDims=*/true);
983 }
984 
986  assert(isCompatibleType(type) &&
987  "expected a type compatible with the LLVM dialect");
988 
990  .Case<BFloat16Type, Float16Type>(
991  [](Type) { return llvm::TypeSize::getFixed(16); })
992  .Case<Float32Type>([](Type) { return llvm::TypeSize::getFixed(32); })
993  .Case<Float64Type, LLVMX86MMXType>(
994  [](Type) { return llvm::TypeSize::getFixed(64); })
995  .Case<Float80Type>([](Type) { return llvm::TypeSize::getFixed(80); })
996  .Case<Float128Type>([](Type) { return llvm::TypeSize::getFixed(128); })
997  .Case<IntegerType>([](IntegerType intTy) {
998  return llvm::TypeSize::getFixed(intTy.getWidth());
999  })
1000  .Case<LLVMPPCFP128Type>(
1001  [](Type) { return llvm::TypeSize::getFixed(128); })
1002  .Case<LLVMFixedVectorType>([](LLVMFixedVectorType t) {
1003  llvm::TypeSize elementSize =
1004  getPrimitiveTypeSizeInBits(t.getElementType());
1005  return llvm::TypeSize(elementSize.getFixedValue() * t.getNumElements(),
1006  elementSize.isScalable());
1007  })
1008  .Case<VectorType>([](VectorType t) {
1009  assert(isCompatibleVectorType(t) &&
1010  "unexpected incompatible with LLVM vector type");
1011  llvm::TypeSize elementSize =
1012  getPrimitiveTypeSizeInBits(t.getElementType());
1013  return llvm::TypeSize(elementSize.getFixedValue() * t.getNumElements(),
1014  elementSize.isScalable());
1015  })
1016  .Default([](Type ty) {
1017  assert((llvm::isa<LLVMVoidType, LLVMLabelType, LLVMMetadataType,
1018  LLVMTokenType, LLVMStructType, LLVMArrayType,
1019  LLVMPointerType, LLVMFunctionType, LLVMTargetExtType>(
1020  ty)) &&
1021  "unexpected missing support for primitive type");
1022  return llvm::TypeSize::getFixed(0);
1023  });
1024 }
1025 
1026 //===----------------------------------------------------------------------===//
1027 // LLVMDialect
1028 //===----------------------------------------------------------------------===//
1029 
1030 void LLVMDialect::registerTypes() {
1031  addTypes<
1032 #define GET_TYPEDEF_LIST
1033 #include "mlir/Dialect/LLVMIR/LLVMTypes.cpp.inc"
1034  >();
1035 }
1036 
1038  return detail::parseType(parser);
1039 }
1040 
1041 void LLVMDialect::printType(Type type, DialectAsmPrinter &os) const {
1042  return detail::printType(type, os);
1043 }
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:803
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:216
static int64_t getNumElements(ShapedType type)
Definition: TensorOps.cpp:1541
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:308
LLVM dialect structure type representing a collection of different-typed elements manipulated togethe...
Definition: LLVMTypes.h:109
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:114
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 represents success/failure for parsing-like operations that find it important to chain tog...
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:58
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:932
llvm::TypeSize getPrimitiveTypeSizeInBits(Type type)
Returns the size of the given primitive LLVM dialect-compatible type (including vectors) in bits,...
Definition: LLVMTypes.cpp:985
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:923
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:880
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:959
PtrDLEntryPos
The positions of different values in the data layout entry for pointers.
Definition: LLVMTypes.h:287
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:862
Type getScalableVectorType(Type elementType, unsigned numElements)
Creates an LLVM dialect-compatible type with the given element type and length.
Definition: LLVMTypes.cpp:970
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:875
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
Definition: LLVMTypes.cpp:905
Type getVectorElementType(Type type)
Returns the element type of any vector type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:896
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
Definition: LogicalResult.h:68
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
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
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26