[TableGen] Fix validateOperandClass for non Phyical Reg (#118146)
[llvm-project.git] / mlir / lib / Dialect / LLVMIR / IR / LLVMAttrs.cpp
blobee4e344674a67e5a5de17556491d661edd6e8db6
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.
11 //===----------------------------------------------------------------------===//
13 #include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
14 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
15 #include "mlir/IR/Builders.h"
16 #include "mlir/IR/DialectImplementation.h"
17 #include "mlir/Interfaces/FunctionInterfaces.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>
24 using namespace mlir;
25 using namespace mlir::LLVM;
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);
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);
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"
43 //===----------------------------------------------------------------------===//
44 // LLVMDialect registration
45 //===----------------------------------------------------------------------===//
47 void LLVMDialect::registerAttributes() {
48 addAttributes<
49 #define GET_ATTRDEF_LIST
50 #include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc"
51 >();
54 //===----------------------------------------------------------------------===//
55 // DINodeAttr
56 //===----------------------------------------------------------------------===//
58 bool DINodeAttr::classof(Attribute attr) {
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);
69 //===----------------------------------------------------------------------===//
70 // DIScopeAttr
71 //===----------------------------------------------------------------------===//
73 bool DIScopeAttr::classof(Attribute attr) {
74 return llvm::isa<DICommonBlockAttr, DICompileUnitAttr, DICompositeTypeAttr,
75 DIFileAttr, DILocalScopeAttr, DIModuleAttr, DINamespaceAttr>(
76 attr);
79 //===----------------------------------------------------------------------===//
80 // DILocalScopeAttr
81 //===----------------------------------------------------------------------===//
83 bool DILocalScopeAttr::classof(Attribute attr) {
84 return llvm::isa<DILexicalBlockAttr, DILexicalBlockFileAttr,
85 DISubprogramAttr>(attr);
88 //===----------------------------------------------------------------------===//
89 // DIVariableAttr
90 //===----------------------------------------------------------------------===//
92 bool DIVariableAttr::classof(Attribute attr) {
93 return llvm::isa<DILocalVariableAttr, DIGlobalVariableAttr>(attr);
96 //===----------------------------------------------------------------------===//
97 // DITypeAttr
98 //===----------------------------------------------------------------------===//
100 bool DITypeAttr::classof(Attribute attr) {
101 return llvm::isa<DINullTypeAttr, DIBasicTypeAttr, DICompositeTypeAttr,
102 DIDerivedTypeAttr, DIStringTypeAttr, DISubroutineTypeAttr>(
103 attr);
106 //===----------------------------------------------------------------------===//
107 // TBAANodeAttr
108 //===----------------------------------------------------------------------===//
110 bool TBAANodeAttr::classof(Attribute attr) {
111 return llvm::isa<TBAATypeDescriptorAttr, TBAARootAttr>(attr);
114 //===----------------------------------------------------------------------===//
115 // MemoryEffectsAttr
116 //===----------------------------------------------------------------------===//
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 {};
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;
139 //===----------------------------------------------------------------------===//
140 // DIExpression
141 //===----------------------------------------------------------------------===//
143 DIExpressionAttr DIExpressionAttr::get(MLIRContext *context) {
144 return get(context, ArrayRef<DIExpressionElemAttr>({}));
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 << "\"";
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";
175 args.push_back(operand);
176 return success();
179 // Parse operands as a comma-separated list.
180 return parser.parseCommaSeparatedList(operandParser);
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;
195 // All operands are expected to be printed as integers.
196 printer << operand;
197 i++;
201 //===----------------------------------------------------------------------===//
202 // DICompositeTypeAttr
203 //===----------------------------------------------------------------------===//
205 DIRecursiveTypeAttrInterface
206 DICompositeTypeAttr::withRecId(DistinctAttr recId) {
207 return DICompositeTypeAttr::get(
208 getContext(), recId, getIsRecSelf(), getTag(), getName(), getFile(),
209 getLine(), getScope(), getBaseType(), getFlags(), getSizeInBits(),
210 getAlignInBits(), getElements(), getDataLocation(), getRank(),
211 getAllocated(), getAssociated());
214 DIRecursiveTypeAttrInterface
215 DICompositeTypeAttr::getRecSelf(DistinctAttr recId) {
216 return DICompositeTypeAttr::get(recId.getContext(), recId, /*isRecSelf=*/true,
217 0, {}, {}, 0, {}, {}, DIFlags(), 0, 0, {}, {},
218 {}, {}, {});
221 //===----------------------------------------------------------------------===//
222 // DISubprogramAttr
223 //===----------------------------------------------------------------------===//
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());
233 DIRecursiveTypeAttrInterface DISubprogramAttr::getRecSelf(DistinctAttr recId) {
234 return DISubprogramAttr::get(recId.getContext(), recId, /*isRecSelf=*/true,
235 {}, {}, {}, {}, {}, 0, 0, {}, {}, {}, {}, {});
238 //===----------------------------------------------------------------------===//
239 // ConstantRangeAttr
240 //===----------------------------------------------------------------------===//
242 Attribute ConstantRangeAttr::parse(AsmParser &parser, Type odsType) {
243 llvm::SMLoc loc = parser.getCurrentLocation();
244 IntegerType widthType;
245 if (parser.parseLess() || parser.parseType(widthType) ||
246 parser.parseComma()) {
247 return Attribute{};
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);
264 void ConstantRangeAttr::print(AsmPrinter &printer) const {
265 printer << "<i" << getLower().getBitWidth() << ", " << getLower() << ", "
266 << getUpper() << ">";
269 LogicalResult
270 ConstantRangeAttr::verify(llvm::function_ref<InFlightDiagnostic()> emitError,
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();
279 //===----------------------------------------------------------------------===//
280 // TargetFeaturesAttr
281 //===----------------------------------------------------------------------===//
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 }));
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);
299 LogicalResult
300 TargetFeaturesAttr::verify(function_ref<InFlightDiagnostic()> emitError,
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 ','";
311 return success();
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);
321 bool TargetFeaturesAttr::contains(StringRef feature) const {
322 if (nullOrEmpty())
323 return false;
324 return llvm::is_contained(getFeatures(), feature);
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;
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());