MLIR  21.0.0git
LLVMAttrs.cpp
Go to the documentation of this file.
1 //===- LLVMAttrs.cpp - LLVM Attributes registration -----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the attribute details for the LLVM IR dialect in MLIR.
10 //
11 //===----------------------------------------------------------------------===//
12 
15 #include "mlir/IR/Builders.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/TypeSwitch.h"
20 #include "llvm/BinaryFormat/Dwarf.h"
21 #include "llvm/IR/DebugInfoMetadata.h"
22 #include <optional>
23 
24 using namespace mlir;
25 using namespace mlir::LLVM;
26 
27 /// Parses DWARF expression arguments with respect to the DWARF operation
28 /// opcode. Some DWARF expression operations have a specific number of operands
29 /// and may appear in a textual form.
30 static ParseResult parseExpressionArg(AsmParser &parser, uint64_t opcode,
31  SmallVector<uint64_t> &args);
32 
33 /// Prints DWARF expression arguments with respect to the specific DWARF
34 /// operation. Some operands are printed in their textual form.
35 static void printExpressionArg(AsmPrinter &printer, uint64_t opcode,
36  ArrayRef<uint64_t> args);
37 
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"
42 
43 //===----------------------------------------------------------------------===//
44 // LLVMDialect registration
45 //===----------------------------------------------------------------------===//
46 
47 void LLVMDialect::registerAttributes() {
48  addAttributes<
49 #define GET_ATTRDEF_LIST
50 #include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc"
51 
52  >();
53 }
54 
55 //===----------------------------------------------------------------------===//
56 // AliasScopeAttr
57 //===----------------------------------------------------------------------===//
58 
59 LogicalResult
61  Attribute id, AliasScopeDomainAttr domain,
62  StringAttr description) {
63  (void)domain;
64  (void)description;
65  if (!llvm::isa<StringAttr, DistinctAttr>(id))
66  return emitError()
67  << "id of an alias scope must be a StringAttr or a DistrinctAttr";
68 
69  return success();
70 }
71 
72 //===----------------------------------------------------------------------===//
73 // DINodeAttr
74 //===----------------------------------------------------------------------===//
75 
77  return llvm::isa<
78  DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr,
79  DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr, DIGenericSubrangeAttr,
80  DIGlobalVariableAttr, DIImportedEntityAttr, DILabelAttr,
81  DILexicalBlockAttr, DILexicalBlockFileAttr, DILocalVariableAttr,
82  DIModuleAttr, DINamespaceAttr, DINullTypeAttr, DIAnnotationAttr,
83  DIStringTypeAttr, DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>(
84  attr);
85 }
86 
87 //===----------------------------------------------------------------------===//
88 // DIScopeAttr
89 //===----------------------------------------------------------------------===//
90 
92  return llvm::isa<DICommonBlockAttr, DICompileUnitAttr, DICompositeTypeAttr,
93  DIFileAttr, DILocalScopeAttr, DIModuleAttr, DINamespaceAttr>(
94  attr);
95 }
96 
97 //===----------------------------------------------------------------------===//
98 // DILocalScopeAttr
99 //===----------------------------------------------------------------------===//
100 
102  return llvm::isa<DILexicalBlockAttr, DILexicalBlockFileAttr,
103  DISubprogramAttr>(attr);
104 }
105 
106 //===----------------------------------------------------------------------===//
107 // DIVariableAttr
108 //===----------------------------------------------------------------------===//
109 
111  return llvm::isa<DILocalVariableAttr, DIGlobalVariableAttr>(attr);
112 }
113 
114 //===----------------------------------------------------------------------===//
115 // DITypeAttr
116 //===----------------------------------------------------------------------===//
117 
119  return llvm::isa<DINullTypeAttr, DIBasicTypeAttr, DICompositeTypeAttr,
120  DIDerivedTypeAttr, DIStringTypeAttr, DISubroutineTypeAttr>(
121  attr);
122 }
123 
124 //===----------------------------------------------------------------------===//
125 // TBAANodeAttr
126 //===----------------------------------------------------------------------===//
127 
129  return llvm::isa<TBAATypeDescriptorAttr, TBAARootAttr>(attr);
130 }
131 
132 //===----------------------------------------------------------------------===//
133 // MemoryEffectsAttr
134 //===----------------------------------------------------------------------===//
135 
136 MemoryEffectsAttr MemoryEffectsAttr::get(MLIRContext *context,
137  ArrayRef<ModRefInfo> memInfoArgs) {
138  if (memInfoArgs.empty())
139  return MemoryEffectsAttr::get(context, ModRefInfo::ModRef,
140  ModRefInfo::ModRef, ModRefInfo::ModRef);
141  if (memInfoArgs.size() == 3)
142  return MemoryEffectsAttr::get(context, memInfoArgs[0], memInfoArgs[1],
143  memInfoArgs[2]);
144  return {};
145 }
146 
147 bool MemoryEffectsAttr::isReadWrite() {
148  if (this->getArgMem() != ModRefInfo::ModRef)
149  return false;
150  if (this->getInaccessibleMem() != ModRefInfo::ModRef)
151  return false;
152  if (this->getOther() != ModRefInfo::ModRef)
153  return false;
154  return true;
155 }
156 
157 //===----------------------------------------------------------------------===//
158 // DIExpression
159 //===----------------------------------------------------------------------===//
160 
161 DIExpressionAttr DIExpressionAttr::get(MLIRContext *context) {
162  return get(context, ArrayRef<DIExpressionElemAttr>({}));
163 }
164 
165 ParseResult parseExpressionArg(AsmParser &parser, uint64_t opcode,
166  SmallVector<uint64_t> &args) {
167  auto operandParser = [&]() -> LogicalResult {
168  uint64_t operand = 0;
169  if (!args.empty() && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
170  // Attempt to parse a keyword.
171  StringRef keyword;
172  if (succeeded(parser.parseOptionalKeyword(&keyword))) {
173  operand = llvm::dwarf::getAttributeEncoding(keyword);
174  if (operand == 0) {
175  // The keyword is invalid.
176  return parser.emitError(parser.getCurrentLocation())
177  << "encountered unknown attribute encoding \"" << keyword
178  << "\"";
179  }
180  }
181  }
182 
183  // operand should be non-zero if a keyword was parsed. Otherwise, the
184  // operand MUST be an integer.
185  if (operand == 0) {
186  // Parse the next operand as an integer.
187  if (parser.parseInteger(operand)) {
188  return parser.emitError(parser.getCurrentLocation())
189  << "expected integer operand";
190  }
191  }
192 
193  args.push_back(operand);
194  return success();
195  };
196 
197  // Parse operands as a comma-separated list.
198  return parser.parseCommaSeparatedList(operandParser);
199 }
200 
201 void printExpressionArg(AsmPrinter &printer, uint64_t opcode,
202  ArrayRef<uint64_t> args) {
203  size_t i = 0;
204  llvm::interleaveComma(args, printer, [&](uint64_t operand) {
205  if (i > 0 && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
206  if (const StringRef keyword =
207  llvm::dwarf::AttributeEncodingString(operand);
208  !keyword.empty()) {
209  printer << keyword;
210  return;
211  }
212  }
213  // All operands are expected to be printed as integers.
214  printer << operand;
215  i++;
216  });
217 }
218 
219 //===----------------------------------------------------------------------===//
220 // DICompositeTypeAttr
221 //===----------------------------------------------------------------------===//
222 
223 DIRecursiveTypeAttrInterface
224 DICompositeTypeAttr::withRecId(DistinctAttr recId) {
226  getContext(), recId, getIsRecSelf(), getTag(), getName(), getFile(),
227  getLine(), getScope(), getBaseType(), getFlags(), getSizeInBits(),
228  getAlignInBits(), getElements(), getDataLocation(), getRank(),
229  getAllocated(), getAssociated());
230 }
231 
232 DIRecursiveTypeAttrInterface
233 DICompositeTypeAttr::getRecSelf(DistinctAttr recId) {
234  return DICompositeTypeAttr::get(recId.getContext(), recId, /*isRecSelf=*/true,
235  0, {}, {}, 0, {}, {}, DIFlags(), 0, 0, {}, {},
236  {}, {}, {});
237 }
238 
239 //===----------------------------------------------------------------------===//
240 // DISubprogramAttr
241 //===----------------------------------------------------------------------===//
242 
243 DIRecursiveTypeAttrInterface DISubprogramAttr::withRecId(DistinctAttr recId) {
244  return DISubprogramAttr::get(getContext(), recId, getIsRecSelf(), getId(),
245  getCompileUnit(), getScope(), getName(),
246  getLinkageName(), getFile(), getLine(),
247  getScopeLine(), getSubprogramFlags(), getType(),
248  getRetainedNodes(), getAnnotations());
249 }
250 
251 DIRecursiveTypeAttrInterface DISubprogramAttr::getRecSelf(DistinctAttr recId) {
252  return DISubprogramAttr::get(recId.getContext(), recId, /*isRecSelf=*/true,
253  {}, {}, {}, {}, {}, {}, 0, 0, {}, {}, {}, {});
254 }
255 
256 //===----------------------------------------------------------------------===//
257 // ConstantRangeAttr
258 //===----------------------------------------------------------------------===//
259 
261  llvm::SMLoc loc = parser.getCurrentLocation();
262  IntegerType widthType;
263  if (parser.parseLess() || parser.parseType(widthType) ||
264  parser.parseComma()) {
265  return Attribute{};
266  }
267  unsigned bitWidth = widthType.getWidth();
268  APInt lower(bitWidth, 0);
269  APInt upper(bitWidth, 0);
270  if (parser.parseInteger(lower) || parser.parseComma() ||
271  parser.parseInteger(upper) || parser.parseGreater())
272  return Attribute{};
273  // Non-positive numbers may use more bits than `bitWidth`
274  lower = lower.sextOrTrunc(bitWidth);
275  upper = upper.sextOrTrunc(bitWidth);
276  return parser.getChecked<ConstantRangeAttr>(loc, parser.getContext(), lower,
277  upper);
278 }
279 
280 void ConstantRangeAttr::print(AsmPrinter &printer) const {
281  printer << "<i" << getLower().getBitWidth() << ", " << getLower() << ", "
282  << getUpper() << ">";
283 }
284 
285 LogicalResult
287  APInt lower, APInt upper) {
288  if (lower.getBitWidth() != upper.getBitWidth())
289  return emitError()
290  << "expected lower and upper to have matching bitwidths but got "
291  << lower.getBitWidth() << " vs. " << upper.getBitWidth();
292  return success();
293 }
294 
295 //===----------------------------------------------------------------------===//
296 // TargetFeaturesAttr
297 //===----------------------------------------------------------------------===//
298 
299 TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
300  llvm::ArrayRef<StringRef> features) {
301  return Base::get(context,
302  llvm::map_to_vector(features, [&](StringRef feature) {
303  return StringAttr::get(context, feature);
304  }));
305 }
306 
307 TargetFeaturesAttr
308 TargetFeaturesAttr::getChecked(function_ref<InFlightDiagnostic()> emitError,
309  MLIRContext *context,
310  llvm::ArrayRef<StringRef> features) {
311  return Base::getChecked(emitError, context,
312  llvm::map_to_vector(features, [&](StringRef feature) {
313  return StringAttr::get(context, feature);
314  }));
315 }
316 
317 TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
318  StringRef targetFeatures) {
319  SmallVector<StringRef> features;
320  targetFeatures.split(features, ',', /*MaxSplit=*/-1,
321  /*KeepEmpty=*/false);
322  return get(context, features);
323 }
324 
325 TargetFeaturesAttr
326 TargetFeaturesAttr::getChecked(function_ref<InFlightDiagnostic()> emitError,
327  MLIRContext *context, StringRef targetFeatures) {
328  SmallVector<StringRef> features;
329  targetFeatures.split(features, ',', /*MaxSplit=*/-1,
330  /*KeepEmpty=*/false);
331  ArrayRef featuresRef(features);
332  return getChecked(emitError, context, featuresRef);
333 }
334 
335 LogicalResult
337  llvm::ArrayRef<StringAttr> features) {
338  for (StringAttr featureAttr : features) {
339  if (!featureAttr || featureAttr.empty())
340  return emitError() << "target features can not be null or empty";
341  auto feature = featureAttr.strref();
342  if (feature[0] != '+' && feature[0] != '-')
343  return emitError() << "target features must start with '+' or '-'";
344  if (feature.contains(','))
345  return emitError() << "target features can not contain ','";
346  }
347  return success();
348 }
349 
350 bool TargetFeaturesAttr::contains(StringAttr feature) const {
351  if (nullOrEmpty())
352  return false;
353  // Note: Using StringAttr does pointer comparisons.
354  return llvm::is_contained(getFeatures(), feature);
355 }
356 
357 bool TargetFeaturesAttr::contains(StringRef feature) const {
358  if (nullOrEmpty())
359  return false;
360  return llvm::is_contained(getFeatures(), feature);
361 }
362 
363 std::string TargetFeaturesAttr::getFeaturesString() const {
364  std::string featuresString;
365  llvm::raw_string_ostream ss(featuresString);
366  llvm::interleave(
367  getFeatures(), ss, [&](auto &feature) { ss << feature.strref(); }, ",");
368  return featuresString;
369 }
370 
371 TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
372  auto parentFunction = op->getParentOfType<FunctionOpInterface>();
373  if (!parentFunction)
374  return {};
375  return parentFunction.getOperation()->getAttrOfType<TargetFeaturesAttr>(
376  getAttributeName());
377 }
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.
Definition: LLVMAttrs.cpp:201
static ParseResult parseExpressionArg(AsmParser &parser, uint64_t opcode, SmallVector< uint64_t > &args)
Parses DWARF expression arguments with respect to the DWARF operation opcode.
Definition: LLVMAttrs.cpp:165
static bool contains(SMRange range, SMLoc loc)
Returns true if the given range contains the given source location.
Definition: MLIRServer.cpp:111
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
Definition: AsmPrinter.cpp:73
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.
Definition: Attributes.h:25
MLIRContext * getContext() const
Return the context this attribute belongs to.
Definition: Attributes.cpp:37
An attribute that associates a referenced attribute with a unique identifier.
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:314
This class represents a LLVM attribute that describes a local debug info scope.
Definition: LLVMAttrs.h:46
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:101
static bool classof(Attribute attr)
Definition: LLVMAttrs.cpp:76
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:91
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:118
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:110
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:128
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
Definition: Operation.h:238
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Definition: Query.cpp:20
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
Definition: Utils.cpp:305
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,...
Definition: Verifier.cpp:425