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 DISubprogramAttr::withRecId(DistinctAttr recId) {
338 return DISubprogramAttr::get(
getContext(), recId, getIsRecSelf(), getId(),
339 getCompileUnit(), getScope(), getName(),
340 getLinkageName(), getFile(), getLine(),
341 getScopeLine(), getSubprogramFlags(),
getType(),
342 getRetainedNodes(), getAnnotations());
345DIRecursiveTypeAttrInterface DISubprogramAttr::getRecSelf(DistinctAttr recId) {
346 return DISubprogramAttr::get(recId.
getContext(), recId,
true,
347 {}, {}, {}, {}, {}, {}, 0, 0, {}, {}, {}, {});
354Attribute ConstantRangeAttr::parse(AsmParser &parser, Type odsType) {
356 IntegerType widthType;
361 unsigned bitWidth = widthType.getWidth();
362 APInt lower(bitWidth, 0);
363 APInt upper(bitWidth, 0);
368 lower = lower.sextOrTrunc(bitWidth);
369 upper = upper.sextOrTrunc(bitWidth);
374void ConstantRangeAttr::print(AsmPrinter &printer)
const {
375 printer <<
"<i" << getLower().getBitWidth() <<
", " << getLower() <<
", "
376 << getUpper() <<
">";
380ConstantRangeAttr::verify(llvm::function_ref<InFlightDiagnostic()>
emitError,
381 APInt lower, APInt upper) {
382 if (lower.getBitWidth() != upper.getBitWidth())
384 <<
"expected lower and upper to have matching bitwidths but got "
385 << lower.getBitWidth() <<
" vs. " << upper.getBitWidth();
393TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
394 llvm::ArrayRef<StringRef> features) {
395 return Base::get(context,
396 llvm::map_to_vector(features, [&](StringRef feature) {
397 return StringAttr::get(context, feature);
403 MLIRContext *context,
404 llvm::ArrayRef<StringRef> features) {
405 return Base::getChecked(
emitError, context,
406 llvm::map_to_vector(features, [&](StringRef feature) {
407 return StringAttr::get(context, feature);
411TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
412 StringRef targetFeatures) {
413 SmallVector<StringRef> features;
414 targetFeatures.split(features,
',', -1,
416 return get(context, features);
421 MLIRContext *context, StringRef targetFeatures) {
422 SmallVector<StringRef> features;
423 targetFeatures.split(features,
',', -1,
425 ArrayRef featuresRef(features);
426 return getChecked(
emitError, context, featuresRef);
431 llvm::ArrayRef<StringAttr> features) {
432 for (StringAttr featureAttr : features) {
433 if (!featureAttr || featureAttr.empty())
434 return emitError() <<
"target features can not be null or empty";
435 auto feature = featureAttr.strref();
436 if (feature[0] !=
'+' && feature[0] !=
'-')
437 return emitError() <<
"target features must start with '+' or '-'";
438 if (feature.contains(
','))
439 return emitError() <<
"target features can not contain ','";
444bool TargetFeaturesAttr::contains(StringAttr feature)
const {
448 return llvm::is_contained(getFeatures(), feature);
451bool TargetFeaturesAttr::contains(StringRef feature)
const {
454 return llvm::is_contained(getFeatures(), feature);
457std::string TargetFeaturesAttr::getFeaturesString()
const {
458 std::string featuresString;
459 llvm::raw_string_ostream ss(featuresString);
461 getFeatures(), ss, [&](
auto &feature) { ss << feature.strref(); },
",");
462 return featuresString;
465TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
469 return parentFunction.getOperation()->getAttrOfType<TargetFeaturesAttr>(
474 auto stringKey = dyn_cast<StringAttr>(key);
481 if (
contains((std::string(
"+") + stringKey.strref()).str()))
484 if (
contains((std::string(
"-") + stringKey.strref()).str()))
495 if (
auto stringAttrKey = dyn_cast<StringAttr>(key)) {
496 if (stringAttrKey.getValue() ==
"triple")
498 if (stringAttrKey.getValue() ==
"chip")
500 if (stringAttrKey.getValue() ==
"features" && getFeatures())
501 return getFeatures();
512 LLVM::ModFlagBehavior flagBehavior, StringAttr key,
514 if (key == LLVMDialect::getModuleFlagKeyCGProfileName()) {
515 auto arrayAttr = dyn_cast<ArrayAttr>(value);
516 if ((!arrayAttr) || (!llvm::all_of(arrayAttr, [](Attribute attr) {
517 return isa<ModuleFlagCGProfileEntryAttr>(attr);
520 <<
"'CG Profile' key expects an array of '#llvm.cgprofile_entry'";
524 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName()) {
525 if (!isa<ModuleFlagProfileSummaryAttr>(value))
526 return emitError() <<
"'ProfileSummary' key expects a "
527 "'#llvm.profile_summary' attribute";
531 if (isa<IntegerAttr, StringAttr>(value))
534 return emitError() <<
"only integer and string values are currently "
535 "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 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