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"
45 DISourceLanguageNameAttr &language);
51 DISourceLanguageNameAttr language);
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"
62void LLVMDialect::registerAttributes() {
64#define GET_ATTRDEF_LIST
65#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc"
76 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
77 const ::mlir::DataLayout *dataLayout,
81 emitError() <<
"type must be LLVM type with size, but got " << type;
84 if (ordering == ptr::AtomicOrdering::not_atomic)
90 emitError() <<
"expected a valid data layout";
95 emitError() <<
"unsupported type " << type <<
" for atomic access";
101bool AddressSpaceAttr::isValidLoad(
102 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
103 const ::mlir::DataLayout *dataLayout,
109bool AddressSpaceAttr::isValidStore(
110 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
111 const ::mlir::DataLayout *dataLayout,
117bool AddressSpaceAttr::isValidAtomicOp(
118 ptr::AtomicBinOp op,
Type type, ptr::AtomicOrdering ordering,
119 std::optional<int64_t> alignment, const ::mlir::DataLayout *dataLayout,
122 assert(
false &&
"unimplemented, see TODO in the source.");
126bool AddressSpaceAttr::isValidAtomicXchg(
127 Type type, ptr::AtomicOrdering successOrdering,
128 ptr::AtomicOrdering failureOrdering, std::optional<int64_t> alignment,
129 const ::mlir::DataLayout *dataLayout,
132 assert(
false &&
"unimplemented, see TODO in the source.");
136bool AddressSpaceAttr::isValidAddrSpaceCast(
140 assert(
false &&
"unimplemented, see TODO in the source.");
144bool AddressSpaceAttr::isValidPtrIntCast(
149 assert(
false &&
"unimplemented, see TODO in the source.");
158 llvm::LLVMContext::MD_dbg, llvm::LLVMContext::MD_prof};
162#define LLVM_FIXED_MD_KIND(EnumID, Name, Value) \
163 case llvm::LLVMContext::EnumID: \
165#include "llvm/IR/FixedMetadataKinds.def"
166#undef LLVM_FIXED_MD_KIND
168 llvm_unreachable(
"unknown fixed metadata kind");
173 StringAttr metadataName, MDNodeAttr node) {
175 StringRef name = metadataName.getValue();
177 return emitError() <<
"function_metadata entry name must not be empty";
181 return emitError() <<
"reserved function_metadata entry '" << name
182 <<
"' is not supported by the generic carrier";
193 Attribute id, AliasScopeDomainAttr domain,
194 StringAttr description) {
197 if (!llvm::isa<StringAttr, DistinctAttr>(
id))
199 <<
"id of an alias scope must be a StringAttr or a DistrinctAttr";
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>(
224 return llvm::isa<DICommonBlockAttr, DICompileUnitAttr, DICompositeTypeAttr,
226 DIModuleAttr, DINamespaceAttr>(attr);
234 return llvm::isa<DILexicalBlockAttr, DILexicalBlockFileAttr,
235 DISubprogramAttr>(attr);
243 return llvm::isa<DILocalVariableAttr, DIGlobalVariableAttr>(attr);
251 return llvm::isa<DINullTypeAttr, DIBasicTypeAttr, DICompositeTypeAttr,
252 DIDerivedTypeAttr, DIStringTypeAttr, DISubroutineTypeAttr>(
260LogicalResult DIDerivedTypeAttr::verify(
263 uint64_t sizeInBits, uint32_t alignInBits, uint64_t offsetInBits,
264 std::optional<unsigned> dwarfAddressSpace, DIFlags flags,
266 if (extraData && !llvm::isa<DINodeAttr, IntegerAttr>(extraData))
267 return emitError() <<
"extraData must be a DINodeAttr or an IntegerAttr";
276 return llvm::isa<TBAATypeDescriptorAttr, TBAARootAttr>(attr);
283MemoryEffectsAttr MemoryEffectsAttr::get(
MLIRContext *context,
285 if (memInfoArgs.empty())
286 return MemoryEffectsAttr::get(context, 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]);
299bool MemoryEffectsAttr::isReadWrite() {
300 if (this->getArgMem() != ModRefInfo::ModRef)
302 if (this->getInaccessibleMem() != ModRefInfo::ModRef)
304 if (this->getOther() != ModRefInfo::ModRef)
306 if (this->getErrnoMem() != ModRefInfo::ModRef)
308 if (this->getTargetMem0() != ModRefInfo::ModRef)
310 if (this->getTargetMem1() != ModRefInfo::ModRef)
319DIExpressionAttr DIExpressionAttr::get(MLIRContext *context) {
320 return get(context, ArrayRef<DIExpressionElemAttr>({}));
325 auto operandParser = [&]() -> LogicalResult {
326 uint64_t operand = 0;
327 if (!args.empty() && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
331 operand = llvm::dwarf::getAttributeEncoding(keyword);
335 <<
"encountered unknown attribute encoding \"" << keyword
347 <<
"expected integer operand";
351 args.push_back(operand);
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);
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());
390DIRecursiveTypeAttrInterface
391DICompositeTypeAttr::getRecSelf(DistinctAttr recId) {
392 return DICompositeTypeAttr::get(recId.
getContext(), recId,
true,
393 0, {}, {}, 0, {}, {}, DIFlags(), 0, 0, {}, {},
402 DISourceLanguageNameAttr &language) {
403 DISourceLanguageNameAttr nestedLanguage;
407 if (failed(*nestedResult))
409 language = nestedLanguage;
418 if (
unsigned value = llvm::dwarf::getLanguage(spelling)) {
419 language = DISourceLanguageNameAttr::get(
425 <<
"invalid debug info source language: " << spelling;
429 DISourceLanguageNameAttr language) {
431 if (language.getLanguage() && !language.getName() && !language.getVersion() &&
432 !language.getDialect()) {
433 printer << llvm::dwarf::LanguageString(language.getLanguage());
439LogicalResult DISourceLanguageNameAttr::verify(
441 unsigned name, std::optional<uint32_t> version,
unsigned ) {
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";
455DIRecursiveTypeAttrInterface DICompileUnitAttr::withRecId(DistinctAttr recId) {
456 return DICompileUnitAttr::get(
458 getFile(), getProducer(), getIsOptimized(), getEmissionKind(),
459 getIsDebugInfoForProfiling(), getNameTableKind(), getSplitDebugFilename(),
460 getImportedEntities());
463DIRecursiveTypeAttrInterface DICompileUnitAttr::getRecSelf(DistinctAttr recId) {
465 return DICompileUnitAttr::get(
468 {}, {},
false, DIEmissionKind::None,
469 false, DINameTableKind::Default,
473LogicalResult DICompileUnitAttr::verify(
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) {
483 return emitError() <<
"sourceLanguage must be set";
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());
499DIRecursiveTypeAttrInterface DISubprogramAttr::getRecSelf(DistinctAttr recId) {
500 return DISubprogramAttr::get(recId.
getContext(), recId,
true,
501 {}, {}, {}, {}, {}, {}, 0, 0, {}, {}, {}, {});
508Attribute ConstantRangeAttr::parse(AsmParser &parser, Type odsType) {
510 IntegerType widthType;
515 unsigned bitWidth = widthType.getWidth();
516 APInt lower(bitWidth, 0);
517 APInt upper(bitWidth, 0);
522 lower = lower.sextOrTrunc(bitWidth);
523 upper = upper.sextOrTrunc(bitWidth);
528void ConstantRangeAttr::print(AsmPrinter &printer)
const {
529 printer <<
"<i" << getLower().getBitWidth() <<
", " << getLower() <<
", "
530 << getUpper() <<
">";
534ConstantRangeAttr::verify(llvm::function_ref<InFlightDiagnostic()>
emitError,
535 APInt lower, APInt upper) {
536 if (lower.getBitWidth() != upper.getBitWidth())
538 <<
"expected lower and upper to have matching bitwidths but got "
539 << lower.getBitWidth() <<
" vs. " << upper.getBitWidth();
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);
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);
565TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
566 StringRef targetFeatures) {
567 SmallVector<StringRef> features;
568 targetFeatures.split(features,
',', -1,
570 return get(context, features);
575 MLIRContext *context, StringRef targetFeatures) {
576 SmallVector<StringRef> features;
577 targetFeatures.split(features,
',', -1,
579 ArrayRef featuresRef(features);
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 ','";
598bool TargetFeaturesAttr::contains(StringAttr feature)
const {
602 return llvm::is_contained(getFeatures(), feature);
605bool TargetFeaturesAttr::contains(StringRef feature)
const {
608 return llvm::is_contained(getFeatures(), feature);
611std::string TargetFeaturesAttr::getFeaturesString()
const {
612 std::string featuresString;
613 llvm::raw_string_ostream ss(featuresString);
615 getFeatures(), ss, [&](
auto &feature) { ss << feature.strref(); },
",");
616 return featuresString;
619TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
623 return parentFunction.getOperation()->getAttrOfType<TargetFeaturesAttr>(
628 auto stringKey = dyn_cast<StringAttr>(key);
635 if (
contains((std::string(
"+") + stringKey.strref()).str()))
638 if (
contains((std::string(
"-") + stringKey.strref()).str()))
649 if (
auto stringAttrKey = dyn_cast<StringAttr>(key)) {
650 if (stringAttrKey.getValue() ==
"triple")
652 if (stringAttrKey.getValue() ==
"chip")
654 if (stringAttrKey.getValue() ==
"features" && getFeatures())
655 return getFeatures();
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);
673 <<
"'CG Profile' key expects an array of '#llvm.cgprofile_entry'";
677 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName()) {
678 if (!isa<ModuleFlagProfileSummaryAttr>(value))
679 return emitError() <<
"'ProfileSummary' key expects a "
680 "'#llvm.profile_summary' attribute";
684 if (isa<IntegerAttr, StringAttr, IntrinsicIntegerAttrInterface>(value))
692 if (
auto arrayAttr = dyn_cast<ArrayAttr>(value))
693 if (!arrayAttr.empty() &&
694 llvm::all_of(arrayAttr, [](
Attribute a) { return isa<StringAttr>(a); }))
698 <<
"only integer, integer-like dialect attributes, string, "
699 "and string-array values are currently supported for "
706 LLVM::ModFlagBehavior flagBehavior, StringAttr key,
711ModFlagBehavior ModuleFlagAttr::getModuleFlagBehavior()
const {
712 return getBehavior();
715StringAttr ModuleFlagAttr::getModuleFlagKey()
const {
return getKey(); }
717Attribute ModuleFlagAttr::getModuleFlagValue()
const {
return getValue(); }
725 Attribute arg,
unsigned addressSpace) {
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 "
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.
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.
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
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.
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