MLIR  19.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<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
60  DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
61  DILabelAttr, DILexicalBlockAttr, DILexicalBlockFileAttr,
62  DILocalVariableAttr, DIModuleAttr, DINamespaceAttr,
63  DINullTypeAttr, DISubprogramAttr, DISubrangeAttr,
64  DISubroutineTypeAttr>(attr);
65 }
66 
67 //===----------------------------------------------------------------------===//
68 // DIScopeAttr
69 //===----------------------------------------------------------------------===//
70 
72  return llvm::isa<DICompileUnitAttr, DICompositeTypeAttr, DIFileAttr,
73  DILocalScopeAttr, DIModuleAttr, DINamespaceAttr>(attr);
74 }
75 
76 //===----------------------------------------------------------------------===//
77 // DILocalScopeAttr
78 //===----------------------------------------------------------------------===//
79 
81  return llvm::isa<DILexicalBlockAttr, DILexicalBlockFileAttr,
82  DISubprogramAttr>(attr);
83 }
84 
85 //===----------------------------------------------------------------------===//
86 // DITypeAttr
87 //===----------------------------------------------------------------------===//
88 
90  return llvm::isa<DINullTypeAttr, DIBasicTypeAttr, DICompositeTypeAttr,
91  DIDerivedTypeAttr, DISubroutineTypeAttr>(attr);
92 }
93 
94 //===----------------------------------------------------------------------===//
95 // TBAANodeAttr
96 //===----------------------------------------------------------------------===//
97 
99  return llvm::isa<TBAATypeDescriptorAttr, TBAARootAttr>(attr);
100 }
101 
102 //===----------------------------------------------------------------------===//
103 // MemoryEffectsAttr
104 //===----------------------------------------------------------------------===//
105 
106 MemoryEffectsAttr MemoryEffectsAttr::get(MLIRContext *context,
107  ArrayRef<ModRefInfo> memInfoArgs) {
108  if (memInfoArgs.empty())
109  return MemoryEffectsAttr::get(context, ModRefInfo::ModRef,
110  ModRefInfo::ModRef, ModRefInfo::ModRef);
111  if (memInfoArgs.size() == 3)
112  return MemoryEffectsAttr::get(context, memInfoArgs[0], memInfoArgs[1],
113  memInfoArgs[2]);
114  return {};
115 }
116 
117 bool MemoryEffectsAttr::isReadWrite() {
118  if (this->getArgMem() != ModRefInfo::ModRef)
119  return false;
120  if (this->getInaccessibleMem() != ModRefInfo::ModRef)
121  return false;
122  if (this->getOther() != ModRefInfo::ModRef)
123  return false;
124  return true;
125 }
126 
127 //===----------------------------------------------------------------------===//
128 // DIExpression
129 //===----------------------------------------------------------------------===//
130 
131 DIExpressionAttr DIExpressionAttr::get(MLIRContext *context) {
132  return get(context, ArrayRef<DIExpressionElemAttr>({}));
133 }
134 
135 LogicalResult parseExpressionArg(AsmParser &parser, uint64_t opcode,
136  SmallVector<uint64_t> &args) {
137  auto operandParser = [&]() -> LogicalResult {
138  uint64_t operand = 0;
139  if (!args.empty() && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
140  // Attempt to parse a keyword.
141  StringRef keyword;
142  if (succeeded(parser.parseOptionalKeyword(&keyword))) {
143  operand = llvm::dwarf::getAttributeEncoding(keyword);
144  if (operand == 0) {
145  // The keyword is invalid.
146  return parser.emitError(parser.getCurrentLocation())
147  << "encountered unknown attribute encoding \"" << keyword
148  << "\"";
149  }
150  }
151  }
152 
153  // operand should be non-zero if a keyword was parsed. Otherwise, the
154  // operand MUST be an integer.
155  if (operand == 0) {
156  // Parse the next operand as an integer.
157  if (parser.parseInteger(operand)) {
158  return parser.emitError(parser.getCurrentLocation())
159  << "expected integer operand";
160  }
161  }
162 
163  args.push_back(operand);
164  return success();
165  };
166 
167  // Parse operands as a comma-separated list.
168  return parser.parseCommaSeparatedList(operandParser);
169 }
170 
171 void printExpressionArg(AsmPrinter &printer, uint64_t opcode,
172  ArrayRef<uint64_t> args) {
173  size_t i = 0;
174  llvm::interleaveComma(args, printer, [&](uint64_t operand) {
175  if (i > 0 && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
176  if (const StringRef keyword =
177  llvm::dwarf::AttributeEncodingString(operand);
178  !keyword.empty()) {
179  printer << keyword;
180  return;
181  }
182  }
183  // All operands are expected to be printed as integers.
184  printer << operand;
185  i++;
186  });
187 }
188 
189 //===----------------------------------------------------------------------===//
190 // DICompositeTypeAttr
191 //===----------------------------------------------------------------------===//
192 
193 DIRecursiveTypeAttrInterface
194 DICompositeTypeAttr::withRecId(DistinctAttr recId) {
195  return DICompositeTypeAttr::get(getContext(), getTag(), recId, getName(),
196  getFile(), getLine(), getScope(),
197  getBaseType(), getFlags(), getSizeInBits(),
198  getAlignInBits(), getElements());
199 }
200 
201 DIRecursiveTypeAttrInterface
202 DICompositeTypeAttr::getRecSelf(DistinctAttr recId) {
203  return DICompositeTypeAttr::get(recId.getContext(), 0, recId, {}, {}, 0, {},
204  {}, DIFlags(), 0, 0, {});
205 }
206 
207 //===----------------------------------------------------------------------===//
208 // TargetFeaturesAttr
209 //===----------------------------------------------------------------------===//
210 
211 TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
212  llvm::ArrayRef<StringRef> features) {
213  return Base::get(context,
214  llvm::map_to_vector(features, [&](StringRef feature) {
215  return StringAttr::get(context, feature);
216  }));
217 }
218 
219 TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
220  StringRef targetFeatures) {
221  SmallVector<StringRef> features;
222  targetFeatures.split(features, ',', /*MaxSplit=*/-1,
223  /*KeepEmpty=*/false);
224  return get(context, features);
225 }
226 
229  llvm::ArrayRef<StringAttr> features) {
230  for (StringAttr featureAttr : features) {
231  if (!featureAttr || featureAttr.empty())
232  return emitError() << "target features can not be null or empty";
233  auto feature = featureAttr.strref();
234  if (feature[0] != '+' && feature[0] != '-')
235  return emitError() << "target features must start with '+' or '-'";
236  if (feature.contains(','))
237  return emitError() << "target features can not contain ','";
238  }
239  return success();
240 }
241 
242 bool TargetFeaturesAttr::contains(StringAttr feature) const {
243  if (nullOrEmpty())
244  return false;
245  // Note: Using StringAttr does pointer comparisons.
246  return llvm::is_contained(getFeatures(), feature);
247 }
248 
249 bool TargetFeaturesAttr::contains(StringRef feature) const {
250  if (nullOrEmpty())
251  return false;
252  return llvm::is_contained(getFeatures(), feature);
253 }
254 
255 std::string TargetFeaturesAttr::getFeaturesString() const {
256  std::string featuresString;
257  llvm::raw_string_ostream ss(featuresString);
258  llvm::interleave(
259  getFeatures(), ss, [&](auto &feature) { ss << feature.strref(); }, ",");
260  return ss.str();
261 }
262 
263 TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
264  auto parentFunction = op->getParentOfType<FunctionOpInterface>();
265  if (!parentFunction)
266  return {};
267  return parentFunction.getOperation()->getAttrOfType<TargetFeaturesAttr>(
268  getAttributeName());
269 }
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:135
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:171
static bool contains(SMRange range, SMLoc loc)
Returns true if the given range contains the given source location.
Definition: MLIRServer.cpp:111
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.
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 SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
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:308
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:80
static bool classof(Attribute attr)
Definition: LLVMAttrs.cpp:58
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:71
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:89
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:98
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
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
Definition: LogicalResult.h:68
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
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:421
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26