MLIR  18.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/LLVMOpsEnums.cpp.inc"
39 #define GET_ATTRDEF_CLASSES
40 #include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc"
41 
42 //===----------------------------------------------------------------------===//
43 // LLVMDialect registration
44 //===----------------------------------------------------------------------===//
45 
46 void LLVMDialect::registerAttributes() {
47  addAttributes<
48 #define GET_ATTRDEF_LIST
49 #include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc"
50  >();
51 }
52 
53 //===----------------------------------------------------------------------===//
54 // DINodeAttr
55 //===----------------------------------------------------------------------===//
56 
58  return llvm::isa<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
59  DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
60  DILabelAttr, DILexicalBlockAttr, DILexicalBlockFileAttr,
61  DILocalVariableAttr, DIModuleAttr, DINamespaceAttr,
62  DINullTypeAttr, DISubprogramAttr, DISubrangeAttr,
63  DISubroutineTypeAttr>(attr);
64 }
65 
66 //===----------------------------------------------------------------------===//
67 // DIScopeAttr
68 //===----------------------------------------------------------------------===//
69 
71  return llvm::isa<DICompileUnitAttr, DICompositeTypeAttr, DIFileAttr,
72  DILocalScopeAttr, DIModuleAttr, DINamespaceAttr>(attr);
73 }
74 
75 //===----------------------------------------------------------------------===//
76 // DILocalScopeAttr
77 //===----------------------------------------------------------------------===//
78 
80  return llvm::isa<DILexicalBlockAttr, DILexicalBlockFileAttr,
81  DISubprogramAttr>(attr);
82 }
83 
84 //===----------------------------------------------------------------------===//
85 // DITypeAttr
86 //===----------------------------------------------------------------------===//
87 
89  return llvm::isa<DINullTypeAttr, DIBasicTypeAttr, DICompositeTypeAttr,
90  DIDerivedTypeAttr, DISubroutineTypeAttr>(attr);
91 }
92 
93 //===----------------------------------------------------------------------===//
94 // TBAANodeAttr
95 //===----------------------------------------------------------------------===//
96 
98  return llvm::isa<TBAATypeDescriptorAttr, TBAARootAttr>(attr);
99 }
100 
101 //===----------------------------------------------------------------------===//
102 // MemoryEffectsAttr
103 //===----------------------------------------------------------------------===//
104 
105 MemoryEffectsAttr MemoryEffectsAttr::get(MLIRContext *context,
106  ArrayRef<ModRefInfo> memInfoArgs) {
107  if (memInfoArgs.empty())
108  return MemoryEffectsAttr::get(context, ModRefInfo::ModRef,
109  ModRefInfo::ModRef, ModRefInfo::ModRef);
110  if (memInfoArgs.size() == 3)
111  return MemoryEffectsAttr::get(context, memInfoArgs[0], memInfoArgs[1],
112  memInfoArgs[2]);
113  return {};
114 }
115 
116 bool MemoryEffectsAttr::isReadWrite() {
117  if (this->getArgMem() != ModRefInfo::ModRef)
118  return false;
119  if (this->getInaccessibleMem() != ModRefInfo::ModRef)
120  return false;
121  if (this->getOther() != ModRefInfo::ModRef)
122  return false;
123  return true;
124 }
125 
126 //===----------------------------------------------------------------------===//
127 // DIExpression
128 //===----------------------------------------------------------------------===//
129 
130 DIExpressionAttr DIExpressionAttr::get(MLIRContext *context) {
131  return get(context, ArrayRef<DIExpressionElemAttr>({}));
132 }
133 
134 LogicalResult parseExpressionArg(AsmParser &parser, uint64_t opcode,
135  SmallVector<uint64_t> &args) {
136  auto operandParser = [&]() -> LogicalResult {
137  uint64_t operand = 0;
138  if (!args.empty() && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
139  // Attempt to parse a keyword.
140  StringRef keyword;
141  if (succeeded(parser.parseOptionalKeyword(&keyword))) {
142  operand = llvm::dwarf::getAttributeEncoding(keyword);
143  if (operand == 0) {
144  // The keyword is invalid.
145  return parser.emitError(parser.getCurrentLocation())
146  << "encountered unknown attribute encoding \"" << keyword
147  << "\"";
148  }
149  }
150  }
151 
152  // operand should be non-zero if a keyword was parsed. Otherwise, the
153  // operand MUST be an integer.
154  if (operand == 0) {
155  // Parse the next operand as an integer.
156  if (parser.parseInteger(operand)) {
157  return parser.emitError(parser.getCurrentLocation())
158  << "expected integer operand";
159  }
160  }
161 
162  args.push_back(operand);
163  return success();
164  };
165 
166  // Parse operands as a comma-separated list.
167  return parser.parseCommaSeparatedList(operandParser);
168 }
169 
170 void printExpressionArg(AsmPrinter &printer, uint64_t opcode,
171  ArrayRef<uint64_t> args) {
172  size_t i = 0;
173  llvm::interleaveComma(args, printer, [&](uint64_t operand) {
174  if (i > 0 && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
175  if (const StringRef keyword =
176  llvm::dwarf::AttributeEncodingString(operand);
177  !keyword.empty()) {
178  printer << keyword;
179  return;
180  }
181  }
182  // All operands are expected to be printed as integers.
183  printer << operand;
184  i++;
185  });
186 }
187 
188 //===----------------------------------------------------------------------===//
189 // TargetFeaturesAttr
190 //===----------------------------------------------------------------------===//
191 
192 TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
193  llvm::ArrayRef<StringRef> features) {
194  return Base::get(context,
195  llvm::map_to_vector(features, [&](StringRef feature) {
196  return StringAttr::get(context, feature);
197  }));
198 }
199 
200 TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
201  StringRef targetFeatures) {
202  SmallVector<StringRef> features;
203  targetFeatures.split(features, ',', /*MaxSplit=*/-1,
204  /*KeepEmpty=*/false);
205  return get(context, features);
206 }
207 
210  llvm::ArrayRef<StringAttr> features) {
211  for (StringAttr featureAttr : features) {
212  if (!featureAttr || featureAttr.empty())
213  return emitError() << "target features can not be null or empty";
214  auto feature = featureAttr.strref();
215  if (feature[0] != '+' && feature[0] != '-')
216  return emitError() << "target features must start with '+' or '-'";
217  if (feature.contains(','))
218  return emitError() << "target features can not contain ','";
219  }
220  return success();
221 }
222 
223 bool TargetFeaturesAttr::contains(StringAttr feature) const {
224  if (nullOrEmpty())
225  return false;
226  // Note: Using StringAttr does pointer comparisons.
227  return llvm::is_contained(getFeatures(), feature);
228 }
229 
230 bool TargetFeaturesAttr::contains(StringRef feature) const {
231  if (nullOrEmpty())
232  return false;
233  return llvm::is_contained(getFeatures(), feature);
234 }
235 
236 std::string TargetFeaturesAttr::getFeaturesString() const {
237  std::string featuresString;
238  llvm::raw_string_ostream ss(featuresString);
239  llvm::interleave(
240  getFeatures(), ss, [&](auto &feature) { ss << feature.strref(); }, ",");
241  return ss.str();
242 }
243 
244 TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
245  auto parentFunction = op->getParentOfType<FunctionOpInterface>();
246  if (!parentFunction)
247  return {};
248  return parentFunction.getOperation()->getAttrOfType<TargetFeaturesAttr>(
249  getAttributeName());
250 }
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:134
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:170
static bool contains(SMRange range, SMLoc loc)
Returns true if the given range contains the given source location.
Definition: MLIRServer.cpp:110
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
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:79
static bool classof(Attribute attr)
Definition: LLVMAttrs.cpp:57
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:70
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:88
static bool classof(Attribute attr)
Support LLVM type casting.
Definition: LLVMAttrs.cpp:97
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