20#include "llvm/ADT/StringExtras.h"
21#include "llvm/ADT/TypeSwitch.h"
22#include "llvm/BinaryFormat/Dwarf.h"
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"
47void LLVMDialect::registerAttributes() {
49#define GET_ATTRDEF_LIST
50#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc"
61 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
62 const ::mlir::DataLayout *dataLayout,
66 emitError() <<
"type must be LLVM type with size, but got " << type;
69 if (ordering == ptr::AtomicOrdering::not_atomic)
75 emitError() <<
"expected a valid data layout";
80 emitError() <<
"unsupported type " << type <<
" for atomic access";
86bool AddressSpaceAttr::isValidLoad(
87 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
88 const ::mlir::DataLayout *dataLayout,
94bool AddressSpaceAttr::isValidStore(
95 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
96 const ::mlir::DataLayout *dataLayout,
102bool AddressSpaceAttr::isValidAtomicOp(
103 ptr::AtomicBinOp op,
Type type, ptr::AtomicOrdering ordering,
104 std::optional<int64_t> alignment, const ::mlir::DataLayout *dataLayout,
107 assert(
false &&
"unimplemented, see TODO in the source.");
111bool AddressSpaceAttr::isValidAtomicXchg(
112 Type type, ptr::AtomicOrdering successOrdering,
113 ptr::AtomicOrdering failureOrdering, std::optional<int64_t> alignment,
114 const ::mlir::DataLayout *dataLayout,
117 assert(
false &&
"unimplemented, see TODO in the source.");
121bool AddressSpaceAttr::isValidAddrSpaceCast(
125 assert(
false &&
"unimplemented, see TODO in the source.");
129bool AddressSpaceAttr::isValidPtrIntCast(
134 assert(
false &&
"unimplemented, see TODO in the source.");
144 Attribute id, AliasScopeDomainAttr domain,
145 StringAttr description) {
148 if (!llvm::isa<StringAttr, DistinctAttr>(
id))
150 <<
"id of an alias scope must be a StringAttr or a DistrinctAttr";
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>(
175 return llvm::isa<DICommonBlockAttr, DICompileUnitAttr, DICompositeTypeAttr,
177 DIModuleAttr, DINamespaceAttr>(attr);
185 return llvm::isa<DILexicalBlockAttr, DILexicalBlockFileAttr,
186 DISubprogramAttr>(attr);
194 return llvm::isa<DILocalVariableAttr, DIGlobalVariableAttr>(attr);
202 return llvm::isa<DINullTypeAttr, DIBasicTypeAttr, DICompositeTypeAttr,
203 DIDerivedTypeAttr, DIStringTypeAttr, DISubroutineTypeAttr>(
211LogicalResult DIDerivedTypeAttr::verify(
214 uint64_t sizeInBits, uint32_t alignInBits, uint64_t offsetInBits,
215 std::optional<unsigned> dwarfAddressSpace, DIFlags flags,
217 if (extraData && !llvm::isa<DINodeAttr, IntegerAttr>(extraData))
218 return emitError() <<
"extraData must be a DINodeAttr or an IntegerAttr";
227 return llvm::isa<TBAATypeDescriptorAttr, TBAARootAttr>(attr);
234MemoryEffectsAttr MemoryEffectsAttr::get(
MLIRContext *context,
236 if (memInfoArgs.empty())
237 return MemoryEffectsAttr::get(context, ModRefInfo::ModRef,
243 if (memInfoArgs.size() == 6)
244 return MemoryEffectsAttr::get(context, memInfoArgs[0], memInfoArgs[1],
245 memInfoArgs[2], memInfoArgs[3],
246 memInfoArgs[4], memInfoArgs[5]);
250bool MemoryEffectsAttr::isReadWrite() {
251 if (this->getArgMem() != ModRefInfo::ModRef)
253 if (this->getInaccessibleMem() != ModRefInfo::ModRef)
255 if (this->getOther() != ModRefInfo::ModRef)
257 if (this->getErrnoMem() != ModRefInfo::ModRef)
259 if (this->getTargetMem0() != ModRefInfo::ModRef)
261 if (this->getTargetMem1() != ModRefInfo::ModRef)
270DIExpressionAttr DIExpressionAttr::get(MLIRContext *context) {
271 return get(context, ArrayRef<DIExpressionElemAttr>({}));
276 auto operandParser = [&]() -> LogicalResult {
277 uint64_t operand = 0;
278 if (!args.empty() && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
282 operand = llvm::dwarf::getAttributeEncoding(keyword);
286 <<
"encountered unknown attribute encoding \"" << keyword
298 <<
"expected integer operand";
302 args.push_back(operand);
313 llvm::interleaveComma(args, printer, [&](uint64_t operand) {
314 if (i > 0 && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
315 if (
const StringRef keyword =
316 llvm::dwarf::AttributeEncodingString(operand);
332DIRecursiveTypeAttrInterface
333DICompositeTypeAttr::withRecId(DistinctAttr recId) {
334 return DICompositeTypeAttr::get(
335 getContext(), recId, getIsRecSelf(), getTag(), getName(), getFile(),
336 getLine(), getScope(), getBaseType(), getFlags(), getSizeInBits(),
337 getAlignInBits(), getDataLocation(), getRank(), getAllocated(),
338 getAssociated(), getIdentifier(), getDiscriminator(), getElements());
341DIRecursiveTypeAttrInterface
342DICompositeTypeAttr::getRecSelf(DistinctAttr recId) {
343 return DICompositeTypeAttr::get(recId.
getContext(), recId,
true,
344 0, {}, {}, 0, {}, {}, DIFlags(), 0, 0, {}, {},
352DIRecursiveTypeAttrInterface DICompileUnitAttr::withRecId(DistinctAttr recId) {
353 return DICompileUnitAttr::get(
354 getContext(), recId, getIsRecSelf(), getId(), getSourceLanguage(),
355 getFile(), getProducer(), getIsOptimized(), getEmissionKind(),
356 getIsDebugInfoForProfiling(), getNameTableKind(), getSplitDebugFilename(),
357 getImportedEntities());
360DIRecursiveTypeAttrInterface DICompileUnitAttr::getRecSelf(DistinctAttr recId) {
362 return DICompileUnitAttr::get(
365 false, DIEmissionKind::None,
366 false, DINameTableKind::Default,
374DIRecursiveTypeAttrInterface DISubprogramAttr::withRecId(DistinctAttr recId) {
375 return DISubprogramAttr::get(
getContext(), recId, getIsRecSelf(), getId(),
376 getCompileUnit(), getScope(), getName(),
377 getLinkageName(), getFile(), getLine(),
378 getScopeLine(), getSubprogramFlags(),
getType(),
379 getRetainedNodes(), getAnnotations());
382DIRecursiveTypeAttrInterface DISubprogramAttr::getRecSelf(DistinctAttr recId) {
383 return DISubprogramAttr::get(recId.
getContext(), recId,
true,
384 {}, {}, {}, {}, {}, {}, 0, 0, {}, {}, {}, {});
391Attribute ConstantRangeAttr::parse(AsmParser &parser, Type odsType) {
393 IntegerType widthType;
398 unsigned bitWidth = widthType.getWidth();
399 APInt lower(bitWidth, 0);
400 APInt upper(bitWidth, 0);
405 lower = lower.sextOrTrunc(bitWidth);
406 upper = upper.sextOrTrunc(bitWidth);
411void ConstantRangeAttr::print(AsmPrinter &printer)
const {
412 printer <<
"<i" << getLower().getBitWidth() <<
", " << getLower() <<
", "
413 << getUpper() <<
">";
417ConstantRangeAttr::verify(llvm::function_ref<InFlightDiagnostic()>
emitError,
418 APInt lower, APInt upper) {
419 if (lower.getBitWidth() != upper.getBitWidth())
421 <<
"expected lower and upper to have matching bitwidths but got "
422 << lower.getBitWidth() <<
" vs. " << upper.getBitWidth();
430TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
431 llvm::ArrayRef<StringRef> features) {
432 return Base::get(context,
433 llvm::map_to_vector(features, [&](StringRef feature) {
434 return StringAttr::get(context, feature);
440 MLIRContext *context,
441 llvm::ArrayRef<StringRef> features) {
442 return Base::getChecked(
emitError, context,
443 llvm::map_to_vector(features, [&](StringRef feature) {
444 return StringAttr::get(context, feature);
448TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
449 StringRef targetFeatures) {
450 SmallVector<StringRef> features;
451 targetFeatures.split(features,
',', -1,
453 return get(context, features);
458 MLIRContext *context, StringRef targetFeatures) {
459 SmallVector<StringRef> features;
460 targetFeatures.split(features,
',', -1,
462 ArrayRef featuresRef(features);
468 llvm::ArrayRef<StringAttr> features) {
469 for (StringAttr featureAttr : features) {
470 if (!featureAttr || featureAttr.empty())
471 return emitError() <<
"target features can not be null or empty";
472 auto feature = featureAttr.strref();
473 if (feature[0] !=
'+' && feature[0] !=
'-')
474 return emitError() <<
"target features must start with '+' or '-'";
475 if (feature.contains(
','))
476 return emitError() <<
"target features can not contain ','";
481bool TargetFeaturesAttr::contains(StringAttr feature)
const {
485 return llvm::is_contained(getFeatures(), feature);
488bool TargetFeaturesAttr::contains(StringRef feature)
const {
491 return llvm::is_contained(getFeatures(), feature);
494std::string TargetFeaturesAttr::getFeaturesString()
const {
495 std::string featuresString;
496 llvm::raw_string_ostream ss(featuresString);
498 getFeatures(), ss, [&](
auto &feature) { ss << feature.strref(); },
",");
499 return featuresString;
502TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
506 return parentFunction.getOperation()->getAttrOfType<TargetFeaturesAttr>(
511 auto stringKey = dyn_cast<StringAttr>(key);
518 if (
contains((std::string(
"+") + stringKey.strref()).str()))
521 if (
contains((std::string(
"-") + stringKey.strref()).str()))
532 if (
auto stringAttrKey = dyn_cast<StringAttr>(key)) {
533 if (stringAttrKey.getValue() ==
"triple")
535 if (stringAttrKey.getValue() ==
"chip")
537 if (stringAttrKey.getValue() ==
"features" && getFeatures())
538 return getFeatures();
549 LLVM::ModFlagBehavior flagBehavior, StringAttr key,
551 if (key == LLVMDialect::getModuleFlagKeyCGProfileName()) {
552 auto arrayAttr = dyn_cast<ArrayAttr>(value);
553 if ((!arrayAttr) || (!llvm::all_of(arrayAttr, [](Attribute attr) {
554 return isa<ModuleFlagCGProfileEntryAttr>(attr);
557 <<
"'CG Profile' key expects an array of '#llvm.cgprofile_entry'";
561 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName()) {
562 if (!isa<ModuleFlagProfileSummaryAttr>(value))
563 return emitError() <<
"'ProfileSummary' key expects a "
564 "'#llvm.profile_summary' attribute";
568 if (isa<IntegerAttr, StringAttr>(value))
576 if (
auto arrayAttr = dyn_cast<ArrayAttr>(value))
577 if (!arrayAttr.empty() &&
578 llvm::all_of(arrayAttr, [](Attribute a) { return isa<StringAttr>(a); }))
581 return emitError() <<
"only integer, string, and string-array values are "
582 "currently supported for unknown key '"
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 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.
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'.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
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