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>(
212 return llvm::isa<TBAATypeDescriptorAttr, TBAARootAttr>(attr);
219MemoryEffectsAttr MemoryEffectsAttr::get(
MLIRContext *context,
221 if (memInfoArgs.empty())
222 return MemoryEffectsAttr::get(context, 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]);
235bool MemoryEffectsAttr::isReadWrite() {
236 if (this->getArgMem() != ModRefInfo::ModRef)
238 if (this->getInaccessibleMem() != ModRefInfo::ModRef)
240 if (this->getOther() != ModRefInfo::ModRef)
242 if (this->getErrnoMem() != ModRefInfo::ModRef)
244 if (this->getTargetMem0() != ModRefInfo::ModRef)
246 if (this->getTargetMem1() != ModRefInfo::ModRef)
255DIExpressionAttr DIExpressionAttr::get(MLIRContext *context) {
256 return get(context, ArrayRef<DIExpressionElemAttr>({}));
261 auto operandParser = [&]() -> LogicalResult {
262 uint64_t operand = 0;
263 if (!args.empty() && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
267 operand = llvm::dwarf::getAttributeEncoding(keyword);
271 <<
"encountered unknown attribute encoding \"" << keyword
283 <<
"expected integer operand";
287 args.push_back(operand);
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);
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());
326DIRecursiveTypeAttrInterface
327DICompositeTypeAttr::getRecSelf(DistinctAttr recId) {
328 return DICompositeTypeAttr::get(recId.
getContext(), recId,
true,
329 0, {}, {}, 0, {}, {}, DIFlags(), 0, 0, {}, {},
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());
345DIRecursiveTypeAttrInterface DICompileUnitAttr::getRecSelf(DistinctAttr recId) {
347 return DICompileUnitAttr::get(
350 false, DIEmissionKind::None,
351 false, DINameTableKind::Default,
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());
367DIRecursiveTypeAttrInterface DISubprogramAttr::getRecSelf(DistinctAttr recId) {
368 return DISubprogramAttr::get(recId.
getContext(), recId,
true,
369 {}, {}, {}, {}, {}, {}, 0, 0, {}, {}, {}, {});
376Attribute ConstantRangeAttr::parse(AsmParser &parser, Type odsType) {
378 IntegerType widthType;
383 unsigned bitWidth = widthType.getWidth();
384 APInt lower(bitWidth, 0);
385 APInt upper(bitWidth, 0);
390 lower = lower.sextOrTrunc(bitWidth);
391 upper = upper.sextOrTrunc(bitWidth);
396void ConstantRangeAttr::print(AsmPrinter &printer)
const {
397 printer <<
"<i" << getLower().getBitWidth() <<
", " << getLower() <<
", "
398 << getUpper() <<
">";
402ConstantRangeAttr::verify(llvm::function_ref<InFlightDiagnostic()>
emitError,
403 APInt lower, APInt upper) {
404 if (lower.getBitWidth() != upper.getBitWidth())
406 <<
"expected lower and upper to have matching bitwidths but got "
407 << lower.getBitWidth() <<
" vs. " << upper.getBitWidth();
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);
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);
433TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
434 StringRef targetFeatures) {
435 SmallVector<StringRef> features;
436 targetFeatures.split(features,
',', -1,
438 return get(context, features);
443 MLIRContext *context, StringRef targetFeatures) {
444 SmallVector<StringRef> features;
445 targetFeatures.split(features,
',', -1,
447 ArrayRef featuresRef(features);
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 ','";
466bool TargetFeaturesAttr::contains(StringAttr feature)
const {
470 return llvm::is_contained(getFeatures(), feature);
473bool TargetFeaturesAttr::contains(StringRef feature)
const {
476 return llvm::is_contained(getFeatures(), feature);
479std::string TargetFeaturesAttr::getFeaturesString()
const {
480 std::string featuresString;
481 llvm::raw_string_ostream ss(featuresString);
483 getFeatures(), ss, [&](
auto &feature) { ss << feature.strref(); },
",");
484 return featuresString;
487TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
491 return parentFunction.getOperation()->getAttrOfType<TargetFeaturesAttr>(
496 auto stringKey = dyn_cast<StringAttr>(key);
503 if (
contains((std::string(
"+") + stringKey.strref()).str()))
506 if (
contains((std::string(
"-") + stringKey.strref()).str()))
517 if (
auto stringAttrKey = dyn_cast<StringAttr>(key)) {
518 if (stringAttrKey.getValue() ==
"triple")
520 if (stringAttrKey.getValue() ==
"chip")
522 if (stringAttrKey.getValue() ==
"features" && getFeatures())
523 return getFeatures();
534 LLVM::ModFlagBehavior flagBehavior, StringAttr key,
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);
542 <<
"'CG Profile' key expects an array of '#llvm.cgprofile_entry'";
546 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName()) {
547 if (!isa<ModuleFlagProfileSummaryAttr>(value))
548 return emitError() <<
"'ProfileSummary' key expects a "
549 "'#llvm.profile_summary' attribute";
553 if (isa<IntegerAttr, StringAttr>(value))
561 if (
auto arrayAttr = dyn_cast<ArrayAttr>(value))
562 if (!arrayAttr.empty() &&
563 llvm::all_of(arrayAttr, [](Attribute a) { return isa<StringAttr>(a); }))
566 return emitError() <<
"only integer, string, and string-array values are "
567 "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)
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.
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