MLIR  20.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 LogicalResult 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 // DINodeAttr
56 //===----------------------------------------------------------------------===//
57 
59  return llvm::isa<
60  DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr,
61  DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr, DIGenericSubrangeAttr,
62  DIGlobalVariableAttr, DIImportedEntityAttr, DILabelAttr,
63  DILexicalBlockAttr, DILexicalBlockFileAttr, DILocalVariableAttr,
64  DIModuleAttr, DINamespaceAttr, DINullTypeAttr, DIAnnotationAttr,
65  DIStringTypeAttr, DISubprogramAttr, DISubrangeAttr, DISubroutineTypeAttr>(
66  attr);
67 }
68 
69 //===----------------------------------------------------------------------===//
70 // DIScopeAttr
71 //===----------------------------------------------------------------------===//
72 
74  return llvm::isa<DICommonBlockAttr, DICompileUnitAttr, DICompositeTypeAttr,
75  DIFileAttr, DILocalScopeAttr, DIModuleAttr, DINamespaceAttr>(
76  attr);
77 }
78 
79 //===----------------------------------------------------------------------===//
80 // DILocalScopeAttr
81 //===----------------------------------------------------------------------===//
82 
84  return llvm::isa<DILexicalBlockAttr, DILexicalBlockFileAttr,
85  DISubprogramAttr>(attr);
86 }
87 
88 //===----------------------------------------------------------------------===//
89 // DIVariableAttr
90 //===----------------------------------------------------------------------===//
91 
93  return llvm::isa<DILocalVariableAttr, DIGlobalVariableAttr>(attr);
94 }
95 
96 //===----------------------------------------------------------------------===//
97 // DITypeAttr
98 //===----------------------------------------------------------------------===//
99 
101  return llvm::isa<DINullTypeAttr, DIBasicTypeAttr, DICompositeTypeAttr,
102  DIDerivedTypeAttr, DIStringTypeAttr, DISubroutineTypeAttr>(
103  attr);
104 }
105 
106 //===----------------------------------------------------------------------===//
107 // TBAANodeAttr
108 //===----------------------------------------------------------------------===//
109 
111  return llvm::isa<TBAATypeDescriptorAttr, TBAARootAttr>(attr);
112 }
113 
114 //===----------------------------------------------------------------------===//
115 // MemoryEffectsAttr
116 //===----------------------------------------------------------------------===//
117 
118 MemoryEffectsAttr MemoryEffectsAttr::get(MLIRContext *context,
119  ArrayRef<ModRefInfo> memInfoArgs) {
120  if (memInfoArgs.empty())
121  return MemoryEffectsAttr::get(context, ModRefInfo::ModRef,
122  ModRefInfo::ModRef, ModRefInfo::ModRef);
123  if (memInfoArgs.size() == 3)
124  return MemoryEffectsAttr::get(context, memInfoArgs[0], memInfoArgs[1],
125  memInfoArgs[2]);
126  return {};
127 }
128 
129 bool MemoryEffectsAttr::isReadWrite() {
130  if (this->getArgMem() != ModRefInfo::ModRef)
131  return false;
132  if (this->getInaccessibleMem() != ModRefInfo::ModRef)
133  return false;
134  if (this->getOther() != ModRefInfo::ModRef)
135  return false;
136  return true;
137 }
138 
139 //===----------------------------------------------------------------------===//
140 // DIExpression
141 //===----------------------------------------------------------------------===//
142 
143 DIExpressionAttr DIExpressionAttr::get(MLIRContext *context) {
144  return get(context, ArrayRef<DIExpressionElemAttr>({}));
145 }
146 
147 LogicalResult parseExpressionArg(AsmParser &parser, uint64_t opcode,
148  SmallVector<uint64_t> &args) {
149  auto operandParser = [&]() -> LogicalResult {
150  uint64_t operand = 0;
151  if (!args.empty() && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
152  // Attempt to parse a keyword.
153  StringRef keyword;
154  if (succeeded(parser.parseOptionalKeyword(&keyword))) {
155  operand = llvm::dwarf::getAttributeEncoding(keyword);
156  if (operand == 0) {
157  // The keyword is invalid.
158  return parser.emitError(parser.getCurrentLocation())
159  << "encountered unknown attribute encoding \"" << keyword
160  << "\"";
161  }
162  }
163  }
164 
165  // operand should be non-zero if a keyword was parsed. Otherwise, the
166  // operand MUST be an integer.
167  if (operand == 0) {
168  // Parse the next operand as an integer.
169  if (parser.parseInteger(operand)) {
170  return parser.emitError(parser.getCurrentLocation())
171  << "expected integer operand";
172  }
173  }
174 
175  args.push_back(operand);
176  return success();
177  };
178 
179  // Parse operands as a comma-separated list.
180  return parser.parseCommaSeparatedList(operandParser);
181 }
182 
183 void printExpressionArg(AsmPrinter &printer, uint64_t opcode,
184  ArrayRef<uint64_t> args) {
185  size_t i = 0;
186  llvm::interleaveComma(args, printer, [&](uint64_t operand) {
187  if (i > 0 && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
188  if (const StringRef keyword =
189  llvm::dwarf::AttributeEncodingString(operand);
190  !keyword.empty()) {
191  printer << keyword;
192  return;
193  }
194  }
195  // All operands are expected to be printed as integers.
196  printer << operand;
197  i++;
198  });
199 }
200 
201 //===----------------------------------------------------------------------===//
202 // DICompositeTypeAttr
203 //===----------------------------------------------------------------------===//
204 
205 DIRecursiveTypeAttrInterface
206 DICompositeTypeAttr::withRecId(DistinctAttr recId) {
208  getContext(), recId, getIsRecSelf(), getTag(), getName(), getFile(),
209  getLine(), getScope(), getBaseType(), getFlags(), getSizeInBits(),
210  getAlignInBits(), getElements(), getDataLocation(), getRank(),
211  getAllocated(), getAssociated());
212 }
213 
214 DIRecursiveTypeAttrInterface
215 DICompositeTypeAttr::getRecSelf(DistinctAttr recId) {
216  return DICompositeTypeAttr::get(recId.getContext(), recId, /*isRecSelf=*/true,
217  0, {}, {}, 0, {}, {}, DIFlags(), 0, 0, {}, {},
218  {}, {}, {});
219 }
220 
221 //===----------------------------------------------------------------------===//
222 // DISubprogramAttr
223 //===----------------------------------------------------------------------===//
224 
225 DIRecursiveTypeAttrInterface DISubprogramAttr::withRecId(DistinctAttr recId) {
226  return DISubprogramAttr::get(getContext(), recId, getIsRecSelf(), getId(),
227  getCompileUnit(), getScope(), getName(),
228  getLinkageName(), getFile(), getLine(),
229  getScopeLine(), getSubprogramFlags(), getType(),
230  getRetainedNodes(), getAnnotations());
231 }
232 
233 DIRecursiveTypeAttrInterface DISubprogramAttr::getRecSelf(DistinctAttr recId) {
234  return DISubprogramAttr::get(recId.getContext(), recId, /*isRecSelf=*/true,
235  {}, {}, {}, {}, {}, 0, 0, {}, {}, {}, {}, {});
236 }
237 
238 //===----------------------------------------------------------------------===//
239 // ConstantRangeAttr
240 //===----------------------------------------------------------------------===//
241 
243  llvm::SMLoc loc = parser.getCurrentLocation();
244  IntegerType widthType;
245  if (parser.parseLess() || parser.parseType(widthType) ||
246  parser.parseComma()) {
247  return Attribute{};
248  }
249  unsigned bitWidth = widthType.getWidth();
250  APInt lower(bitWidth, 0);
251  APInt upper(bitWidth, 0);
252  if (parser.parseInteger(lower) || parser.parseComma() ||
253  parser.parseInteger(upper) || parser.parseGreater())
254  return Attribute{};
255  // For some reason, 0 is always parsed as 64-bits, fix that if needed.
256  if (lower.isZero())
257  lower = lower.sextOrTrunc(bitWidth);
258  if (upper.isZero())
259  upper = upper.sextOrTrunc(bitWidth);
260  return parser.getChecked<ConstantRangeAttr>(loc, parser.getContext(), lower,
261  upper);
262 }
263 
264 void ConstantRangeAttr::print(AsmPrinter &printer) const {
265  printer << "<i" << getLower().getBitWidth() << ", " << getLower() << ", "
266  << getUpper() << ">";
267 }
268 
269 LogicalResult
271  APInt lower, APInt upper) {
272  if (lower.getBitWidth() != upper.getBitWidth())
273  return emitError()
274  << "expected lower and upper to have matching bitwidths but got "
275  << lower.getBitWidth() << " vs. " << upper.getBitWidth();
276  return success();
277 }
278 
279 //===----------------------------------------------------------------------===//
280 // TargetFeaturesAttr
281 //===----------------------------------------------------------------------===//
282 
283 TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
284  llvm::ArrayRef<StringRef> features) {
285  return Base::get(context,
286  llvm::map_to_vector(features, [&](StringRef feature) {
287  return StringAttr::get(context, feature);
288  }));
289 }
290 
291 TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
292  StringRef targetFeatures) {
293  SmallVector<StringRef> features;
294  targetFeatures.split(features, ',', /*MaxSplit=*/-1,
295  /*KeepEmpty=*/false);
296  return get(context, features);
297 }
298 
299 LogicalResult
301  llvm::ArrayRef<StringAttr> features) {
302  for (StringAttr featureAttr : features) {
303  if (!featureAttr || featureAttr.empty())
304  return emitError() << "target features can not be null or empty";
305  auto feature = featureAttr.strref();
306  if (feature[0] != '+' && feature[0] != '-')
307  return emitError() << "target features must start with '+' or '-'";
308  if (feature.contains(','))
309  return emitError() << "target features can not contain ','";
310  }
311  return success();
312 }
313 
314 bool TargetFeaturesAttr::contains(StringAttr feature) const {
315  if (nullOrEmpty())
316  return false;
317  // Note: Using StringAttr does pointer comparisons.
318  return llvm::is_contained(getFeatures(), feature);
319 }
320 
321 bool TargetFeaturesAttr::contains(StringRef feature) const {
322  if (nullOrEmpty())
323  return false;
324  return llvm::is_contained(getFeatures(), feature);
325 }
326 
327 std::string TargetFeaturesAttr::getFeaturesString() const {
328  std::string featuresString;
329  llvm::raw_string_ostream ss(featuresString);
330  llvm::interleave(
331  getFeatures(), ss, [&](auto &feature) { ss << feature.strref(); }, ",");
332  return featuresString;
333 }
334 
335 TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
336  auto parentFunction = op->getParentOfType<FunctionOpInterface>();
337  if (!parentFunction)
338  return {};
339  return parentFunction.getOperation()->getAttrOfType<TargetFeaturesAttr>(
340  getAttributeName());
341 }
static MLIRContext * getContext(OpFoldResult val)
static LogicalResult parseExpressionArg(AsmParser &parser, uint64_t opcode, SmallVector< uint64_t > &args)
Parses DWARF expression arguments with respect to the DWARF operation opcode.
Definition: LLVMAttrs.cpp:147
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:183
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:83
static bool classof(Attribute attr)
Definition: LLVMAttrs.cpp:58
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:73
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:100
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:92
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:110
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:426