20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/ADT/TypeSwitch.h"
22 #include "llvm/BinaryFormat/Dwarf.h"
31 SmallVector<uint64_t> &args);
36 ArrayRef<uint64_t> args);
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"
47 void 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";
86 bool AddressSpaceAttr::isValidLoad(
87 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
88 const ::mlir::DataLayout *dataLayout,
94 bool AddressSpaceAttr::isValidStore(
95 Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
96 const ::mlir::DataLayout *dataLayout,
102 bool 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.");
111 bool 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.");
121 bool AddressSpaceAttr::isValidAddrSpaceCast(
125 assert(
false &&
"unimplemented, see TODO in the source.");
129 bool 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);
221 if (memInfoArgs.empty())
223 ModRefInfo::ModRef, ModRefInfo::ModRef);
224 if (memInfoArgs.size() == 3)
230 bool MemoryEffectsAttr::isReadWrite() {
231 if (this->getArgMem() != ModRefInfo::ModRef)
233 if (this->getInaccessibleMem() != ModRefInfo::ModRef)
235 if (this->getOther() != ModRefInfo::ModRef)
245 return get(context, ArrayRef<DIExpressionElemAttr>({}));
249 SmallVector<uint64_t> &args) {
250 auto operandParser = [&]() -> LogicalResult {
251 uint64_t operand = 0;
252 if (!args.empty() && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
256 operand = llvm::dwarf::getAttributeEncoding(keyword);
260 <<
"encountered unknown attribute encoding \"" << keyword
272 <<
"expected integer operand";
276 args.push_back(operand);
285 ArrayRef<uint64_t> args) {
287 llvm::interleaveComma(args, printer, [&](uint64_t operand) {
288 if (i > 0 && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
289 if (
const StringRef keyword =
290 llvm::dwarf::AttributeEncodingString(operand);
306 DIRecursiveTypeAttrInterface
309 getContext(), recId, getIsRecSelf(), getTag(), getName(), getFile(),
310 getLine(), getScope(), getBaseType(), getFlags(), getSizeInBits(),
311 getAlignInBits(), getDataLocation(), getRank(), getAllocated(),
312 getAssociated(), getElements());
315 DIRecursiveTypeAttrInterface
318 0, {}, {}, 0, {}, {}, DIFlags(), 0, 0, {}, {},
326 DIRecursiveTypeAttrInterface DISubprogramAttr::withRecId(
DistinctAttr recId) {
328 getCompileUnit(), getScope(), getName(),
329 getLinkageName(), getFile(), getLine(),
330 getScopeLine(), getSubprogramFlags(),
getType(),
331 getRetainedNodes(), getAnnotations());
334 DIRecursiveTypeAttrInterface DISubprogramAttr::getRecSelf(
DistinctAttr recId) {
336 {}, {}, {}, {}, {}, {}, 0, 0, {}, {}, {}, {});
345 IntegerType widthType;
350 unsigned bitWidth = widthType.getWidth();
351 APInt lower(bitWidth, 0);
352 APInt upper(bitWidth, 0);
357 lower = lower.sextOrTrunc(bitWidth);
358 upper = upper.sextOrTrunc(bitWidth);
364 printer <<
"<i" << getLower().getBitWidth() <<
", " << getLower() <<
", "
365 << getUpper() <<
">";
370 APInt lower, APInt upper) {
371 if (lower.getBitWidth() != upper.getBitWidth())
373 <<
"expected lower and upper to have matching bitwidths but got "
374 << lower.getBitWidth() <<
" vs. " << upper.getBitWidth();
385 llvm::map_to_vector(features, [&](StringRef feature) {
394 return Base::getChecked(
emitError, context,
395 llvm::map_to_vector(features, [&](StringRef feature) {
401 StringRef targetFeatures) {
402 SmallVector<StringRef> features;
403 targetFeatures.split(features,
',', -1,
405 return get(context, features);
411 SmallVector<StringRef> features;
412 targetFeatures.split(features,
',', -1,
414 ArrayRef featuresRef(features);
415 return getChecked(
emitError, context, featuresRef);
421 for (StringAttr featureAttr : features) {
422 if (!featureAttr || featureAttr.empty())
423 return emitError() <<
"target features can not be null or empty";
424 auto feature = featureAttr.strref();
425 if (feature[0] !=
'+' && feature[0] !=
'-')
426 return emitError() <<
"target features must start with '+' or '-'";
427 if (feature.contains(
','))
428 return emitError() <<
"target features can not contain ','";
437 return llvm::is_contained(getFeatures(), feature);
443 return llvm::is_contained(getFeatures(), feature);
446 std::string TargetFeaturesAttr::getFeaturesString()
const {
447 std::string featuresString;
448 llvm::raw_string_ostream ss(featuresString);
450 getFeatures(), ss, [&](
auto &feature) { ss << feature.strref(); },
",");
451 return featuresString;
454 TargetFeaturesAttr TargetFeaturesAttr::featuresAt(
Operation *op) {
458 return parentFunction.getOperation()->getAttrOfType<TargetFeaturesAttr>(
463 auto stringKey = dyn_cast<StringAttr>(key);
470 if (
contains((std::string(
"+") + stringKey.strref()).str()))
473 if (
contains((std::string(
"-") + stringKey.strref()).str()))
484 if (
auto stringAttrKey = dyn_cast<StringAttr>(key)) {
485 if (stringAttrKey.getValue() ==
"triple")
487 if (stringAttrKey.getValue() ==
"chip")
489 if (stringAttrKey.getValue() ==
"features" && getFeatures())
490 return getFeatures();
501 LLVM::ModFlagBehavior flagBehavior, StringAttr key,
503 if (key == LLVMDialect::getModuleFlagKeyCGProfileName()) {
504 auto arrayAttr = dyn_cast<ArrayAttr>(value);
505 if ((!arrayAttr) || (!llvm::all_of(arrayAttr, [](
Attribute attr) {
506 return isa<ModuleFlagCGProfileEntryAttr>(attr);
509 <<
"'CG Profile' key expects an array of '#llvm.cgprofile_entry'";
513 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName()) {
514 if (!isa<ModuleFlagProfileSummaryAttr>(value))
515 return emitError() <<
"'ProfileSummary' key expects a "
516 "'#llvm.profile_summary' attribute";
520 if (isa<IntegerAttr, StringAttr>(value))
523 return emitError() <<
"only integer and string values are currently "
524 "supported for unknown key '"
static MLIRContext * getContext(OpFoldResult val)
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.
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
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)
An attribute that associates a referenced attribute with a unique identifier.
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.
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.
MLIRContext is the top-level object for a collection of MLIR operations.
Operation is the basic unit of execution within MLIR.
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.
FailureOr< Attribute > query(Operation *op, ArrayRef< DataLayoutEntryKey > keys, bool emitError=false)
Perform a DLTI-query at op, recursively querying each key of keys on query interface-implementing att...
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Include the generated interface declarations.
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...
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...