18#include "llvm/ADT/STLExtras.h"
19#include "llvm/BinaryFormat/Dwarf.h"
20#include "llvm/IR/DebugInfoMetadata.h"
21#include "llvm/IR/LLVMContext.h"
22#include "llvm/Support/ErrorHandling.h"
41 DISourceLanguageNameAttr &language);
47 DISourceLanguageNameAttr language);
49#include "mlir/Dialect/LLVMIR/LLVMAttrInterfaces.cpp.inc"
50#include "mlir/Dialect/LLVMIR/LLVMOpsEnums.cpp.inc"
51#define GET_ATTRDEF_CLASSES
52#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc"
58void LLVMDialect::registerAttributes() {
60#define GET_ATTRDEF_LIST
61#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc"
72 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
73 const ::mlir::DataLayout *dataLayout,
77 emitError() <<
"type must be LLVM type with size, but got " << type;
80 if (ordering == ptr::AtomicOrdering::not_atomic)
86 emitError() <<
"expected a valid data layout";
91 emitError() <<
"unsupported type " << type <<
" for atomic access";
97bool AddressSpaceAttr::isValidLoad(
98 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
99 const ::mlir::DataLayout *dataLayout,
105bool AddressSpaceAttr::isValidStore(
106 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
107 const ::mlir::DataLayout *dataLayout,
113bool AddressSpaceAttr::isValidAtomicOp(
114 ptr::AtomicBinOp op,
Type type, ptr::AtomicOrdering ordering,
115 std::optional<int64_t> alignment, const ::mlir::DataLayout *dataLayout,
118 assert(
false &&
"unimplemented, see TODO in the source.");
122bool AddressSpaceAttr::isValidAtomicXchg(
123 Type type, ptr::AtomicOrdering successOrdering,
124 ptr::AtomicOrdering failureOrdering, std::optional<int64_t> alignment,
125 const ::mlir::DataLayout *dataLayout,
128 assert(
false &&
"unimplemented, see TODO in the source.");
132bool AddressSpaceAttr::isValidAddrSpaceCast(
136 assert(
false &&
"unimplemented, see TODO in the source.");
140bool AddressSpaceAttr::isValidPtrIntCast(
145 assert(
false &&
"unimplemented, see TODO in the source.");
154 llvm::LLVMContext::MD_dbg, llvm::LLVMContext::MD_prof};
158#define LLVM_FIXED_MD_KIND(EnumID, Name, Value) \
159 case llvm::LLVMContext::EnumID: \
161#include "llvm/IR/FixedMetadataKinds.def"
162#undef LLVM_FIXED_MD_KIND
164 llvm_unreachable(
"unknown fixed metadata kind");
169 StringAttr metadataName, MDNodeAttr node) {
171 StringRef name = metadataName.getValue();
173 return emitError() <<
"function_metadata entry name must not be empty";
177 return emitError() <<
"reserved function_metadata entry '" << name
178 <<
"' is not supported by the generic carrier";
189 Attribute id, AliasScopeDomainAttr domain,
190 StringAttr description) {
193 if (!llvm::isa<StringAttr, DistinctAttr>(
id))
195 <<
"id of an alias scope must be a StringAttr or a DistrinctAttr";
206 DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr,
207 DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr, DIGenericSubrangeAttr,
208 DIGlobalVariableAttr, DIImportedEntityAttr, DILabelAttr,
209 DILexicalBlockAttr, DILexicalBlockFileAttr, DILocalVariableAttr,
210 DIModuleAttr, DINamespaceAttr, DINullTypeAttr, DIAnnotationAttr,
211 DIStringTypeAttr, DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>(
220 return llvm::isa<DICommonBlockAttr, DICompileUnitAttr, DICompositeTypeAttr,
222 DIModuleAttr, DINamespaceAttr>(attr);
230 return llvm::isa<DILexicalBlockAttr, DILexicalBlockFileAttr,
231 DISubprogramAttr>(attr);
239 return llvm::isa<DILocalVariableAttr, DIGlobalVariableAttr>(attr);
247 return llvm::isa<DINullTypeAttr, DIBasicTypeAttr, DICompositeTypeAttr,
248 DIDerivedTypeAttr, DIStringTypeAttr, DISubroutineTypeAttr>(
256LogicalResult DIDerivedTypeAttr::verify(
259 uint64_t sizeInBits, uint32_t alignInBits, uint64_t offsetInBits,
260 std::optional<unsigned> dwarfAddressSpace, DIFlags flags,
262 if (extraData && !llvm::isa<DINodeAttr, IntegerAttr>(extraData))
263 return emitError() <<
"extraData must be a DINodeAttr or an IntegerAttr";
272 return llvm::isa<TBAATypeDescriptorAttr, TBAARootAttr>(attr);
286 if (callStack.empty())
287 return emitError() <<
"call stack of a memprof MemInfoBlock must not be "
296MemoryEffectsAttr MemoryEffectsAttr::get(
MLIRContext *context,
298 if (memInfoArgs.empty())
299 return MemoryEffectsAttr::get(context, ModRefInfo::ModRef,
305 if (memInfoArgs.size() == 6)
306 return MemoryEffectsAttr::get(context, memInfoArgs[0], memInfoArgs[1],
307 memInfoArgs[2], memInfoArgs[3],
308 memInfoArgs[4], memInfoArgs[5]);
312bool MemoryEffectsAttr::isReadWrite() {
313 if (this->getArgMem() != ModRefInfo::ModRef)
315 if (this->getInaccessibleMem() != ModRefInfo::ModRef)
317 if (this->getOther() != ModRefInfo::ModRef)
319 if (this->getErrnoMem() != ModRefInfo::ModRef)
321 if (this->getTargetMem0() != ModRefInfo::ModRef)
323 if (this->getTargetMem1() != ModRefInfo::ModRef)
332DIExpressionAttr DIExpressionAttr::get(MLIRContext *context) {
333 return get(context, ArrayRef<DIExpressionElemAttr>({}));
338 auto operandParser = [&]() -> LogicalResult {
339 uint64_t operand = 0;
340 if (!args.empty() && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
344 operand = llvm::dwarf::getAttributeEncoding(keyword);
348 <<
"encountered unknown attribute encoding \"" << keyword
360 <<
"expected integer operand";
364 args.push_back(operand);
375 llvm::interleaveComma(args, printer, [&](uint64_t operand) {
376 if (i > 0 && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
377 if (
const StringRef keyword =
378 llvm::dwarf::AttributeEncodingString(operand);
394DIRecursiveTypeAttrInterface
395DICompositeTypeAttr::withRecId(DistinctAttr recId) {
396 return DICompositeTypeAttr::get(
397 getContext(), recId, getIsRecSelf(), getTag(), getName(), getFile(),
398 getLine(), getScope(), getBaseType(),
getFlags(), getSizeInBits(),
399 getAlignInBits(), getDataLocation(), getRank(), getAllocated(),
400 getAssociated(), getIdentifier(), getDiscriminator(), getElements());
403DIRecursiveTypeAttrInterface
404DICompositeTypeAttr::getRecSelf(DistinctAttr recId) {
405 return DICompositeTypeAttr::get(recId.
getContext(), recId,
true,
406 0, {}, {}, 0, {}, {}, DIFlags(), 0, 0, {}, {},
415 DISourceLanguageNameAttr &language) {
416 DISourceLanguageNameAttr nestedLanguage;
420 if (failed(*nestedResult))
422 language = nestedLanguage;
431 if (
unsigned value = llvm::dwarf::getLanguage(spelling)) {
432 language = DISourceLanguageNameAttr::get(
438 <<
"invalid debug info source language: " << spelling;
442 DISourceLanguageNameAttr language) {
444 if (language.getLanguage() && !language.getName() && !language.getVersion() &&
445 !language.getDialect()) {
446 printer << llvm::dwarf::LanguageString(language.getLanguage());
452LogicalResult DISourceLanguageNameAttr::verify(
454 unsigned name, std::optional<uint32_t> version,
unsigned ) {
455 if (
static_cast<bool>(language) ==
static_cast<bool>(name))
456 return emitError() <<
"expected exactly one of language or name";
457 if (name && !version)
458 return emitError() <<
"DW_LNAME requires a version";
459 if (language && version)
460 return emitError() <<
"DW_LANG cannot have a version";
468DIRecursiveTypeAttrInterface DICompileUnitAttr::withRecId(DistinctAttr recId) {
469 return DICompileUnitAttr::get(
471 getFile(), getProducer(), getIsOptimized(), getEmissionKind(),
472 getIsDebugInfoForProfiling(), getNameTableKind(), getSplitDebugFilename(),
473 getImportedEntities());
476DIRecursiveTypeAttrInterface DICompileUnitAttr::getRecSelf(DistinctAttr recId) {
478 return DICompileUnitAttr::get(
481 {}, {},
false, DIEmissionKind::None,
482 false, DINameTableKind::Default,
486LogicalResult DICompileUnitAttr::verify(
488 bool isRecSelf, DistinctAttr
id, DISourceLanguageNameAttr sourceLanguage,
489 DIFileAttr file, StringAttr producer,
bool isOptimized,
490 DIEmissionKind emissionKind,
bool isDebugInfoForProfiling,
491 DINameTableKind nameTableKind, StringAttr splitDebugFilename,
492 ArrayRef<DINodeAttr> importedEntities) {
496 return emitError() <<
"sourceLanguage must be set";
504DIRecursiveTypeAttrInterface DISubprogramAttr::withRecId(DistinctAttr recId) {
505 return DISubprogramAttr::get(
getContext(), recId, getIsRecSelf(), getId(),
506 getCompileUnit(), getScope(), getName(),
507 getLinkageName(), getFile(), getLine(),
508 getScopeLine(), getSubprogramFlags(),
getType(),
509 getRetainedNodes(), getAnnotations());
512DIRecursiveTypeAttrInterface DISubprogramAttr::getRecSelf(DistinctAttr recId) {
513 return DISubprogramAttr::get(recId.
getContext(), recId,
true,
514 {}, {}, {}, {}, {}, {}, 0, 0, {}, {}, {}, {});
521Attribute ConstantRangeAttr::parse(AsmParser &parser, Type odsType) {
523 IntegerType widthType;
528 unsigned bitWidth = widthType.getWidth();
529 APInt lower(bitWidth, 0);
530 APInt upper(bitWidth, 0);
535 lower = lower.sextOrTrunc(bitWidth);
536 upper = upper.sextOrTrunc(bitWidth);
541void ConstantRangeAttr::print(AsmPrinter &printer)
const {
542 printer <<
"<i" << getLower().getBitWidth() <<
", " << getLower() <<
", "
543 << getUpper() <<
">";
547ConstantRangeAttr::verify(llvm::function_ref<InFlightDiagnostic()>
emitError,
548 APInt lower, APInt upper) {
549 if (lower.getBitWidth() != upper.getBitWidth())
551 <<
"expected lower and upper to have matching bitwidths but got "
552 << lower.getBitWidth() <<
" vs. " << upper.getBitWidth();
560TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
561 llvm::ArrayRef<StringRef> features) {
562 return Base::get(context,
563 llvm::map_to_vector(features, [&](StringRef feature) {
564 return StringAttr::get(context, feature);
570 MLIRContext *context,
571 llvm::ArrayRef<StringRef> features) {
572 return Base::getChecked(
emitError, context,
573 llvm::map_to_vector(features, [&](StringRef feature) {
574 return StringAttr::get(context, feature);
578TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
579 StringRef targetFeatures) {
580 SmallVector<StringRef> features;
581 targetFeatures.split(features,
',', -1,
583 return get(context, features);
588 MLIRContext *context, StringRef targetFeatures) {
589 SmallVector<StringRef> features;
590 targetFeatures.split(features,
',', -1,
592 ArrayRef featuresRef(features);
598 llvm::ArrayRef<StringAttr> features) {
599 for (StringAttr featureAttr : features) {
600 if (!featureAttr || featureAttr.empty())
601 return emitError() <<
"target features can not be null or empty";
602 auto feature = featureAttr.strref();
603 if (feature[0] !=
'+' && feature[0] !=
'-')
604 return emitError() <<
"target features must start with '+' or '-'";
605 if (feature.contains(
','))
606 return emitError() <<
"target features can not contain ','";
611bool TargetFeaturesAttr::contains(StringAttr feature)
const {
615 return llvm::is_contained(getFeatures(), feature);
618bool TargetFeaturesAttr::contains(StringRef feature)
const {
621 return llvm::is_contained(getFeatures(), feature);
624std::string TargetFeaturesAttr::getFeaturesString()
const {
625 std::string featuresString;
626 llvm::raw_string_ostream ss(featuresString);
628 getFeatures(), ss, [&](
auto &feature) { ss << feature.strref(); },
",");
629 return featuresString;
632TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
636 Operation *parentOp = parentFunction.getOperation();
637 if (
auto llvmFunc = dyn_cast<LLVMFuncOp>(parentOp))
638 return llvmFunc.getTargetFeaturesAttr();
642 TargetFeaturesAttr targetFeatures;
644 parentOp, [&](StringRef name, Attribute &attr) {
645 if (name == getAttributeName())
646 targetFeatures = dyn_cast<TargetFeaturesAttr>(attr);
649 return targetFeatures;
655 auto stringKey = dyn_cast<StringAttr>(key);
662 if (
contains((std::string(
"+") + stringKey.strref()).str()))
665 if (
contains((std::string(
"-") + stringKey.strref()).str()))
676 if (
auto stringAttrKey = dyn_cast<StringAttr>(key)) {
677 if (stringAttrKey.getValue() ==
"triple")
679 if (stringAttrKey.getValue() ==
"chip")
681 if (stringAttrKey.getValue() ==
"features" && getFeatures())
682 return getFeatures();
694 if (key == LLVMDialect::getModuleFlagKeyCGProfileName()) {
695 auto arrayAttr = dyn_cast<ArrayAttr>(value);
696 if ((!arrayAttr) || (!llvm::all_of(arrayAttr, [](
Attribute attr) {
697 return isa<ModuleFlagCGProfileEntryAttr>(attr);
700 <<
"'CG Profile' key expects an array of '#llvm.cgprofile_entry'";
704 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName()) {
705 if (!isa<ModuleFlagProfileSummaryAttr>(value))
706 return emitError() <<
"'ProfileSummary' key expects a "
707 "'#llvm.profile_summary' attribute";
711 if (isa<IntegerAttr, StringAttr, IntrinsicIntegerAttrInterface>(value))
719 if (
auto arrayAttr = dyn_cast<ArrayAttr>(value))
720 if (!arrayAttr.empty() &&
721 llvm::all_of(arrayAttr, [](
Attribute a) { return isa<StringAttr>(a); }))
725 <<
"only integer, integer-like dialect attributes, string, "
726 "and string-array values are currently supported for "
733 LLVM::ModFlagBehavior flagBehavior, StringAttr key,
738ModFlagBehavior ModuleFlagAttr::getModuleFlagBehavior()
const {
739 return getBehavior();
742StringAttr ModuleFlagAttr::getModuleFlagKey()
const {
return getKey(); }
744Attribute ModuleFlagAttr::getModuleFlagValue()
const {
return getValue(); }
752 Attribute arg,
unsigned addressSpace) {
755 if (!isa<MDGlobalValueAttr, MDNullAttr, MDAddrSpaceCastAttr>(arg))
756 return emitError() <<
"expected #llvm.md_global_value, #llvm.md_null, or "
757 "#llvm.md_addrspacecast operand, but got "
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.
static bool contains(SMRange range, SMLoc loc)
Returns true if the given range contains the given source location.
static arith::FastMathFlags getFlags(arith::FastMathFlagsAttr fastmath)
Returns the flags held by fastmath, or none if it is null.
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.
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.
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.
static bool classof(Attribute attr)
Support LLVM type casting.
This class represents a LLVM attribute that describes a debug info type.
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.
void walkInherentAttrs(Operation *op, InherentAttrVisitor visitor) const
Visit the inherent attributes stored in the properties of op.
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
OperationName getName()
The name of an operation is the key identifier for it.
AttrClass getDiscardableAttrOfType(StringRef name)
Access a discardable attribute by name and cast it to AttrClass.
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...
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.
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.
detail::DenseArrayAttrImpl< int64_t > DenseI64ArrayAttr
llvm::PointerUnion< Type, StringAttr > DataLayoutEntryKey
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
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