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
17using namespace mlir;
18using namespace mlir::spirv;
19
20//===----------------------------------------------------------------------===//
21// TableGen'erated attribute utility functions
22//===----------------------------------------------------------------------===//
23
24namespace mlir {
25namespace spirv {
26#include "mlir/Dialect/SPIRV/IR/SPIRVAttrUtils.inc"
27} // namespace spirv
28
29//===----------------------------------------------------------------------===//
30// Attribute storage classes
31//===----------------------------------------------------------------------===//
32
33namespace spirv {
34namespace detail {
35
36struct 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
61struct 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
85struct 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
123spirv::InterfaceVarABIAttr
124spirv::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
136spirv::InterfaceVarABIAttr
137spirv::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
144StringRef spirv::InterfaceVarABIAttr::getKindName() {
145 return "interface_var_abi";
146}
147
148uint32_t spirv::InterfaceVarABIAttr::getBinding() {
149 return llvm::cast<IntegerAttr>(getImpl()->binding).getInt();
150}
151
152uint32_t spirv::InterfaceVarABIAttr::getDescriptorSet() {
153 return llvm::cast<IntegerAttr>(getImpl()->descriptorSet).getInt();
154}
155
156std::optional<spirv::StorageClass>
157spirv::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
166LogicalResult 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
193spirv::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
213spirv::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
221StringRef spirv::VerCapExtAttr::getKindName() { return "vce"; }
222
223spirv::Version spirv::VerCapExtAttr::getVersion() {
224 return static_cast<spirv::Version>(
225 llvm::cast<IntegerAttr>(getImpl()->version).getValue().getZExtValue());
226}
227
228spirv::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
235spirv::VerCapExtAttr::ext_range spirv::VerCapExtAttr::getExtensions() {
236 auto range = getExtensionsAttr().getValue();
237 return {ext_iterator(range.begin()), ext_iterator(range.end())};
238}
239
240ArrayAttr spirv::VerCapExtAttr::getExtensionsAttr() {
241 return llvm::cast<ArrayAttr>(getImpl()->extensions);
242}
243
244spirv::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
252spirv::VerCapExtAttr::cap_range spirv::VerCapExtAttr::getCapabilities() {
253 auto range = getCapabilitiesAttr().getValue();
254 return {cap_iterator(range.begin()), cap_iterator(range.end())};
255}
256
257ArrayAttr spirv::VerCapExtAttr::getCapabilitiesAttr() {
258 return llvm::cast<ArrayAttr>(getImpl()->capabilities);
259}
260
261LogicalResult 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
290spirv::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
299StringRef spirv::TargetEnvAttr::getKindName() { return "target_env"; }
300
301spirv::VerCapExtAttr spirv::TargetEnvAttr::getTripleAttr() const {
302 return llvm::cast<spirv::VerCapExtAttr>(getImpl()->triple);
303}
304
305spirv::Version spirv::TargetEnvAttr::getVersion() const {
306 return getTripleAttr().getVersion();
307}
308
309spirv::VerCapExtAttr::ext_range spirv::TargetEnvAttr::getExtensions() {
310 return getTripleAttr().getExtensions();
311}
312
313ArrayAttr spirv::TargetEnvAttr::getExtensionsAttr() {
314 return getTripleAttr().getExtensionsAttr();
315}
316
317spirv::VerCapExtAttr::cap_range spirv::TargetEnvAttr::getCapabilities() {
318 return getTripleAttr().getCapabilities();
319}
320
321ArrayAttr spirv::TargetEnvAttr::getCapabilitiesAttr() {
322 return getTripleAttr().getCapabilitiesAttr();
323}
324
325spirv::ClientAPI spirv::TargetEnvAttr::getClientAPI() const {
326 return getImpl()->clientAPI;
327}
328
329spirv::Vendor spirv::TargetEnvAttr::getVendorID() const {
330 return getImpl()->vendorID;
331}
332
333spirv::DeviceType spirv::TargetEnvAttr::getDeviceType() const {
334 return getImpl()->deviceType;
335}
336
337uint32_t spirv::TargetEnvAttr::getDeviceID() const {
338 return getImpl()->deviceID;
339}
340
341spirv::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.
358static ParseResult
359parseKeywordList(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.
383static 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
451static 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.
526static 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
592Attribute 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
624static 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
635static 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
655static 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
666void 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
685void 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

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of mlir/lib/Dialect/SPIRV/IR/SPIRVAttributes.cpp