MLIR 24.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/STLExtras.h"
21#include "llvm/ADT/StringExtras.h"
22#include "llvm/ADT/TypeSwitch.h"
23#include "llvm/BinaryFormat/Dwarf.h"
24#include "llvm/IR/DebugInfoMetadata.h"
25#include "llvm/IR/LLVMContext.h"
26#include "llvm/Support/ErrorHandling.h"
27
28using namespace mlir;
29using namespace mlir::LLVM;
30
31/// Parses DWARF expression arguments with respect to the DWARF operation
32/// opcode. Some DWARF expression operations have a specific number of operands
33/// and may appear in a textual form.
34static ParseResult parseExpressionArg(AsmParser &parser, uint64_t opcode,
36
37/// Prints DWARF expression arguments with respect to the specific DWARF
38/// operation. Some operands are printed in their textual form.
39static void printExpressionArg(AsmPrinter &printer, uint64_t opcode,
41
42/// Parses a source language from either the historical inline `DW_LANG_*`
43/// syntax or a nested `DISourceLanguageNameAttr`.
44static ParseResult parseSourceLanguage(AsmParser &parser,
45 DISourceLanguageNameAttr &language);
46
47/// Prints an unversioned source language without a dialect using the
48/// historical inline `DW_LANG_*` syntax. All other source languages are
49/// printed as a nested `DISourceLanguageNameAttr`.
50static void printSourceLanguage(AsmPrinter &printer,
51 DISourceLanguageNameAttr language);
52
53#include "mlir/Dialect/LLVMIR/LLVMAttrInterfaces.cpp.inc"
54#include "mlir/Dialect/LLVMIR/LLVMOpsEnums.cpp.inc"
55#define GET_ATTRDEF_CLASSES
56#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc"
57
58//===----------------------------------------------------------------------===//
59// LLVMDialect registration
60//===----------------------------------------------------------------------===//
61
62void LLVMDialect::registerAttributes() {
63 addAttributes<
64#define GET_ATTRDEF_LIST
65#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc"
66
67 >();
68}
69
70//===----------------------------------------------------------------------===//
71// AddressSpaceAttr
72//===----------------------------------------------------------------------===//
73
74/// Checks whether the given type is an LLVM type that can be loaded or stored.
76 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
77 const ::mlir::DataLayout *dataLayout,
79 if (!isLoadableType(type)) {
80 if (emitError)
81 emitError() << "type must be LLVM type with size, but got " << type;
82 return false;
83 }
84 if (ordering == ptr::AtomicOrdering::not_atomic)
85 return true;
86
87 // To check atomic validity we need a datalayout.
88 if (!dataLayout) {
89 if (emitError)
90 emitError() << "expected a valid data layout";
91 return false;
92 }
93 if (!isTypeCompatibleWithAtomicOp(type, *dataLayout)) {
94 if (emitError)
95 emitError() << "unsupported type " << type << " for atomic access";
96 return false;
97 }
98 return true;
99}
100
101bool AddressSpaceAttr::isValidLoad(
102 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
103 const ::mlir::DataLayout *dataLayout,
105 return detail::isValidLoadStoreImpl(type, ordering, alignment, dataLayout,
106 emitError);
107}
108
109bool AddressSpaceAttr::isValidStore(
110 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
111 const ::mlir::DataLayout *dataLayout,
113 return detail::isValidLoadStoreImpl(type, ordering, alignment, dataLayout,
114 emitError);
115}
116
117bool AddressSpaceAttr::isValidAtomicOp(
118 ptr::AtomicBinOp op, Type type, ptr::AtomicOrdering ordering,
119 std::optional<int64_t> alignment, const ::mlir::DataLayout *dataLayout,
121 // TODO: update this method once `ptr.atomic_rmw` is implemented.
122 assert(false && "unimplemented, see TODO in the source.");
123 return false;
124}
125
126bool AddressSpaceAttr::isValidAtomicXchg(
127 Type type, ptr::AtomicOrdering successOrdering,
128 ptr::AtomicOrdering failureOrdering, std::optional<int64_t> alignment,
129 const ::mlir::DataLayout *dataLayout,
131 // TODO: update this method once `ptr.atomic_cmpxchg` is implemented.
132 assert(false && "unimplemented, see TODO in the source.");
133 return false;
134}
135
136bool AddressSpaceAttr::isValidAddrSpaceCast(
138 // TODO: update this method once the `ptr.addrspace_cast` op is added to the
139 // dialect.
140 assert(false && "unimplemented, see TODO in the source.");
141 return false;
142}
143
144bool AddressSpaceAttr::isValidPtrIntCast(
145 Type intLikeTy, Type ptrLikeTy,
147 // TODO: update this method once the int-cast ops are added to the `ptr`
148 // dialect.
149 assert(false && "unimplemented, see TODO in the source.");
150 return false;
151}
152
153//===----------------------------------------------------------------------===//
154// FunctionMetadataAttr
155//===----------------------------------------------------------------------===//
156
157static constexpr unsigned kReservedFunctionMetadataKinds[] = {
158 llvm::LLVMContext::MD_dbg, llvm::LLVMContext::MD_prof};
159
160static StringRef getFixedMetadataKindName(unsigned kind) {
161 switch (kind) {
162#define LLVM_FIXED_MD_KIND(EnumID, Name, Value) \
163 case llvm::LLVMContext::EnumID: \
164 return Name;
165#include "llvm/IR/FixedMetadataKinds.def"
166#undef LLVM_FIXED_MD_KIND
167 }
168 llvm_unreachable("unknown fixed metadata kind");
169}
170
171LogicalResult
172FunctionMetadataAttr::verify(function_ref<InFlightDiagnostic()> emitError,
173 StringAttr metadataName, MDNodeAttr node) {
174 (void)node;
175 StringRef name = metadataName.getValue();
176 if (name.empty())
177 return emitError() << "function_metadata entry name must not be empty";
178 if (llvm::any_of(kReservedFunctionMetadataKinds, [&](unsigned kind) {
179 return name == getFixedMetadataKindName(kind);
180 })) {
181 return emitError() << "reserved function_metadata entry '" << name
182 << "' is not supported by the generic carrier";
183 }
184 return success();
185}
186
187//===----------------------------------------------------------------------===//
188// AliasScopeAttr
189//===----------------------------------------------------------------------===//
190
191LogicalResult
192AliasScopeAttr::verify(function_ref<InFlightDiagnostic()> emitError,
193 Attribute id, AliasScopeDomainAttr domain,
194 StringAttr description) {
195 (void)domain;
196 (void)description;
197 if (!llvm::isa<StringAttr, DistinctAttr>(id))
198 return emitError()
199 << "id of an alias scope must be a StringAttr or a DistrinctAttr";
200
201 return success();
202}
203
204//===----------------------------------------------------------------------===//
205// DINodeAttr
206//===----------------------------------------------------------------------===//
207
209 return llvm::isa<
210 DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr,
211 DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr, DIGenericSubrangeAttr,
212 DIGlobalVariableAttr, DIImportedEntityAttr, DILabelAttr,
213 DILexicalBlockAttr, DILexicalBlockFileAttr, DILocalVariableAttr,
214 DIModuleAttr, DINamespaceAttr, DINullTypeAttr, DIAnnotationAttr,
215 DIStringTypeAttr, DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>(
216 attr);
217}
218
219//===----------------------------------------------------------------------===//
220// DIScopeAttr
221//===----------------------------------------------------------------------===//
222
224 return llvm::isa<DICommonBlockAttr, DICompileUnitAttr, DICompositeTypeAttr,
225 DIDerivedTypeAttr, DIFileAttr, DILocalScopeAttr,
226 DIModuleAttr, DINamespaceAttr>(attr);
227}
228
229//===----------------------------------------------------------------------===//
230// DILocalScopeAttr
231//===----------------------------------------------------------------------===//
232
234 return llvm::isa<DILexicalBlockAttr, DILexicalBlockFileAttr,
235 DISubprogramAttr>(attr);
236}
237
238//===----------------------------------------------------------------------===//
239// DIVariableAttr
240//===----------------------------------------------------------------------===//
241
243 return llvm::isa<DILocalVariableAttr, DIGlobalVariableAttr>(attr);
244}
245
246//===----------------------------------------------------------------------===//
247// DITypeAttr
248//===----------------------------------------------------------------------===//
249
251 return llvm::isa<DINullTypeAttr, DIBasicTypeAttr, DICompositeTypeAttr,
252 DIDerivedTypeAttr, DIStringTypeAttr, DISubroutineTypeAttr>(
253 attr);
254}
255
256//===----------------------------------------------------------------------===//
257// DIDerivedTypeAttr
258//===----------------------------------------------------------------------===//
259
260LogicalResult DIDerivedTypeAttr::verify(
261 function_ref<InFlightDiagnostic()> emitError, unsigned tag, StringAttr name,
262 DIFileAttr file, uint32_t line, DIScopeAttr scope, DITypeAttr baseType,
263 uint64_t sizeInBits, uint32_t alignInBits, uint64_t offsetInBits,
264 std::optional<unsigned> dwarfAddressSpace, DIFlags flags,
265 Attribute extraData) {
266 if (extraData && !llvm::isa<DINodeAttr, IntegerAttr>(extraData))
267 return emitError() << "extraData must be a DINodeAttr or an IntegerAttr";
268 return success();
269}
270
271//===----------------------------------------------------------------------===//
272// TBAANodeAttr
273//===----------------------------------------------------------------------===//
274
276 return llvm::isa<TBAATypeDescriptorAttr, TBAARootAttr>(attr);
277}
278
279//===----------------------------------------------------------------------===//
280// MemoryEffectsAttr
281//===----------------------------------------------------------------------===//
282
283MemoryEffectsAttr MemoryEffectsAttr::get(MLIRContext *context,
284 ArrayRef<ModRefInfo> memInfoArgs) {
285 if (memInfoArgs.empty())
286 return MemoryEffectsAttr::get(context, /*other=*/ModRefInfo::ModRef,
287 /*argMem=*/ModRefInfo::ModRef,
288 /*inaccessibleMem=*/ModRefInfo::ModRef,
289 /*errnoMem=*/ModRefInfo::ModRef,
290 /*targetMem0=*/ModRefInfo::ModRef,
291 /*targetMem1=*/ModRefInfo::ModRef);
292 if (memInfoArgs.size() == 6)
293 return MemoryEffectsAttr::get(context, memInfoArgs[0], memInfoArgs[1],
294 memInfoArgs[2], memInfoArgs[3],
295 memInfoArgs[4], memInfoArgs[5]);
296 return {};
297}
298
299bool MemoryEffectsAttr::isReadWrite() {
300 if (this->getArgMem() != ModRefInfo::ModRef)
301 return false;
302 if (this->getInaccessibleMem() != ModRefInfo::ModRef)
303 return false;
304 if (this->getOther() != ModRefInfo::ModRef)
305 return false;
306 if (this->getErrnoMem() != ModRefInfo::ModRef)
307 return false;
308 if (this->getTargetMem0() != ModRefInfo::ModRef)
309 return false;
310 if (this->getTargetMem1() != ModRefInfo::ModRef)
311 return false;
312 return true;
313}
314
315//===----------------------------------------------------------------------===//
316// DIExpression
317//===----------------------------------------------------------------------===//
318
319DIExpressionAttr DIExpressionAttr::get(MLIRContext *context) {
320 return get(context, ArrayRef<DIExpressionElemAttr>({}));
321}
322
323ParseResult parseExpressionArg(AsmParser &parser, uint64_t opcode,
324 SmallVector<uint64_t> &args) {
325 auto operandParser = [&]() -> LogicalResult {
326 uint64_t operand = 0;
327 if (!args.empty() && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
328 // Attempt to parse a keyword.
329 StringRef keyword;
330 if (succeeded(parser.parseOptionalKeyword(&keyword))) {
331 operand = llvm::dwarf::getAttributeEncoding(keyword);
332 if (operand == 0) {
333 // The keyword is invalid.
334 return parser.emitError(parser.getCurrentLocation())
335 << "encountered unknown attribute encoding \"" << keyword
336 << "\"";
337 }
338 }
339 }
340
341 // operand should be non-zero if a keyword was parsed. Otherwise, the
342 // operand MUST be an integer.
343 if (operand == 0) {
344 // Parse the next operand as an integer.
345 if (parser.parseInteger(operand)) {
346 return parser.emitError(parser.getCurrentLocation())
347 << "expected integer operand";
348 }
349 }
350
351 args.push_back(operand);
352 return success();
353 };
354
355 // Parse operands as a comma-separated list.
356 return parser.parseCommaSeparatedList(operandParser);
357}
358
359void printExpressionArg(AsmPrinter &printer, uint64_t opcode,
360 ArrayRef<uint64_t> args) {
361 size_t i = 0;
362 llvm::interleaveComma(args, printer, [&](uint64_t operand) {
363 if (i > 0 && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
364 if (const StringRef keyword =
365 llvm::dwarf::AttributeEncodingString(operand);
366 !keyword.empty()) {
367 printer << keyword;
368 return;
369 }
370 }
371 // All operands are expected to be printed as integers.
372 printer << operand;
373 i++;
374 });
375}
376
377//===----------------------------------------------------------------------===//
378// DICompositeTypeAttr
379//===----------------------------------------------------------------------===//
380
381DIRecursiveTypeAttrInterface
382DICompositeTypeAttr::withRecId(DistinctAttr recId) {
383 return DICompositeTypeAttr::get(
384 getContext(), recId, getIsRecSelf(), getTag(), getName(), getFile(),
385 getLine(), getScope(), getBaseType(), getFlags(), getSizeInBits(),
386 getAlignInBits(), getDataLocation(), getRank(), getAllocated(),
387 getAssociated(), getIdentifier(), getDiscriminator(), getElements());
388}
389
390DIRecursiveTypeAttrInterface
391DICompositeTypeAttr::getRecSelf(DistinctAttr recId) {
392 return DICompositeTypeAttr::get(recId.getContext(), recId, /*isRecSelf=*/true,
393 0, {}, {}, 0, {}, {}, DIFlags(), 0, 0, {}, {},
394 {}, {}, {}, {}, {});
395}
396
397//===----------------------------------------------------------------------===//
398// DISourceLanguageNameAttr
399//===----------------------------------------------------------------------===//
400
401static ParseResult parseSourceLanguage(AsmParser &parser,
402 DISourceLanguageNameAttr &language) {
403 DISourceLanguageNameAttr nestedLanguage;
404 OptionalParseResult nestedResult =
405 parser.parseOptionalAttribute(nestedLanguage);
406 if (nestedResult.has_value()) {
407 if (failed(*nestedResult))
408 return failure();
409 language = nestedLanguage;
410 return success();
411 }
412
413 // If we cannot parse the full attr, try to just parse a DWARF language.
414 SMLoc loc = parser.getCurrentLocation();
415 StringRef spelling;
416 if (parser.parseKeyword(&spelling))
417 return failure();
418 if (unsigned value = llvm::dwarf::getLanguage(spelling)) {
419 language = DISourceLanguageNameAttr::get(
420 parser.getContext(), value, /*name=*/0, /*version=*/std::nullopt,
421 /*dialect=*/0);
422 return success();
423 }
424 return parser.emitError(loc)
425 << "invalid debug info source language: " << spelling;
426}
427
428static void printSourceLanguage(AsmPrinter &printer,
429 DISourceLanguageNameAttr language) {
430 // Print only the DWARF language if the other fields are not set.
431 if (language.getLanguage() && !language.getName() && !language.getVersion() &&
432 !language.getDialect()) {
433 printer << llvm::dwarf::LanguageString(language.getLanguage());
434 return;
435 }
436 printer.printAttribute(language);
437}
438
439LogicalResult DISourceLanguageNameAttr::verify(
440 function_ref<InFlightDiagnostic()> emitError, unsigned language,
441 unsigned name, std::optional<uint32_t> version, unsigned /*dialect*/) {
442 if (static_cast<bool>(language) == static_cast<bool>(name))
443 return emitError() << "expected exactly one of language or name";
444 if (name && !version)
445 return emitError() << "DW_LNAME requires a version";
446 if (language && version)
447 return emitError() << "DW_LANG cannot have a version";
448 return success();
449}
450
451//===----------------------------------------------------------------------===//
452// DICompileUnitAttr
453//===----------------------------------------------------------------------===//
454
455DIRecursiveTypeAttrInterface DICompileUnitAttr::withRecId(DistinctAttr recId) {
456 return DICompileUnitAttr::get(
457 getContext(), recId, getIsRecSelf(), getId(), getSourceLanguage(),
458 getFile(), getProducer(), getIsOptimized(), getEmissionKind(),
459 getIsDebugInfoForProfiling(), getNameTableKind(), getSplitDebugFilename(),
460 getImportedEntities());
461}
462
463DIRecursiveTypeAttrInterface DICompileUnitAttr::getRecSelf(DistinctAttr recId) {
464
465 return DICompileUnitAttr::get(
466 recId.getContext(), recId, /*isRecSelf=*/true, /*id=*/{},
467 /*sourceLanguage=*/{},
468 /*file=*/{}, /*producer=*/{}, /*isOptimized=*/false, DIEmissionKind::None,
469 /*isDebugInfoForProfiling=*/false, DINameTableKind::Default,
470 /*splitDebugFilename=*/{}, /*importedEntities=*/{});
471}
472
473LogicalResult DICompileUnitAttr::verify(
474 function_ref<InFlightDiagnostic()> emitError, DistinctAttr recId,
475 bool isRecSelf, DistinctAttr id, DISourceLanguageNameAttr sourceLanguage,
476 DIFileAttr file, StringAttr producer, bool isOptimized,
477 DIEmissionKind emissionKind, bool isDebugInfoForProfiling,
478 DINameTableKind nameTableKind, StringAttr splitDebugFilename,
479 ArrayRef<DINodeAttr> importedEntities) {
480 if (isRecSelf)
481 return success();
482 if (!sourceLanguage)
483 return emitError() << "sourceLanguage must be set";
484 return success();
485}
486
487//===----------------------------------------------------------------------===//
488// DISubprogramAttr
489//===----------------------------------------------------------------------===//
490
491DIRecursiveTypeAttrInterface DISubprogramAttr::withRecId(DistinctAttr recId) {
492 return DISubprogramAttr::get(getContext(), recId, getIsRecSelf(), getId(),
493 getCompileUnit(), getScope(), getName(),
494 getLinkageName(), getFile(), getLine(),
495 getScopeLine(), getSubprogramFlags(), getType(),
496 getRetainedNodes(), getAnnotations());
497}
498
499DIRecursiveTypeAttrInterface DISubprogramAttr::getRecSelf(DistinctAttr recId) {
500 return DISubprogramAttr::get(recId.getContext(), recId, /*isRecSelf=*/true,
501 {}, {}, {}, {}, {}, {}, 0, 0, {}, {}, {}, {});
502}
503
504//===----------------------------------------------------------------------===//
505// ConstantRangeAttr
506//===----------------------------------------------------------------------===//
507
508Attribute ConstantRangeAttr::parse(AsmParser &parser, Type odsType) {
509 llvm::SMLoc loc = parser.getCurrentLocation();
510 IntegerType widthType;
511 if (parser.parseLess() || parser.parseType(widthType) ||
512 parser.parseComma()) {
513 return Attribute{};
514 }
515 unsigned bitWidth = widthType.getWidth();
516 APInt lower(bitWidth, 0);
517 APInt upper(bitWidth, 0);
518 if (parser.parseInteger(lower) || parser.parseComma() ||
519 parser.parseInteger(upper) || parser.parseGreater())
520 return Attribute{};
521 // Non-positive numbers may use more bits than `bitWidth`
522 lower = lower.sextOrTrunc(bitWidth);
523 upper = upper.sextOrTrunc(bitWidth);
524 return parser.getChecked<ConstantRangeAttr>(loc, parser.getContext(), lower,
525 upper);
526}
527
528void ConstantRangeAttr::print(AsmPrinter &printer) const {
529 printer << "<i" << getLower().getBitWidth() << ", " << getLower() << ", "
530 << getUpper() << ">";
531}
532
533LogicalResult
534ConstantRangeAttr::verify(llvm::function_ref<InFlightDiagnostic()> emitError,
535 APInt lower, APInt upper) {
536 if (lower.getBitWidth() != upper.getBitWidth())
537 return emitError()
538 << "expected lower and upper to have matching bitwidths but got "
539 << lower.getBitWidth() << " vs. " << upper.getBitWidth();
540 return success();
541}
542
543//===----------------------------------------------------------------------===//
544// TargetFeaturesAttr
545//===----------------------------------------------------------------------===//
546
547TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
548 llvm::ArrayRef<StringRef> features) {
549 return Base::get(context,
550 llvm::map_to_vector(features, [&](StringRef feature) {
551 return StringAttr::get(context, feature);
552 }));
553}
554
555TargetFeaturesAttr
556TargetFeaturesAttr::getChecked(function_ref<InFlightDiagnostic()> emitError,
557 MLIRContext *context,
558 llvm::ArrayRef<StringRef> features) {
559 return Base::getChecked(emitError, context,
560 llvm::map_to_vector(features, [&](StringRef feature) {
561 return StringAttr::get(context, feature);
562 }));
563}
564
565TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
566 StringRef targetFeatures) {
567 SmallVector<StringRef> features;
568 targetFeatures.split(features, ',', /*MaxSplit=*/-1,
569 /*KeepEmpty=*/false);
570 return get(context, features);
571}
572
573TargetFeaturesAttr
574TargetFeaturesAttr::getChecked(function_ref<InFlightDiagnostic()> emitError,
575 MLIRContext *context, StringRef targetFeatures) {
576 SmallVector<StringRef> features;
577 targetFeatures.split(features, ',', /*MaxSplit=*/-1,
578 /*KeepEmpty=*/false);
579 ArrayRef featuresRef(features);
580 return getChecked(emitError, context, featuresRef);
581}
582
583LogicalResult
584TargetFeaturesAttr::verify(function_ref<InFlightDiagnostic()> emitError,
585 llvm::ArrayRef<StringAttr> features) {
586 for (StringAttr featureAttr : features) {
587 if (!featureAttr || featureAttr.empty())
588 return emitError() << "target features can not be null or empty";
589 auto feature = featureAttr.strref();
590 if (feature[0] != '+' && feature[0] != '-')
591 return emitError() << "target features must start with '+' or '-'";
592 if (feature.contains(','))
593 return emitError() << "target features can not contain ','";
594 }
595 return success();
596}
597
598bool TargetFeaturesAttr::contains(StringAttr feature) const {
599 if (nullOrEmpty())
600 return false;
601 // Note: Using StringAttr does pointer comparisons.
602 return llvm::is_contained(getFeatures(), feature);
603}
604
605bool TargetFeaturesAttr::contains(StringRef feature) const {
606 if (nullOrEmpty())
607 return false;
608 return llvm::is_contained(getFeatures(), feature);
609}
610
611std::string TargetFeaturesAttr::getFeaturesString() const {
612 std::string featuresString;
613 llvm::raw_string_ostream ss(featuresString);
614 llvm::interleave(
615 getFeatures(), ss, [&](auto &feature) { ss << feature.strref(); }, ",");
616 return featuresString;
617}
618
619TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
620 auto parentFunction = op->getParentOfType<FunctionOpInterface>();
621 if (!parentFunction)
622 return {};
623 return parentFunction.getOperation()->getAttrOfType<TargetFeaturesAttr>(
624 getAttributeName());
625}
626
627FailureOr<Attribute> TargetFeaturesAttr::query(DataLayoutEntryKey key) {
628 auto stringKey = dyn_cast<StringAttr>(key);
629 if (!stringKey)
630 return failure();
631
632 if (contains(stringKey))
633 return UnitAttr::get(getContext());
634
635 if (contains((std::string("+") + stringKey.strref()).str()))
636 return BoolAttr::get(getContext(), true);
637
638 if (contains((std::string("-") + stringKey.strref()).str()))
639 return BoolAttr::get(getContext(), false);
640
641 return failure();
642}
643
644//===----------------------------------------------------------------------===//
645// TargetAttr
646//===----------------------------------------------------------------------===//
647
648FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
649 if (auto stringAttrKey = dyn_cast<StringAttr>(key)) {
650 if (stringAttrKey.getValue() == "triple")
651 return getTriple();
652 if (stringAttrKey.getValue() == "chip")
653 return getChip();
654 if (stringAttrKey.getValue() == "features" && getFeatures())
655 return getFeatures();
656 }
657 return failure();
658}
659
660//===----------------------------------------------------------------------===//
661// ModuleFlagAttr
662//===----------------------------------------------------------------------===//
663
665 StringAttr key, Attribute value,
667 if (key == LLVMDialect::getModuleFlagKeyCGProfileName()) {
668 auto arrayAttr = dyn_cast<ArrayAttr>(value);
669 if ((!arrayAttr) || (!llvm::all_of(arrayAttr, [](Attribute attr) {
670 return isa<ModuleFlagCGProfileEntryAttr>(attr);
671 })))
672 return emitError()
673 << "'CG Profile' key expects an array of '#llvm.cgprofile_entry'";
674 return success();
675 }
676
677 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName()) {
678 if (!isa<ModuleFlagProfileSummaryAttr>(value))
679 return emitError() << "'ProfileSummary' key expects a "
680 "'#llvm.profile_summary' attribute";
681 return success();
682 }
683
684 if (isa<IntegerAttr, StringAttr, IntrinsicIntegerAttrInterface>(value))
685 return success();
686
687 // Allow non-empty ArrayAttr of StringAttrs to represent MDTuples of
688 // MDStrings (e.g. the "riscv-isa" module flag). Integer values within
689 // MDTuples are not handled here because integer module flags are encoded as
690 // ConstantAsMetadata at the top level (not as MDTuples), so no known use
691 // case requires an array-of-integers representation.
692 if (auto arrayAttr = dyn_cast<ArrayAttr>(value))
693 if (!arrayAttr.empty() &&
694 llvm::all_of(arrayAttr, [](Attribute a) { return isa<StringAttr>(a); }))
695 return success();
696
697 return emitError()
698 << "only integer, integer-like dialect attributes, string, "
699 "and string-array values are currently supported for "
700 "unknown key '"
701 << key << "'";
702}
703
704LogicalResult
705ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
706 LLVM::ModFlagBehavior flagBehavior, StringAttr key,
707 Attribute value) {
709}
710
711ModFlagBehavior ModuleFlagAttr::getModuleFlagBehavior() const {
712 return getBehavior();
713}
714
715StringAttr ModuleFlagAttr::getModuleFlagKey() const { return getKey(); }
716
717Attribute ModuleFlagAttr::getModuleFlagValue() const { return getValue(); }
718
719//===----------------------------------------------------------------------===//
720// MDAddrSpaceCastAttr
721//===----------------------------------------------------------------------===//
722
723LogicalResult
724MDAddrSpaceCastAttr::verify(function_ref<InFlightDiagnostic()> emitError,
725 Attribute arg, unsigned addressSpace) {
726 // `addrspacecast` operates on pointers, so the operand must be a metadata
727 // attribute that models a pointer-typed constant.
728 if (!isa<MDGlobalValueAttr, MDNullAttr, MDAddrSpaceCastAttr>(arg))
729 return emitError() << "expected #llvm.md_global_value, #llvm.md_null, or "
730 "#llvm.md_addrspacecast operand, but got "
731 << arg;
732 return success();
733}
return success()
static llvm::DISourceLanguageName getSourceLanguage(DICompileUnitAttr attr)
static StringRef getFixedMetadataKindName(unsigned kind)
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.
static ParseResult parseSourceLanguage(AsmParser &parser, DISourceLanguageNameAttr &language)
Parses a source language from either the historical inline DW_LANG_* syntax or a nested DISourceLangu...
static constexpr unsigned kReservedFunctionMetadataKinds[]
static void printSourceLanguage(AsmPrinter &printer, DISourceLanguageNameAttr language)
Prints an unversioned source language without a dialect using the historical inline DW_LANG_* syntax.
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 OptionalParseResult parseOptionalAttribute(Attribute &result, Type type={})=0
Parse an arbitrary optional attribute of a given type and return it in result.
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.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
This base class exposes generic asm printer hooks, usable across the various derived printers.
virtual void printAttribute(Attribute attr)
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)
This class represents a LLVM attribute that describes a debug info scope.
Definition LLVMAttrs.h:38
static bool classof(Attribute attr)
Support LLVM type casting.
This class represents a LLVM attribute that describes a debug info type.
Definition LLVMAttrs.h:57
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:255
This class implements Optional functionality for ParseResult.
bool has_value() const
Returns true if we contain a valid ParseResult value.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
LogicalResult verifyModuleFlagValue(StringAttr key, Attribute value, function_ref< InFlightDiagnostic()> emitError)
Verifies that a module flag value can be exported to LLVM IR.
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:75
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