1 | //===- SPIRVAttributes.cpp - SPIR-V attribute definitions -----------------===// |
---|---|
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 | #include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.h" |
10 | #include "mlir/Dialect/SPIRV/IR/SPIRVDialect.h" |
11 | #include "mlir/Dialect/SPIRV/IR/SPIRVTypes.h" |
12 | #include "mlir/IR/Builders.h" |
13 | #include "mlir/IR/DialectImplementation.h" |
14 | #include "llvm/ADT/TypeSwitch.h" |
15 | #include "llvm/Support/InterleavedRange.h" |
16 | |
17 | using namespace mlir; |
18 | using namespace mlir::spirv; |
19 | |
20 | //===----------------------------------------------------------------------===// |
21 | // TableGen'erated attribute utility functions |
22 | //===----------------------------------------------------------------------===// |
23 | |
24 | namespace mlir { |
25 | namespace spirv { |
26 | #include "mlir/Dialect/SPIRV/IR/SPIRVAttrUtils.inc" |
27 | } // namespace spirv |
28 | |
29 | //===----------------------------------------------------------------------===// |
30 | // Attribute storage classes |
31 | //===----------------------------------------------------------------------===// |
32 | |
33 | namespace spirv { |
34 | namespace detail { |
35 | |
36 | struct InterfaceVarABIAttributeStorage : public AttributeStorage { |
37 | using KeyTy = std::tuple<Attribute, Attribute, Attribute>; |
38 | |
39 | InterfaceVarABIAttributeStorage(Attribute descriptorSet, Attribute binding, |
40 | Attribute storageClass) |
41 | : descriptorSet(descriptorSet), binding(binding), |
42 | storageClass(storageClass) {} |
43 | |
44 | bool operator==(const KeyTy &key) const { |
45 | return std::get<0>(key) == descriptorSet && std::get<1>(key) == binding && |
46 | std::get<2>(key) == storageClass; |
47 | } |
48 | |
49 | static InterfaceVarABIAttributeStorage * |
50 | construct(AttributeStorageAllocator &allocator, const KeyTy &key) { |
51 | return new (allocator.allocate<InterfaceVarABIAttributeStorage>()) |
52 | InterfaceVarABIAttributeStorage(std::get<0>(key), std::get<1>(key), |
53 | std::get<2>(key)); |
54 | } |
55 | |
56 | Attribute descriptorSet; |
57 | Attribute binding; |
58 | Attribute storageClass; |
59 | }; |
60 | |
61 | struct VerCapExtAttributeStorage : public AttributeStorage { |
62 | using KeyTy = std::tuple<Attribute, Attribute, Attribute>; |
63 | |
64 | VerCapExtAttributeStorage(Attribute version, Attribute capabilities, |
65 | Attribute extensions) |
66 | : version(version), capabilities(capabilities), extensions(extensions) {} |
67 | |
68 | bool operator==(const KeyTy &key) const { |
69 | return std::get<0>(key) == version && std::get<1>(key) == capabilities && |
70 | std::get<2>(key) == extensions; |
71 | } |
72 | |
73 | static VerCapExtAttributeStorage * |
74 | construct(AttributeStorageAllocator &allocator, const KeyTy &key) { |
75 | return new (allocator.allocate<VerCapExtAttributeStorage>()) |
76 | VerCapExtAttributeStorage(std::get<0>(key), std::get<1>(key), |
77 | std::get<2>(key)); |
78 | } |
79 | |
80 | Attribute version; |
81 | Attribute capabilities; |
82 | Attribute extensions; |
83 | }; |
84 | |
85 | struct TargetEnvAttributeStorage : public AttributeStorage { |
86 | using KeyTy = |
87 | std::tuple<Attribute, ClientAPI, Vendor, DeviceType, uint32_t, Attribute>; |
88 | |
89 | TargetEnvAttributeStorage(Attribute triple, ClientAPI clientAPI, |
90 | Vendor vendorID, DeviceType deviceType, |
91 | uint32_t deviceID, Attribute limits) |
92 | : triple(triple), limits(limits), clientAPI(clientAPI), |
93 | vendorID(vendorID), deviceType(deviceType), deviceID(deviceID) {} |
94 | |
95 | bool operator==(const KeyTy &key) const { |
96 | return key == std::make_tuple(triple, clientAPI, vendorID, deviceType, |
97 | deviceID, limits); |
98 | } |
99 | |
100 | static TargetEnvAttributeStorage * |
101 | construct(AttributeStorageAllocator &allocator, const KeyTy &key) { |
102 | return new (allocator.allocate<TargetEnvAttributeStorage>()) |
103 | TargetEnvAttributeStorage(std::get<0>(key), std::get<1>(key), |
104 | std::get<2>(key), std::get<3>(key), |
105 | std::get<4>(key), std::get<5>(key)); |
106 | } |
107 | |
108 | Attribute triple; |
109 | Attribute limits; |
110 | ClientAPI clientAPI; |
111 | Vendor vendorID; |
112 | DeviceType deviceType; |
113 | uint32_t deviceID; |
114 | }; |
115 | } // namespace detail |
116 | } // namespace spirv |
117 | } // namespace mlir |
118 | |
119 | //===----------------------------------------------------------------------===// |
120 | // InterfaceVarABIAttr |
121 | //===----------------------------------------------------------------------===// |
122 | |
123 | spirv::InterfaceVarABIAttr |
124 | spirv::InterfaceVarABIAttr::get(uint32_t descriptorSet, uint32_t binding, |
125 | std::optional<spirv::StorageClass> storageClass, |
126 | MLIRContext *context) { |
127 | Builder b(context); |
128 | auto descriptorSetAttr = b.getI32IntegerAttr(descriptorSet); |
129 | auto bindingAttr = b.getI32IntegerAttr(binding); |
130 | auto storageClassAttr = |
131 | storageClass ? b.getI32IntegerAttr(static_cast<uint32_t>(*storageClass)) |
132 | : IntegerAttr(); |
133 | return get(descriptorSetAttr, bindingAttr, storageClassAttr); |
134 | } |
135 | |
136 | spirv::InterfaceVarABIAttr |
137 | spirv::InterfaceVarABIAttr::get(IntegerAttr descriptorSet, IntegerAttr binding, |
138 | IntegerAttr storageClass) { |
139 | assert(descriptorSet && binding); |
140 | MLIRContext *context = descriptorSet.getContext(); |
141 | return Base::get(context, descriptorSet, binding, storageClass); |
142 | } |
143 | |
144 | StringRef spirv::InterfaceVarABIAttr::getKindName() { |
145 | return "interface_var_abi"; |
146 | } |
147 | |
148 | uint32_t spirv::InterfaceVarABIAttr::getBinding() { |
149 | return llvm::cast<IntegerAttr>(getImpl()->binding).getInt(); |
150 | } |
151 | |
152 | uint32_t spirv::InterfaceVarABIAttr::getDescriptorSet() { |
153 | return llvm::cast<IntegerAttr>(getImpl()->descriptorSet).getInt(); |
154 | } |
155 | |
156 | std::optional<spirv::StorageClass> |
157 | spirv::InterfaceVarABIAttr::getStorageClass() { |
158 | if (getImpl()->storageClass) |
159 | return static_cast<spirv::StorageClass>( |
160 | llvm::cast<IntegerAttr>(getImpl()->storageClass) |
161 | .getValue() |
162 | .getZExtValue()); |
163 | return std::nullopt; |
164 | } |
165 | |
166 | LogicalResult spirv::InterfaceVarABIAttr::verifyInvariants( |
167 | function_ref<InFlightDiagnostic()> emitError, IntegerAttr descriptorSet, |
168 | IntegerAttr binding, IntegerAttr storageClass) { |
169 | if (!descriptorSet.getType().isSignlessInteger(32)) |
170 | return emitError() << "expected 32-bit integer for descriptor set"; |
171 | |
172 | if (!binding.getType().isSignlessInteger(32)) |
173 | return emitError() << "expected 32-bit integer for binding"; |
174 | |
175 | if (storageClass) { |
176 | if (auto storageClassAttr = llvm::cast<IntegerAttr>(storageClass)) { |
177 | auto storageClassValue = |
178 | spirv::symbolizeStorageClass(storageClassAttr.getInt()); |
179 | if (!storageClassValue) |
180 | return emitError() << "unknown storage class"; |
181 | } else { |
182 | return emitError() << "expected valid storage class"; |
183 | } |
184 | } |
185 | |
186 | return success(); |
187 | } |
188 | |
189 | //===----------------------------------------------------------------------===// |
190 | // VerCapExtAttr |
191 | //===----------------------------------------------------------------------===// |
192 | |
193 | spirv::VerCapExtAttr spirv::VerCapExtAttr::get( |
194 | spirv::Version version, ArrayRef<spirv::Capability> capabilities, |
195 | ArrayRef<spirv::Extension> extensions, MLIRContext *context) { |
196 | Builder b(context); |
197 | |
198 | auto versionAttr = b.getI32IntegerAttr(static_cast<uint32_t>(version)); |
199 | |
200 | SmallVector<Attribute, 4> capAttrs; |
201 | capAttrs.reserve(N: capabilities.size()); |
202 | for (spirv::Capability cap : capabilities) |
203 | capAttrs.push_back(b.getI32IntegerAttr(static_cast<uint32_t>(cap))); |
204 | |
205 | SmallVector<Attribute, 4> extAttrs; |
206 | extAttrs.reserve(N: extensions.size()); |
207 | for (spirv::Extension ext : extensions) |
208 | extAttrs.push_back(b.getStringAttr(spirv::stringifyExtension(ext))); |
209 | |
210 | return get(version: versionAttr, capabilities: b.getArrayAttr(capAttrs), extensions: b.getArrayAttr(extAttrs)); |
211 | } |
212 | |
213 | spirv::VerCapExtAttr spirv::VerCapExtAttr::get(IntegerAttr version, |
214 | ArrayAttr capabilities, |
215 | ArrayAttr extensions) { |
216 | assert(version && capabilities && extensions); |
217 | MLIRContext *context = version.getContext(); |
218 | return Base::get(context, version, capabilities, extensions); |
219 | } |
220 | |
221 | StringRef spirv::VerCapExtAttr::getKindName() { return "vce"; } |
222 | |
223 | spirv::Version spirv::VerCapExtAttr::getVersion() { |
224 | return static_cast<spirv::Version>( |
225 | llvm::cast<IntegerAttr>(getImpl()->version).getValue().getZExtValue()); |
226 | } |
227 | |
228 | spirv::VerCapExtAttr::ext_iterator::ext_iterator(ArrayAttr::iterator it) |
229 | : llvm::mapped_iterator<ArrayAttr::iterator, |
230 | spirv::Extension (*)(Attribute)>( |
231 | it, [](Attribute attr) { |
232 | return *symbolizeExtension(llvm::cast<StringAttr>(attr).getValue()); |
233 | }) {} |
234 | |
235 | spirv::VerCapExtAttr::ext_range spirv::VerCapExtAttr::getExtensions() { |
236 | auto range = getExtensionsAttr().getValue(); |
237 | return {ext_iterator(range.begin()), ext_iterator(range.end())}; |
238 | } |
239 | |
240 | ArrayAttr spirv::VerCapExtAttr::getExtensionsAttr() { |
241 | return llvm::cast<ArrayAttr>(getImpl()->extensions); |
242 | } |
243 | |
244 | spirv::VerCapExtAttr::cap_iterator::cap_iterator(ArrayAttr::iterator it) |
245 | : llvm::mapped_iterator<ArrayAttr::iterator, |
246 | spirv::Capability (*)(Attribute)>( |
247 | it, [](Attribute attr) { |
248 | return *symbolizeCapability( |
249 | llvm::cast<IntegerAttr>(attr).getValue().getZExtValue()); |
250 | }) {} |
251 | |
252 | spirv::VerCapExtAttr::cap_range spirv::VerCapExtAttr::getCapabilities() { |
253 | auto range = getCapabilitiesAttr().getValue(); |
254 | return {cap_iterator(range.begin()), cap_iterator(range.end())}; |
255 | } |
256 | |
257 | ArrayAttr spirv::VerCapExtAttr::getCapabilitiesAttr() { |
258 | return llvm::cast<ArrayAttr>(getImpl()->capabilities); |
259 | } |
260 | |
261 | LogicalResult spirv::VerCapExtAttr::verifyInvariants( |
262 | function_ref<InFlightDiagnostic()> emitError, IntegerAttr version, |
263 | ArrayAttr capabilities, ArrayAttr extensions) { |
264 | if (!version.getType().isSignlessInteger(32)) |
265 | return emitError() << "expected 32-bit integer for version"; |
266 | |
267 | if (!llvm::all_of(capabilities.getValue(), [](Attribute attr) { |
268 | if (auto intAttr = llvm::dyn_cast<IntegerAttr>(attr)) |
269 | if (spirv::symbolizeCapability(intAttr.getValue().getZExtValue())) |
270 | return true; |
271 | return false; |
272 | })) |
273 | return emitError() << "unknown capability in capability list"; |
274 | |
275 | if (!llvm::all_of(extensions.getValue(), [](Attribute attr) { |
276 | if (auto strAttr = llvm::dyn_cast<StringAttr>(attr)) |
277 | if (spirv::symbolizeExtension(strAttr.getValue())) |
278 | return true; |
279 | return false; |
280 | })) |
281 | return emitError() << "unknown extension in extension list"; |
282 | |
283 | return success(); |
284 | } |
285 | |
286 | //===----------------------------------------------------------------------===// |
287 | // TargetEnvAttr |
288 | //===----------------------------------------------------------------------===// |
289 | |
290 | spirv::TargetEnvAttr spirv::TargetEnvAttr::get( |
291 | spirv::VerCapExtAttr triple, ResourceLimitsAttr limits, ClientAPI clientAPI, |
292 | Vendor vendorID, DeviceType deviceType, uint32_t deviceID) { |
293 | assert(triple && limits && "expected valid triple and limits"); |
294 | MLIRContext *context = triple.getContext(); |
295 | return Base::get(context, triple, clientAPI, vendorID, deviceType, deviceID, |
296 | limits); |
297 | } |
298 | |
299 | StringRef spirv::TargetEnvAttr::getKindName() { return "target_env"; } |
300 | |
301 | spirv::VerCapExtAttr spirv::TargetEnvAttr::getTripleAttr() const { |
302 | return llvm::cast<spirv::VerCapExtAttr>(getImpl()->triple); |
303 | } |
304 | |
305 | spirv::Version spirv::TargetEnvAttr::getVersion() const { |
306 | return getTripleAttr().getVersion(); |
307 | } |
308 | |
309 | spirv::VerCapExtAttr::ext_range spirv::TargetEnvAttr::getExtensions() { |
310 | return getTripleAttr().getExtensions(); |
311 | } |
312 | |
313 | ArrayAttr spirv::TargetEnvAttr::getExtensionsAttr() { |
314 | return getTripleAttr().getExtensionsAttr(); |
315 | } |
316 | |
317 | spirv::VerCapExtAttr::cap_range spirv::TargetEnvAttr::getCapabilities() { |
318 | return getTripleAttr().getCapabilities(); |
319 | } |
320 | |
321 | ArrayAttr spirv::TargetEnvAttr::getCapabilitiesAttr() { |
322 | return getTripleAttr().getCapabilitiesAttr(); |
323 | } |
324 | |
325 | spirv::ClientAPI spirv::TargetEnvAttr::getClientAPI() const { |
326 | return getImpl()->clientAPI; |
327 | } |
328 | |
329 | spirv::Vendor spirv::TargetEnvAttr::getVendorID() const { |
330 | return getImpl()->vendorID; |
331 | } |
332 | |
333 | spirv::DeviceType spirv::TargetEnvAttr::getDeviceType() const { |
334 | return getImpl()->deviceType; |
335 | } |
336 | |
337 | uint32_t spirv::TargetEnvAttr::getDeviceID() const { |
338 | return getImpl()->deviceID; |
339 | } |
340 | |
341 | spirv::ResourceLimitsAttr spirv::TargetEnvAttr::getResourceLimits() const { |
342 | return llvm::cast<spirv::ResourceLimitsAttr>(getImpl()->limits); |
343 | } |
344 | |
345 | //===----------------------------------------------------------------------===// |
346 | // ODS Generated Attributes |
347 | //===----------------------------------------------------------------------===// |
348 | |
349 | #define GET_ATTRDEF_CLASSES |
350 | #include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.cpp.inc" |
351 | |
352 | //===----------------------------------------------------------------------===// |
353 | // Attribute Parsing |
354 | //===----------------------------------------------------------------------===// |
355 | |
356 | /// Parses a comma-separated list of keywords, invokes `processKeyword` on each |
357 | /// of the parsed keyword, and returns failure if any error occurs. |
358 | static ParseResult |
359 | parseKeywordList(DialectAsmParser &parser, |
360 | function_ref<LogicalResult(SMLoc, StringRef)> processKeyword) { |
361 | if (parser.parseLSquare()) |
362 | return failure(); |
363 | |
364 | // Special case for empty list. |
365 | if (succeeded(Result: parser.parseOptionalRSquare())) |
366 | return success(); |
367 | |
368 | // Keep parsing the keyword and an optional comma following it. If the comma |
369 | // is successfully parsed, then we have more keywords to parse. |
370 | if (failed(parser.parseCommaSeparatedList([&]() { |
371 | auto loc = parser.getCurrentLocation(); |
372 | StringRef keyword; |
373 | if (parser.parseKeyword(keyword: &keyword) || |
374 | failed(processKeyword(loc, keyword))) |
375 | return failure(); |
376 | return success(); |
377 | }))) |
378 | return failure(); |
379 | return parser.parseRSquare(); |
380 | } |
381 | |
382 | /// Parses a spirv::InterfaceVarABIAttr. |
383 | static Attribute parseInterfaceVarABIAttr(DialectAsmParser &parser) { |
384 | if (parser.parseLess()) |
385 | return {}; |
386 | |
387 | Builder &builder = parser.getBuilder(); |
388 | |
389 | if (parser.parseLParen()) |
390 | return {}; |
391 | |
392 | IntegerAttr descriptorSetAttr; |
393 | { |
394 | auto loc = parser.getCurrentLocation(); |
395 | uint32_t descriptorSet = 0; |
396 | auto descriptorSetParseResult = parser.parseOptionalInteger(result&: descriptorSet); |
397 | |
398 | if (!descriptorSetParseResult.has_value() || |
399 | failed(Result: *descriptorSetParseResult)) { |
400 | parser.emitError(loc, message: "missing descriptor set"); |
401 | return {}; |
402 | } |
403 | descriptorSetAttr = builder.getI32IntegerAttr(descriptorSet); |
404 | } |
405 | |
406 | if (parser.parseComma()) |
407 | return {}; |
408 | |
409 | IntegerAttr bindingAttr; |
410 | { |
411 | auto loc = parser.getCurrentLocation(); |
412 | uint32_t binding = 0; |
413 | auto bindingParseResult = parser.parseOptionalInteger(result&: binding); |
414 | |
415 | if (!bindingParseResult.has_value() || failed(Result: *bindingParseResult)) { |
416 | parser.emitError(loc, message: "missing binding"); |
417 | return {}; |
418 | } |
419 | bindingAttr = builder.getI32IntegerAttr(binding); |
420 | } |
421 | |
422 | if (parser.parseRParen()) |
423 | return {}; |
424 | |
425 | IntegerAttr storageClassAttr; |
426 | { |
427 | if (succeeded(Result: parser.parseOptionalComma())) { |
428 | auto loc = parser.getCurrentLocation(); |
429 | StringRef storageClass; |
430 | if (parser.parseKeyword(keyword: &storageClass)) |
431 | return {}; |
432 | |
433 | if (auto storageClassSymbol = |
434 | spirv::symbolizeStorageClass(storageClass)) { |
435 | storageClassAttr = builder.getI32IntegerAttr( |
436 | static_cast<uint32_t>(*storageClassSymbol)); |
437 | } else { |
438 | parser.emitError(loc, message: "unknown storage class: ") << storageClass; |
439 | return {}; |
440 | } |
441 | } |
442 | } |
443 | |
444 | if (parser.parseGreater()) |
445 | return {}; |
446 | |
447 | return spirv::InterfaceVarABIAttr::get(descriptorSetAttr, bindingAttr, |
448 | storageClassAttr); |
449 | } |
450 | |
451 | static Attribute parseVerCapExtAttr(DialectAsmParser &parser) { |
452 | if (parser.parseLess()) |
453 | return {}; |
454 | |
455 | Builder &builder = parser.getBuilder(); |
456 | |
457 | IntegerAttr versionAttr; |
458 | { |
459 | auto loc = parser.getCurrentLocation(); |
460 | StringRef version; |
461 | if (parser.parseKeyword(keyword: &version) || parser.parseComma()) |
462 | return {}; |
463 | |
464 | if (auto versionSymbol = spirv::symbolizeVersion(version)) { |
465 | versionAttr = |
466 | builder.getI32IntegerAttr(static_cast<uint32_t>(*versionSymbol)); |
467 | } else { |
468 | parser.emitError(loc, message: "unknown version: ") << version; |
469 | return {}; |
470 | } |
471 | } |
472 | |
473 | ArrayAttr capabilitiesAttr; |
474 | { |
475 | SmallVector<Attribute, 4> capabilities; |
476 | SMLoc errorloc; |
477 | StringRef errorKeyword; |
478 | |
479 | auto processCapability = [&](SMLoc loc, StringRef capability) { |
480 | if (auto capSymbol = spirv::symbolizeCapability(capability)) { |
481 | capabilities.push_back( |
482 | builder.getI32IntegerAttr(static_cast<uint32_t>(*capSymbol))); |
483 | return success(); |
484 | } |
485 | return errorloc = loc, errorKeyword = capability, failure(); |
486 | }; |
487 | if (parseKeywordList(parser, processCapability) || parser.parseComma()) { |
488 | if (!errorKeyword.empty()) |
489 | parser.emitError(loc: errorloc, message: "unknown capability: ") << errorKeyword; |
490 | return {}; |
491 | } |
492 | |
493 | capabilitiesAttr = builder.getArrayAttr(capabilities); |
494 | } |
495 | |
496 | ArrayAttr extensionsAttr; |
497 | { |
498 | SmallVector<Attribute, 1> extensions; |
499 | SMLoc errorloc; |
500 | StringRef errorKeyword; |
501 | |
502 | auto processExtension = [&](SMLoc loc, StringRef extension) { |
503 | if (spirv::symbolizeExtension(extension)) { |
504 | extensions.push_back(builder.getStringAttr(extension)); |
505 | return success(); |
506 | } |
507 | return errorloc = loc, errorKeyword = extension, failure(); |
508 | }; |
509 | if (parseKeywordList(parser, processExtension)) { |
510 | if (!errorKeyword.empty()) |
511 | parser.emitError(loc: errorloc, message: "unknown extension: ") << errorKeyword; |
512 | return {}; |
513 | } |
514 | |
515 | extensionsAttr = builder.getArrayAttr(extensions); |
516 | } |
517 | |
518 | if (parser.parseGreater()) |
519 | return {}; |
520 | |
521 | return spirv::VerCapExtAttr::get(version: versionAttr, capabilities: capabilitiesAttr, |
522 | extensions: extensionsAttr); |
523 | } |
524 | |
525 | /// Parses a spirv::TargetEnvAttr. |
526 | static Attribute parseTargetEnvAttr(DialectAsmParser &parser) { |
527 | if (parser.parseLess()) |
528 | return {}; |
529 | |
530 | spirv::VerCapExtAttr tripleAttr; |
531 | if (parser.parseAttribute(result&: tripleAttr) || parser.parseComma()) |
532 | return {}; |
533 | |
534 | auto clientAPI = spirv::ClientAPI::Unknown; |
535 | if (succeeded(Result: parser.parseOptionalKeyword(keyword: "api"))) { |
536 | if (parser.parseEqual()) |
537 | return {}; |
538 | auto loc = parser.getCurrentLocation(); |
539 | StringRef apiStr; |
540 | if (parser.parseKeyword(keyword: &apiStr)) |
541 | return {}; |
542 | if (auto apiSymbol = spirv::symbolizeClientAPI(apiStr)) |
543 | clientAPI = *apiSymbol; |
544 | else |
545 | parser.emitError(loc, message: "unknown client API: ") << apiStr; |
546 | if (parser.parseComma()) |
547 | return {}; |
548 | } |
549 | |
550 | // Parse [vendor[:device-type[:device-id]]] |
551 | Vendor vendorID = Vendor::Unknown; |
552 | DeviceType deviceType = DeviceType::Unknown; |
553 | uint32_t deviceID = spirv::TargetEnvAttr::kUnknownDeviceID; |
554 | { |
555 | auto loc = parser.getCurrentLocation(); |
556 | StringRef vendorStr; |
557 | if (succeeded(Result: parser.parseOptionalKeyword(keyword: &vendorStr))) { |
558 | if (auto vendorSymbol = spirv::symbolizeVendor(vendorStr)) |
559 | vendorID = *vendorSymbol; |
560 | else |
561 | parser.emitError(loc, message: "unknown vendor: ") << vendorStr; |
562 | |
563 | if (succeeded(Result: parser.parseOptionalColon())) { |
564 | loc = parser.getCurrentLocation(); |
565 | StringRef deviceTypeStr; |
566 | if (parser.parseKeyword(keyword: &deviceTypeStr)) |
567 | return {}; |
568 | if (auto deviceTypeSymbol = spirv::symbolizeDeviceType(deviceTypeStr)) |
569 | deviceType = *deviceTypeSymbol; |
570 | else |
571 | parser.emitError(loc, message: "unknown device type: ") << deviceTypeStr; |
572 | |
573 | if (succeeded(Result: parser.parseOptionalColon())) { |
574 | loc = parser.getCurrentLocation(); |
575 | if (parser.parseInteger(result&: deviceID)) |
576 | return {}; |
577 | } |
578 | } |
579 | if (parser.parseComma()) |
580 | return {}; |
581 | } |
582 | } |
583 | |
584 | ResourceLimitsAttr limitsAttr; |
585 | if (parser.parseAttribute(limitsAttr) || parser.parseGreater()) |
586 | return {}; |
587 | |
588 | return spirv::TargetEnvAttr::get(tripleAttr, limitsAttr, clientAPI, vendorID, |
589 | deviceType, deviceID); |
590 | } |
591 | |
592 | Attribute SPIRVDialect::parseAttribute(DialectAsmParser &parser, |
593 | Type type) const { |
594 | // SPIR-V attributes are dictionaries so they do not have type. |
595 | if (type) { |
596 | parser.emitError(parser.getNameLoc(), "unexpected type"); |
597 | return {}; |
598 | } |
599 | |
600 | // Parse the kind keyword first. |
601 | StringRef attrKind; |
602 | Attribute attr; |
603 | OptionalParseResult result = |
604 | generatedAttributeParser(parser, &attrKind, type, attr); |
605 | if (result.has_value()) |
606 | return attr; |
607 | |
608 | if (attrKind == spirv::TargetEnvAttr::getKindName()) |
609 | return parseTargetEnvAttr(parser); |
610 | if (attrKind == spirv::VerCapExtAttr::getKindName()) |
611 | return parseVerCapExtAttr(parser); |
612 | if (attrKind == spirv::InterfaceVarABIAttr::getKindName()) |
613 | return parseInterfaceVarABIAttr(parser); |
614 | |
615 | parser.emitError(parser.getNameLoc(), "unknown SPIR-V attribute kind: ") |
616 | << attrKind; |
617 | return {}; |
618 | } |
619 | |
620 | //===----------------------------------------------------------------------===// |
621 | // Attribute Printing |
622 | //===----------------------------------------------------------------------===// |
623 | |
624 | static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer) { |
625 | printer << spirv::VerCapExtAttr::getKindName() << "<" |
626 | << spirv::stringifyVersion(triple.getVersion()) << ", " |
627 | << llvm::interleaved_array(llvm::map_range( |
628 | triple.getCapabilities(), spirv::stringifyCapability)) |
629 | << ", " |
630 | << llvm::interleaved_array( |
631 | triple.getExtensionsAttr().getAsValueRange<StringAttr>()) |
632 | << ">"; |
633 | } |
634 | |
635 | static void print(spirv::TargetEnvAttr targetEnv, DialectAsmPrinter &printer) { |
636 | printer << spirv::TargetEnvAttr::getKindName() << "<#spirv."; |
637 | print(triple: targetEnv.getTripleAttr(), printer); |
638 | auto clientAPI = targetEnv.getClientAPI(); |
639 | if (clientAPI != spirv::ClientAPI::Unknown) |
640 | printer << ", api="<< clientAPI; |
641 | spirv::Vendor vendorID = targetEnv.getVendorID(); |
642 | spirv::DeviceType deviceType = targetEnv.getDeviceType(); |
643 | uint32_t deviceID = targetEnv.getDeviceID(); |
644 | if (vendorID != spirv::Vendor::Unknown) { |
645 | printer << ", "<< spirv::stringifyVendor(vendorID); |
646 | if (deviceType != spirv::DeviceType::Unknown) { |
647 | printer << ":"<< spirv::stringifyDeviceType(deviceType); |
648 | if (deviceID != spirv::TargetEnvAttr::kUnknownDeviceID) |
649 | printer << ":"<< deviceID; |
650 | } |
651 | } |
652 | printer << ", "<< targetEnv.getResourceLimits() << ">"; |
653 | } |
654 | |
655 | static void print(spirv::InterfaceVarABIAttr interfaceVarABIAttr, |
656 | DialectAsmPrinter &printer) { |
657 | printer << spirv::InterfaceVarABIAttr::getKindName() << "<(" |
658 | << interfaceVarABIAttr.getDescriptorSet() << ", " |
659 | << interfaceVarABIAttr.getBinding() << ")"; |
660 | auto storageClass = interfaceVarABIAttr.getStorageClass(); |
661 | if (storageClass) |
662 | printer << ", "<< spirv::stringifyStorageClass(*storageClass); |
663 | printer << ">"; |
664 | } |
665 | |
666 | void SPIRVDialect::printAttribute(Attribute attr, |
667 | DialectAsmPrinter &printer) const { |
668 | if (succeeded(generatedAttributePrinter(attr, printer))) |
669 | return; |
670 | |
671 | if (auto targetEnv = llvm::dyn_cast<TargetEnvAttr>(attr)) |
672 | print(targetEnv, printer); |
673 | else if (auto vceAttr = llvm::dyn_cast<VerCapExtAttr>(attr)) |
674 | print(vceAttr, printer); |
675 | else if (auto interfaceVarABIAttr = llvm::dyn_cast<InterfaceVarABIAttr>(attr)) |
676 | print(interfaceVarABIAttr, printer); |
677 | else |
678 | llvm_unreachable("unhandled SPIR-V attribute kind"); |
679 | } |
680 | |
681 | //===----------------------------------------------------------------------===// |
682 | // SPIR-V Dialect |
683 | //===----------------------------------------------------------------------===// |
684 | |
685 | void spirv::SPIRVDialect::registerAttributes() { |
686 | addAttributes<InterfaceVarABIAttr, TargetEnvAttr, VerCapExtAttr>(); |
687 | addAttributes< |
688 | #define GET_ATTRDEF_LIST |
689 | #include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.cpp.inc" |
690 | >(); |
691 | } |
692 |
Definitions
- InterfaceVarABIAttributeStorage
- InterfaceVarABIAttributeStorage
- operator==
- construct
- VerCapExtAttributeStorage
- VerCapExtAttributeStorage
- operator==
- construct
- TargetEnvAttributeStorage
- TargetEnvAttributeStorage
- operator==
- construct
- get
- get
- getKindName
- getBinding
- getDescriptorSet
- getStorageClass
- verifyInvariants
- get
- get
- getKindName
- getVersion
- ext_iterator
- getExtensions
- getExtensionsAttr
- cap_iterator
- getCapabilities
- getCapabilitiesAttr
- verifyInvariants
- get
- getKindName
- getTripleAttr
- getVersion
- getExtensions
- getExtensionsAttr
- getCapabilities
- getCapabilitiesAttr
- getClientAPI
- getVendorID
- getDeviceType
- getDeviceID
- getResourceLimits
- parseKeywordList
- parseInterfaceVarABIAttr
- parseVerCapExtAttr
- parseTargetEnvAttr
Improve your Profiling and Debugging skills
Find out more