MLIR 23.0.0git
LLVMAttrs.cpp
Go to the documentation of this file.
1//===- LLVMAttrs.cpp - LLVM Attributes registration -----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the attribute details for the LLVM IR dialect in MLIR.
10//
11//===----------------------------------------------------------------------===//
12
17#include "mlir/IR/Builders.h"
20#include "llvm/ADT/StringExtras.h"
21#include "llvm/ADT/TypeSwitch.h"
22#include "llvm/BinaryFormat/Dwarf.h"
23
24using namespace mlir;
25using namespace mlir::LLVM;
26
27/// Parses DWARF expression arguments with respect to the DWARF operation
28/// opcode. Some DWARF expression operations have a specific number of operands
29/// and may appear in a textual form.
30static ParseResult parseExpressionArg(AsmParser &parser, uint64_t opcode,
32
33/// Prints DWARF expression arguments with respect to the specific DWARF
34/// operation. Some operands are printed in their textual form.
35static void printExpressionArg(AsmPrinter &printer, uint64_t opcode,
37
38#include "mlir/Dialect/LLVMIR/LLVMAttrInterfaces.cpp.inc"
39#include "mlir/Dialect/LLVMIR/LLVMOpsEnums.cpp.inc"
40#define GET_ATTRDEF_CLASSES
41#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc"
42
43//===----------------------------------------------------------------------===//
44// LLVMDialect registration
45//===----------------------------------------------------------------------===//
46
47void LLVMDialect::registerAttributes() {
48 addAttributes<
49#define GET_ATTRDEF_LIST
50#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc"
51
52 >();
53}
54
55//===----------------------------------------------------------------------===//
56// AddressSpaceAttr
57//===----------------------------------------------------------------------===//
58
59/// Checks whether the given type is an LLVM type that can be loaded or stored.
61 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
62 const ::mlir::DataLayout *dataLayout,
64 if (!isLoadableType(type)) {
65 if (emitError)
66 emitError() << "type must be LLVM type with size, but got " << type;
67 return false;
68 }
69 if (ordering == ptr::AtomicOrdering::not_atomic)
70 return true;
71
72 // To check atomic validity we need a datalayout.
73 if (!dataLayout) {
74 if (emitError)
75 emitError() << "expected a valid data layout";
76 return false;
77 }
78 if (!isTypeCompatibleWithAtomicOp(type, *dataLayout)) {
79 if (emitError)
80 emitError() << "unsupported type " << type << " for atomic access";
81 return false;
82 }
83 return true;
84}
85
86bool AddressSpaceAttr::isValidLoad(
87 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
88 const ::mlir::DataLayout *dataLayout,
90 return detail::isValidLoadStoreImpl(type, ordering, alignment, dataLayout,
91 emitError);
92}
93
94bool AddressSpaceAttr::isValidStore(
95 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
96 const ::mlir::DataLayout *dataLayout,
98 return detail::isValidLoadStoreImpl(type, ordering, alignment, dataLayout,
99 emitError);
100}
101
102bool AddressSpaceAttr::isValidAtomicOp(
103 ptr::AtomicBinOp op, Type type, ptr::AtomicOrdering ordering,
104 std::optional<int64_t> alignment, const ::mlir::DataLayout *dataLayout,
106 // TODO: update this method once `ptr.atomic_rmw` is implemented.
107 assert(false && "unimplemented, see TODO in the source.");
108 return false;
109}
110
111bool AddressSpaceAttr::isValidAtomicXchg(
112 Type type, ptr::AtomicOrdering successOrdering,
113 ptr::AtomicOrdering failureOrdering, std::optional<int64_t> alignment,
114 const ::mlir::DataLayout *dataLayout,
116 // TODO: update this method once `ptr.atomic_cmpxchg` is implemented.
117 assert(false && "unimplemented, see TODO in the source.");
118 return false;
119}
120
121bool AddressSpaceAttr::isValidAddrSpaceCast(
123 // TODO: update this method once the `ptr.addrspace_cast` op is added to the
124 // dialect.
125 assert(false && "unimplemented, see TODO in the source.");
126 return false;
127}
128
129bool AddressSpaceAttr::isValidPtrIntCast(
130 Type intLikeTy, Type ptrLikeTy,
132 // TODO: update this method once the int-cast ops are added to the `ptr`
133 // dialect.
134 assert(false && "unimplemented, see TODO in the source.");
135 return false;
136}
137
138//===----------------------------------------------------------------------===//
139// AliasScopeAttr
140//===----------------------------------------------------------------------===//
141
142LogicalResult
143AliasScopeAttr::verify(function_ref<InFlightDiagnostic()> emitError,
144 Attribute id, AliasScopeDomainAttr domain,
145 StringAttr description) {
146 (void)domain;
147 (void)description;
148 if (!llvm::isa<StringAttr, DistinctAttr>(id))
149 return emitError()
150 << "id of an alias scope must be a StringAttr or a DistrinctAttr";
151
152 return success();
153}
154
155//===----------------------------------------------------------------------===//
156// DINodeAttr
157//===----------------------------------------------------------------------===//
158
160 return llvm::isa<
161 DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr,
162 DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr, DIGenericSubrangeAttr,
163 DIGlobalVariableAttr, DIImportedEntityAttr, DILabelAttr,
164 DILexicalBlockAttr, DILexicalBlockFileAttr, DILocalVariableAttr,
165 DIModuleAttr, DINamespaceAttr, DINullTypeAttr, DIAnnotationAttr,
166 DIStringTypeAttr, DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>(
167 attr);
168}
169
170//===----------------------------------------------------------------------===//
171// DIScopeAttr
172//===----------------------------------------------------------------------===//
173
175 return llvm::isa<DICommonBlockAttr, DICompileUnitAttr, DICompositeTypeAttr,
176 DIDerivedTypeAttr, DIFileAttr, DILocalScopeAttr,
177 DIModuleAttr, DINamespaceAttr>(attr);
178}
179
180//===----------------------------------------------------------------------===//
181// DILocalScopeAttr
182//===----------------------------------------------------------------------===//
183
185 return llvm::isa<DILexicalBlockAttr, DILexicalBlockFileAttr,
186 DISubprogramAttr>(attr);
187}
188
189//===----------------------------------------------------------------------===//
190// DIVariableAttr
191//===----------------------------------------------------------------------===//
192
194 return llvm::isa<DILocalVariableAttr, DIGlobalVariableAttr>(attr);
195}
196
197//===----------------------------------------------------------------------===//
198// DITypeAttr
199//===----------------------------------------------------------------------===//
200
202 return llvm::isa<DINullTypeAttr, DIBasicTypeAttr, DICompositeTypeAttr,
203 DIDerivedTypeAttr, DIStringTypeAttr, DISubroutineTypeAttr>(
204 attr);
205}
206
207//===----------------------------------------------------------------------===//
208// TBAANodeAttr
209//===----------------------------------------------------------------------===//
210
212 return llvm::isa<TBAATypeDescriptorAttr, TBAARootAttr>(attr);
213}
214
215//===----------------------------------------------------------------------===//
216// MemoryEffectsAttr
217//===----------------------------------------------------------------------===//
218
219MemoryEffectsAttr MemoryEffectsAttr::get(MLIRContext *context,
220 ArrayRef<ModRefInfo> memInfoArgs) {
221 if (memInfoArgs.empty())
222 return MemoryEffectsAttr::get(context, /*other=*/ModRefInfo::ModRef,
223 /*argMem=*/ModRefInfo::ModRef,
224 /*inaccessibleMem=*/ModRefInfo::ModRef,
225 /*errnoMem=*/ModRefInfo::ModRef,
226 /*targetMem0=*/ModRefInfo::ModRef,
227 /*targetMem1=*/ModRefInfo::ModRef);
228 if (memInfoArgs.size() == 6)
229 return MemoryEffectsAttr::get(context, memInfoArgs[0], memInfoArgs[1],
230 memInfoArgs[2], memInfoArgs[3],
231 memInfoArgs[4], memInfoArgs[5]);
232 return {};
233}
234
235bool MemoryEffectsAttr::isReadWrite() {
236 if (this->getArgMem() != ModRefInfo::ModRef)
237 return false;
238 if (this->getInaccessibleMem() != ModRefInfo::ModRef)
239 return false;
240 if (this->getOther() != ModRefInfo::ModRef)
241 return false;
242 if (this->getErrnoMem() != ModRefInfo::ModRef)
243 return false;
244 if (this->getTargetMem0() != ModRefInfo::ModRef)
245 return false;
246 if (this->getTargetMem1() != ModRefInfo::ModRef)
247 return false;
248 return true;
249}
250
251//===----------------------------------------------------------------------===//
252// DIExpression
253//===----------------------------------------------------------------------===//
254
255DIExpressionAttr DIExpressionAttr::get(MLIRContext *context) {
256 return get(context, ArrayRef<DIExpressionElemAttr>({}));
257}
258
259ParseResult parseExpressionArg(AsmParser &parser, uint64_t opcode,
260 SmallVector<uint64_t> &args) {
261 auto operandParser = [&]() -> LogicalResult {
262 uint64_t operand = 0;
263 if (!args.empty() && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
264 // Attempt to parse a keyword.
265 StringRef keyword;
266 if (succeeded(parser.parseOptionalKeyword(&keyword))) {
267 operand = llvm::dwarf::getAttributeEncoding(keyword);
268 if (operand == 0) {
269 // The keyword is invalid.
270 return parser.emitError(parser.getCurrentLocation())
271 << "encountered unknown attribute encoding \"" << keyword
272 << "\"";
273 }
274 }
275 }
276
277 // operand should be non-zero if a keyword was parsed. Otherwise, the
278 // operand MUST be an integer.
279 if (operand == 0) {
280 // Parse the next operand as an integer.
281 if (parser.parseInteger(operand)) {
282 return parser.emitError(parser.getCurrentLocation())
283 << "expected integer operand";
284 }
285 }
286
287 args.push_back(operand);
288 return success();
289 };
290
291 // Parse operands as a comma-separated list.
292 return parser.parseCommaSeparatedList(operandParser);
293}
294
295void printExpressionArg(AsmPrinter &printer, uint64_t opcode,
296 ArrayRef<uint64_t> args) {
297 size_t i = 0;
298 llvm::interleaveComma(args, printer, [&](uint64_t operand) {
299 if (i > 0 && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
300 if (const StringRef keyword =
301 llvm::dwarf::AttributeEncodingString(operand);
302 !keyword.empty()) {
303 printer << keyword;
304 return;
305 }
306 }
307 // All operands are expected to be printed as integers.
308 printer << operand;
309 i++;
310 });
311}
312
313//===----------------------------------------------------------------------===//
314// DICompositeTypeAttr
315//===----------------------------------------------------------------------===//
316
317DIRecursiveTypeAttrInterface
318DICompositeTypeAttr::withRecId(DistinctAttr recId) {
319 return DICompositeTypeAttr::get(
320 getContext(), recId, getIsRecSelf(), getTag(), getName(), getFile(),
321 getLine(), getScope(), getBaseType(), getFlags(), getSizeInBits(),
322 getAlignInBits(), getDataLocation(), getRank(), getAllocated(),
323 getAssociated(), getElements());
324}
325
326DIRecursiveTypeAttrInterface
327DICompositeTypeAttr::getRecSelf(DistinctAttr recId) {
328 return DICompositeTypeAttr::get(recId.getContext(), recId, /*isRecSelf=*/true,
329 0, {}, {}, 0, {}, {}, DIFlags(), 0, 0, {}, {},
330 {}, {}, {});
331}
332
333//===----------------------------------------------------------------------===//
334// DICompileUnitAttr
335//===----------------------------------------------------------------------===//
336
337DIRecursiveTypeAttrInterface DICompileUnitAttr::withRecId(DistinctAttr recId) {
338 return DICompileUnitAttr::get(
339 getContext(), recId, getIsRecSelf(), getId(), getSourceLanguage(),
340 getFile(), getProducer(), getIsOptimized(), getEmissionKind(),
341 getIsDebugInfoForProfiling(), getNameTableKind(), getSplitDebugFilename(),
342 getImportedEntities());
343}
344
345DIRecursiveTypeAttrInterface DICompileUnitAttr::getRecSelf(DistinctAttr recId) {
346
347 return DICompileUnitAttr::get(
348 recId.getContext(), recId, /*isRecSelf=*/true, /*id=*/{},
349 /*sourceLanguage=*/0u, /*file=*/{}, /*producer=*/{},
350 /*isOptimized=*/false, DIEmissionKind::None,
351 /*isDebugInfoForProfiling=*/false, DINameTableKind::Default,
352 /*splitDebugFilename=*/{}, /*importedEntities=*/{});
353}
354
355//===----------------------------------------------------------------------===//
356// DISubprogramAttr
357//===----------------------------------------------------------------------===//
358
359DIRecursiveTypeAttrInterface DISubprogramAttr::withRecId(DistinctAttr recId) {
360 return DISubprogramAttr::get(getContext(), recId, getIsRecSelf(), getId(),
361 getCompileUnit(), getScope(), getName(),
362 getLinkageName(), getFile(), getLine(),
363 getScopeLine(), getSubprogramFlags(), getType(),
364 getRetainedNodes(), getAnnotations());
365}
366
367DIRecursiveTypeAttrInterface DISubprogramAttr::getRecSelf(DistinctAttr recId) {
368 return DISubprogramAttr::get(recId.getContext(), recId, /*isRecSelf=*/true,
369 {}, {}, {}, {}, {}, {}, 0, 0, {}, {}, {}, {});
370}
371
372//===----------------------------------------------------------------------===//
373// ConstantRangeAttr
374//===----------------------------------------------------------------------===//
375
376Attribute ConstantRangeAttr::parse(AsmParser &parser, Type odsType) {
377 llvm::SMLoc loc = parser.getCurrentLocation();
378 IntegerType widthType;
379 if (parser.parseLess() || parser.parseType(widthType) ||
380 parser.parseComma()) {
381 return Attribute{};
382 }
383 unsigned bitWidth = widthType.getWidth();
384 APInt lower(bitWidth, 0);
385 APInt upper(bitWidth, 0);
386 if (parser.parseInteger(lower) || parser.parseComma() ||
387 parser.parseInteger(upper) || parser.parseGreater())
388 return Attribute{};
389 // Non-positive numbers may use more bits than `bitWidth`
390 lower = lower.sextOrTrunc(bitWidth);
391 upper = upper.sextOrTrunc(bitWidth);
392 return parser.getChecked<ConstantRangeAttr>(loc, parser.getContext(), lower,
393 upper);
394}
395
396void ConstantRangeAttr::print(AsmPrinter &printer) const {
397 printer << "<i" << getLower().getBitWidth() << ", " << getLower() << ", "
398 << getUpper() << ">";
399}
400
401LogicalResult
402ConstantRangeAttr::verify(llvm::function_ref<InFlightDiagnostic()> emitError,
403 APInt lower, APInt upper) {
404 if (lower.getBitWidth() != upper.getBitWidth())
405 return emitError()
406 << "expected lower and upper to have matching bitwidths but got "
407 << lower.getBitWidth() << " vs. " << upper.getBitWidth();
408 return success();
409}
410
411//===----------------------------------------------------------------------===//
412// TargetFeaturesAttr
413//===----------------------------------------------------------------------===//
414
415TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
416 llvm::ArrayRef<StringRef> features) {
417 return Base::get(context,
418 llvm::map_to_vector(features, [&](StringRef feature) {
419 return StringAttr::get(context, feature);
420 }));
421}
422
423TargetFeaturesAttr
424TargetFeaturesAttr::getChecked(function_ref<InFlightDiagnostic()> emitError,
425 MLIRContext *context,
426 llvm::ArrayRef<StringRef> features) {
427 return Base::getChecked(emitError, context,
428 llvm::map_to_vector(features, [&](StringRef feature) {
429 return StringAttr::get(context, feature);
430 }));
431}
432
433TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
434 StringRef targetFeatures) {
435 SmallVector<StringRef> features;
436 targetFeatures.split(features, ',', /*MaxSplit=*/-1,
437 /*KeepEmpty=*/false);
438 return get(context, features);
439}
440
441TargetFeaturesAttr
442TargetFeaturesAttr::getChecked(function_ref<InFlightDiagnostic()> emitError,
443 MLIRContext *context, StringRef targetFeatures) {
444 SmallVector<StringRef> features;
445 targetFeatures.split(features, ',', /*MaxSplit=*/-1,
446 /*KeepEmpty=*/false);
447 ArrayRef featuresRef(features);
448 return getChecked(emitError, context, featuresRef);
449}
450
451LogicalResult
452TargetFeaturesAttr::verify(function_ref<InFlightDiagnostic()> emitError,
453 llvm::ArrayRef<StringAttr> features) {
454 for (StringAttr featureAttr : features) {
455 if (!featureAttr || featureAttr.empty())
456 return emitError() << "target features can not be null or empty";
457 auto feature = featureAttr.strref();
458 if (feature[0] != '+' && feature[0] != '-')
459 return emitError() << "target features must start with '+' or '-'";
460 if (feature.contains(','))
461 return emitError() << "target features can not contain ','";
462 }
463 return success();
464}
465
466bool TargetFeaturesAttr::contains(StringAttr feature) const {
467 if (nullOrEmpty())
468 return false;
469 // Note: Using StringAttr does pointer comparisons.
470 return llvm::is_contained(getFeatures(), feature);
471}
472
473bool TargetFeaturesAttr::contains(StringRef feature) const {
474 if (nullOrEmpty())
475 return false;
476 return llvm::is_contained(getFeatures(), feature);
477}
478
479std::string TargetFeaturesAttr::getFeaturesString() const {
480 std::string featuresString;
481 llvm::raw_string_ostream ss(featuresString);
482 llvm::interleave(
483 getFeatures(), ss, [&](auto &feature) { ss << feature.strref(); }, ",");
484 return featuresString;
485}
486
487TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
488 auto parentFunction = op->getParentOfType<FunctionOpInterface>();
489 if (!parentFunction)
490 return {};
491 return parentFunction.getOperation()->getAttrOfType<TargetFeaturesAttr>(
492 getAttributeName());
493}
494
495FailureOr<Attribute> TargetFeaturesAttr::query(DataLayoutEntryKey key) {
496 auto stringKey = dyn_cast<StringAttr>(key);
497 if (!stringKey)
498 return failure();
499
500 if (contains(stringKey))
501 return UnitAttr::get(getContext());
502
503 if (contains((std::string("+") + stringKey.strref()).str()))
504 return BoolAttr::get(getContext(), true);
505
506 if (contains((std::string("-") + stringKey.strref()).str()))
507 return BoolAttr::get(getContext(), false);
508
509 return failure();
510}
511
512//===----------------------------------------------------------------------===//
513// TargetAttr
514//===----------------------------------------------------------------------===//
515
516FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
517 if (auto stringAttrKey = dyn_cast<StringAttr>(key)) {
518 if (stringAttrKey.getValue() == "triple")
519 return getTriple();
520 if (stringAttrKey.getValue() == "chip")
521 return getChip();
522 if (stringAttrKey.getValue() == "features" && getFeatures())
523 return getFeatures();
524 }
525 return failure();
526}
527
528//===----------------------------------------------------------------------===//
529// ModuleFlagAttr
530//===----------------------------------------------------------------------===//
531
532LogicalResult
533ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
534 LLVM::ModFlagBehavior flagBehavior, StringAttr key,
535 Attribute value) {
536 if (key == LLVMDialect::getModuleFlagKeyCGProfileName()) {
537 auto arrayAttr = dyn_cast<ArrayAttr>(value);
538 if ((!arrayAttr) || (!llvm::all_of(arrayAttr, [](Attribute attr) {
539 return isa<ModuleFlagCGProfileEntryAttr>(attr);
540 })))
541 return emitError()
542 << "'CG Profile' key expects an array of '#llvm.cgprofile_entry'";
543 return success();
544 }
545
546 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName()) {
547 if (!isa<ModuleFlagProfileSummaryAttr>(value))
548 return emitError() << "'ProfileSummary' key expects a "
549 "'#llvm.profile_summary' attribute";
550 return success();
551 }
552
553 if (isa<IntegerAttr, StringAttr>(value))
554 return success();
555
556 // Allow non-empty ArrayAttr of StringAttrs to represent MDTuples of
557 // MDStrings (e.g. the "riscv-isa" module flag). Integer values within
558 // MDTuples are not handled here because integer module flags are encoded as
559 // ConstantAsMetadata at the top level (not as MDTuples), so no known use
560 // case requires an array-of-integers representation.
561 if (auto arrayAttr = dyn_cast<ArrayAttr>(value))
562 if (!arrayAttr.empty() &&
563 llvm::all_of(arrayAttr, [](Attribute a) { return isa<StringAttr>(a); }))
564 return success();
565
566 return emitError() << "only integer, string, and string-array values are "
567 "currently supported for unknown key '"
568 << key << "'";
569}
return success()
static void printExpressionArg(AsmPrinter &printer, uint64_t opcode, ArrayRef< uint64_t > args)
Prints DWARF expression arguments with respect to the specific DWARF operation.
static ParseResult parseExpressionArg(AsmParser &parser, uint64_t opcode, SmallVector< uint64_t > &args)
Parses DWARF expression arguments with respect to the DWARF operation opcode.
b getContext())
static bool contains(SMRange range, SMLoc loc)
Returns true if the given range contains the given source location.
This base class exposes generic asm parser hooks, usable across the various derived parsers.
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 parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseLess()=0
Parse a '<' token.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
auto getChecked(SMLoc loc, ParamsT &&...params)
Invoke the getChecked method of the given Attribute or Type class, using the provided location to emi...
virtual ParseResult parseGreater()=0
Parse a '>' token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseComma()=0
Parse a , token.
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
MLIRContext * getContext() const
Return the context this attribute belongs to.
static BoolAttr get(MLIRContext *context, bool value)
This class represents a diagnostic that is inflight and set to be reported.
This class represents a LLVM attribute that describes a local debug info scope.
Definition LLVMAttrs.h:48
static bool classof(Attribute attr)
Support LLVM type casting.
constexpr Attribute()=default
static bool classof(Attribute attr)
static bool classof(Attribute attr)
Support LLVM type casting.
static bool classof(Attribute attr)
Support LLVM type casting.
static bool classof(Attribute attr)
Support LLVM type casting.
static bool classof(Attribute attr)
Support LLVM type casting.
constexpr Attribute()=default
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
Definition Operation.h:256
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
bool isValidLoadStoreImpl(Type type, ptr::AtomicOrdering ordering, std::optional< int64_t > alignment, const ::mlir::DataLayout *dataLayout, function_ref< InFlightDiagnostic()> emitError)
Checks whether the given type is an LLVM type that can be loaded or stored.
Definition LLVMAttrs.cpp:60
bool isLoadableType(Type type)
Returns true if the given type is a loadable type compatible with the LLVM dialect.
bool isTypeCompatibleWithAtomicOp(Type type, const DataLayout &dataLayout)
Returns true if the given type is supported by atomic operations.
Include the generated interface declarations.
llvm::PointerUnion< Type, StringAttr > DataLayoutEntryKey
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
Definition Utils.cpp:307
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto getChecked(function_ref< InFlightDiagnostic()> emitError, MLIRContext *context, Ts &&...params)
Helper method analogous to get, but uses getChecked when available to allow graceful failure on inval...
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
llvm::function_ref< Fn > function_ref
Definition LLVM.h:147