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
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>
23
24using namespace mlir;
25using 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.
30static 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.
35static 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
47void 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
58bool DINodeAttr::classof(Attribute attr) {
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
71bool DIScopeAttr::classof(Attribute attr) {
72 return llvm::isa<DICompileUnitAttr, DICompositeTypeAttr, DIFileAttr,
73 DILocalScopeAttr, DIModuleAttr, DINamespaceAttr>(attr);
74}
75
76//===----------------------------------------------------------------------===//
77// DILocalScopeAttr
78//===----------------------------------------------------------------------===//
79
80bool DILocalScopeAttr::classof(Attribute attr) {
81 return llvm::isa<DILexicalBlockAttr, DILexicalBlockFileAttr,
82 DISubprogramAttr>(attr);
83}
84
85//===----------------------------------------------------------------------===//
86// DITypeAttr
87//===----------------------------------------------------------------------===//
88
89bool DITypeAttr::classof(Attribute attr) {
90 return llvm::isa<DINullTypeAttr, DIBasicTypeAttr, DICompositeTypeAttr,
91 DIDerivedTypeAttr, DISubroutineTypeAttr>(attr);
92}
93
94//===----------------------------------------------------------------------===//
95// TBAANodeAttr
96//===----------------------------------------------------------------------===//
97
98bool TBAANodeAttr::classof(Attribute attr) {
99 return llvm::isa<TBAATypeDescriptorAttr, TBAARootAttr>(attr);
100}
101
102//===----------------------------------------------------------------------===//
103// MemoryEffectsAttr
104//===----------------------------------------------------------------------===//
105
106MemoryEffectsAttr 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
117bool 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
131DIExpressionAttr DIExpressionAttr::get(MLIRContext *context) {
132 return get(context, ArrayRef<DIExpressionElemAttr>({}));
133}
134
135LogicalResult 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(result: parser.parseOptionalKeyword(keyword: &keyword))) {
143 operand = llvm::dwarf::getAttributeEncoding(EncodingString: keyword);
144 if (operand == 0) {
145 // The keyword is invalid.
146 return parser.emitError(loc: 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(result&: operand)) {
158 return parser.emitError(loc: parser.getCurrentLocation())
159 << "expected integer operand";
160 }
161 }
162
163 args.push_back(Elt: operand);
164 return success();
165 };
166
167 // Parse operands as a comma-separated list.
168 return parser.parseCommaSeparatedList(parseElementFn: operandParser);
169}
170
171void printExpressionArg(AsmPrinter &printer, uint64_t opcode,
172 ArrayRef<uint64_t> args) {
173 size_t i = 0;
174 llvm::interleaveComma(c: args, os&: printer, each_fn: [&](uint64_t operand) {
175 if (i > 0 && opcode == llvm::dwarf::DW_OP_LLVM_convert) {
176 if (const StringRef keyword =
177 llvm::dwarf::AttributeEncodingString(Encoding: 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
193DIRecursiveTypeAttrInterface
194DICompositeTypeAttr::withRecId(DistinctAttr recId) {
195 return DICompositeTypeAttr::get(getContext(), getTag(), recId, getName(),
196 getFile(), getLine(), getScope(),
197 getBaseType(), getFlags(), getSizeInBits(),
198 getAlignInBits(), getElements());
199}
200
201DIRecursiveTypeAttrInterface
202DICompositeTypeAttr::getRecSelf(DistinctAttr recId) {
203 return DICompositeTypeAttr::get(recId.getContext(), 0, recId, {}, {}, 0, {},
204 {}, DIFlags(), 0, 0, {});
205}
206
207//===----------------------------------------------------------------------===//
208// TargetFeaturesAttr
209//===----------------------------------------------------------------------===//
210
211TargetFeaturesAttr 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
219TargetFeaturesAttr 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
227LogicalResult
228TargetFeaturesAttr::verify(function_ref<InFlightDiagnostic()> emitError,
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
242bool 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
249bool TargetFeaturesAttr::contains(StringRef feature) const {
250 if (nullOrEmpty())
251 return false;
252 return llvm::is_contained(getFeatures(), feature);
253}
254
255std::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
263TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
264 auto parentFunction = op->getParentOfType<FunctionOpInterface>();
265 if (!parentFunction)
266 return {};
267 return parentFunction.getOperation()->getAttrOfType<TargetFeaturesAttr>(
268 getAttributeName());
269}
270

source code of mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp