MLIR  15.0.0git
SPIRVAttributes.cpp
Go to the documentation of this file.
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 
12 #include "mlir/IR/Builders.h"
13 
14 using namespace mlir;
15 
16 //===----------------------------------------------------------------------===//
17 // TableGen'erated attribute utility functions
18 //===----------------------------------------------------------------------===//
19 
20 namespace mlir {
21 namespace spirv {
22 #include "mlir/Dialect/SPIRV/IR/SPIRVAttrUtils.inc"
23 } // namespace spirv
24 } // namespace mlir
25 
26 //===----------------------------------------------------------------------===//
27 // DictionaryDict derived attributes
28 //===----------------------------------------------------------------------===//
29 
30 #include "mlir/Dialect/SPIRV/IR/TargetAndABI.cpp.inc"
31 
32 namespace mlir {
33 
34 //===----------------------------------------------------------------------===//
35 // Attribute storage classes
36 //===----------------------------------------------------------------------===//
37 
38 namespace spirv {
39 namespace detail {
40 
42  using KeyTy = std::tuple<Attribute, Attribute, Attribute>;
43 
45  Attribute storageClass)
46  : descriptorSet(descriptorSet), binding(binding),
47  storageClass(storageClass) {}
48 
49  bool operator==(const KeyTy &key) const {
50  return std::get<0>(key) == descriptorSet && std::get<1>(key) == binding &&
51  std::get<2>(key) == storageClass;
52  }
53 
55  construct(AttributeStorageAllocator &allocator, const KeyTy &key) {
56  return new (allocator.allocate<InterfaceVarABIAttributeStorage>())
57  InterfaceVarABIAttributeStorage(std::get<0>(key), std::get<1>(key),
58  std::get<2>(key));
59  }
60 
64 };
65 
67  using KeyTy = std::tuple<Attribute, Attribute, Attribute>;
68 
70  Attribute extensions)
71  : version(version), capabilities(capabilities), extensions(extensions) {}
72 
73  bool operator==(const KeyTy &key) const {
74  return std::get<0>(key) == version && std::get<1>(key) == capabilities &&
75  std::get<2>(key) == extensions;
76  }
77 
79  construct(AttributeStorageAllocator &allocator, const KeyTy &key) {
80  return new (allocator.allocate<VerCapExtAttributeStorage>())
81  VerCapExtAttributeStorage(std::get<0>(key), std::get<1>(key),
82  std::get<2>(key));
83  }
84 
88 };
89 
91  using KeyTy = std::tuple<Attribute, Vendor, DeviceType, uint32_t, Attribute>;
92 
93  TargetEnvAttributeStorage(Attribute triple, Vendor vendorID,
94  DeviceType deviceType, uint32_t deviceID,
95  Attribute limits)
96  : triple(triple), limits(limits), vendorID(vendorID),
97  deviceType(deviceType), deviceID(deviceID) {}
98 
99  bool operator==(const KeyTy &key) const {
100  return key ==
101  std::make_tuple(triple, vendorID, deviceType, deviceID, limits);
102  }
103 
105  construct(AttributeStorageAllocator &allocator, const KeyTy &key) {
106  return new (allocator.allocate<TargetEnvAttributeStorage>())
107  TargetEnvAttributeStorage(std::get<0>(key), std::get<1>(key),
108  std::get<2>(key), std::get<3>(key),
109  std::get<4>(key));
110  }
111 
114  Vendor vendorID;
115  DeviceType deviceType;
116  uint32_t deviceID;
117 };
118 } // namespace detail
119 } // namespace spirv
120 } // namespace mlir
121 
122 //===----------------------------------------------------------------------===//
123 // InterfaceVarABIAttr
124 //===----------------------------------------------------------------------===//
125 
127 spirv::InterfaceVarABIAttr::get(uint32_t descriptorSet, uint32_t binding,
128  Optional<spirv::StorageClass> storageClass,
129  MLIRContext *context) {
130  Builder b(context);
131  auto descriptorSetAttr = b.getI32IntegerAttr(descriptorSet);
132  auto bindingAttr = b.getI32IntegerAttr(binding);
133  auto storageClassAttr =
134  storageClass ? b.getI32IntegerAttr(static_cast<uint32_t>(*storageClass))
135  : IntegerAttr();
136  return get(descriptorSetAttr, bindingAttr, storageClassAttr);
137 }
138 
140 spirv::InterfaceVarABIAttr::get(IntegerAttr descriptorSet, IntegerAttr binding,
141  IntegerAttr storageClass) {
142  assert(descriptorSet && binding);
143  MLIRContext *context = descriptorSet.getContext();
144  return Base::get(context, descriptorSet, binding, storageClass);
145 }
146 
148  return "interface_var_abi";
149 }
150 
152  return getImpl()->binding.cast<IntegerAttr>().getInt();
153 }
154 
156  return getImpl()->descriptorSet.cast<IntegerAttr>().getInt();
157 }
158 
160  if (getImpl()->storageClass)
161  return static_cast<spirv::StorageClass>(
162  getImpl()->storageClass.cast<IntegerAttr>().getValue().getZExtValue());
163  return llvm::None;
164 }
165 
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 = storageClass.cast<IntegerAttr>()) {
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 
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(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(extensions.size());
207  for (spirv::Extension ext : extensions)
208  extAttrs.push_back(b.getStringAttr(spirv::stringifyExtension(ext)));
209 
210  return get(versionAttr, b.getArrayAttr(capAttrs), b.getArrayAttr(extAttrs));
211 }
212 
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 
224  return static_cast<spirv::Version>(
225  getImpl()->version.cast<IntegerAttr>().getValue().getZExtValue());
226 }
227 
229  : llvm::mapped_iterator<ArrayAttr::iterator,
230  spirv::Extension (*)(Attribute)>(
231  it, [](Attribute attr) {
232  return *symbolizeExtension(attr.cast<StringAttr>().getValue());
233  }) {}
234 
236  auto range = getExtensionsAttr().getValue();
237  return {ext_iterator(range.begin()), ext_iterator(range.end())};
238 }
239 
241  return getImpl()->extensions.cast<ArrayAttr>();
242 }
243 
245  : llvm::mapped_iterator<ArrayAttr::iterator,
246  spirv::Capability (*)(Attribute)>(
247  it, [](Attribute attr) {
248  return *symbolizeCapability(
249  attr.cast<IntegerAttr>().getValue().getZExtValue());
250  }) {}
251 
253  auto range = getCapabilitiesAttr().getValue();
254  return {cap_iterator(range.begin()), cap_iterator(range.end())};
255 }
256 
258  return getImpl()->capabilities.cast<ArrayAttr>();
259 }
260 
263  IntegerAttr version, ArrayAttr capabilities,
264  ArrayAttr extensions) {
265  if (!version.getType().isSignlessInteger(32))
266  return emitError() << "expected 32-bit integer for version";
267 
268  if (!llvm::all_of(capabilities.getValue(), [](Attribute attr) {
269  if (auto intAttr = attr.dyn_cast<IntegerAttr>())
270  if (spirv::symbolizeCapability(intAttr.getValue().getZExtValue()))
271  return true;
272  return false;
273  }))
274  return emitError() << "unknown capability in capability list";
275 
276  if (!llvm::all_of(extensions.getValue(), [](Attribute attr) {
277  if (auto strAttr = attr.dyn_cast<StringAttr>())
278  if (spirv::symbolizeExtension(strAttr.getValue()))
279  return true;
280  return false;
281  }))
282  return emitError() << "unknown extension in extension list";
283 
284  return success();
285 }
286 
287 //===----------------------------------------------------------------------===//
288 // TargetEnvAttr
289 //===----------------------------------------------------------------------===//
290 
292  Vendor vendorID,
293  DeviceType deviceType,
294  uint32_t deviceID,
295  DictionaryAttr limits) {
296  assert(triple && limits && "expected valid triple and limits");
297  MLIRContext *context = triple.getContext();
298  return Base::get(context, triple, vendorID, deviceType, deviceID, limits);
299 }
300 
301 StringRef spirv::TargetEnvAttr::getKindName() { return "target_env"; }
302 
304  return getImpl()->triple.cast<spirv::VerCapExtAttr>();
305 }
306 
307 spirv::Version spirv::TargetEnvAttr::getVersion() const {
308  return getTripleAttr().getVersion();
309 }
310 
312  return getTripleAttr().getExtensions();
313 }
314 
316  return getTripleAttr().getExtensionsAttr();
317 }
318 
320  return getTripleAttr().getCapabilities();
321 }
322 
324  return getTripleAttr().getCapabilitiesAttr();
325 }
326 
327 spirv::Vendor spirv::TargetEnvAttr::getVendorID() const {
328  return getImpl()->vendorID;
329 }
330 
331 spirv::DeviceType spirv::TargetEnvAttr::getDeviceType() const {
332  return getImpl()->deviceType;
333 }
334 
336  return getImpl()->deviceID;
337 }
338 
339 spirv::ResourceLimitsAttr spirv::TargetEnvAttr::getResourceLimits() const {
340  return getImpl()->limits.cast<spirv::ResourceLimitsAttr>();
341 }
342 
345  spirv::VerCapExtAttr /*triple*/,
346  spirv::Vendor /*vendorID*/,
347  spirv::DeviceType /*deviceType*/,
348  uint32_t /*deviceID*/, DictionaryAttr limits) {
349  if (!limits.isa<spirv::ResourceLimitsAttr>())
350  return emitError() << "expected spirv::ResourceLimitsAttr for limits";
351 
352  return success();
353 }
354 
355 //===----------------------------------------------------------------------===//
356 // SPIR-V Dialect
357 //===----------------------------------------------------------------------===//
358 
359 void spirv::SPIRVDialect::registerAttributes() {
360  addAttributes<InterfaceVarABIAttr, TargetEnvAttr, VerCapExtAttr>();
361 }
static LogicalResult verify(function_ref< InFlightDiagnostic()> emitError, IntegerAttr version, ArrayAttr capabilities, ArrayAttr extensions)
ArrayAttr getCapabilitiesAttr()
Returns the capabilities as an integer array attribute.
Include the generated interface declarations.
Explicitly register a set of "builtin" types.
Definition: CallGraph.h:221
static StringRef getKindName()
Returns the attribute kind&#39;s name (without the &#39;spv.&#39; prefix).
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:311
An attribute that specifies the information regarding the interface variable: descriptor set...
static TargetEnvAttr get(VerCapExtAttr triple, Vendor vendorID, DeviceType deviceType, uint32_t deviceId, DictionaryAttr limits)
Gets a TargetEnvAttr instance.
This is a utility allocator used to allocate memory for instances of derived types.
ArrayAttr getExtensionsAttr()
Returns the extensions as a string array attribute.
static LogicalResult verify(function_ref< InFlightDiagnostic()> emitError, IntegerAttr descriptorSet, IntegerAttr binding, IntegerAttr storageClass)
ArrayAttr getExtensionsAttr()
Returns the target extensions as a string array attribute.
static ConcreteT get(MLIRContext *ctx, Args... args)
Get or create a new ConcreteT instance within the ctx.
ext_range getExtensions()
Returns the extensions.
DeviceType getDeviceType() const
Returns the device type.
IntegerAttr getI32IntegerAttr(int32_t value)
Definition: Builders.cpp:148
T * allocate()
Allocate an instance of the provided type.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
std::tuple< Attribute, Attribute, Attribute > KeyTy
std::tuple< Attribute, Vendor, DeviceType, uint32_t, Attribute > KeyTy
static TargetEnvAttributeStorage * construct(AttributeStorageAllocator &allocator, const KeyTy &key)
ResourceLimitsAttr getResourceLimits() const
Returns the target resource limits.
Attributes are known-constant values of operations.
Definition: Attributes.h:24
static StringRef getKindName()
Returns the attribute kind&#39;s name (without the &#39;spv.&#39; prefix).
uint32_t getDescriptorSet()
Returns descriptor set.
TargetEnvAttributeStorage(Attribute triple, Vendor vendorID, DeviceType deviceType, uint32_t deviceID, Attribute limits)
An attribute that specifies the SPIR-V (version, capabilities, extensions) triple.
Vendor getVendorID() const
Returns the vendor ID.
uint32_t getBinding()
Returns binding.
std::tuple< Attribute, Attribute, Attribute > KeyTy
static LogicalResult verify(function_ref< InFlightDiagnostic()> emitError, VerCapExtAttr triple, Vendor vendorID, DeviceType deviceType, uint32_t deviceID, DictionaryAttr limits)
uint32_t getDeviceID() const
Returns the device ID.
VerCapExtAttr::cap_range getCapabilities()
Returns the target capabilities.
InterfaceVarABIAttributeStorage(Attribute descriptorSet, Attribute binding, Attribute storageClass)
cap_range getCapabilities()
Returns the capabilities.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
static InterfaceVarABIAttributeStorage * construct(AttributeStorageAllocator &allocator, const KeyTy &key)
This class is a general helper class for creating context-global objects like types, attributes, and affine expressions.
Definition: Builders.h:49
ImplType * getImpl() const
Utility for easy access to the storage instance.
static InterfaceVarABIAttr get(uint32_t descriptorSet, uint32_t binding, Optional< StorageClass > storageClass, MLIRContext *context)
Gets a InterfaceVarABIAttr.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:55
static VerCapExtAttributeStorage * construct(AttributeStorageAllocator &allocator, const KeyTy &key)
VerCapExtAttr getTripleAttr() const
Returns the (version, capabilities, extensions) triple attribute.
Base storage class appearing in an attribute.
static VerCapExtAttr get(Version version, ArrayRef< Capability > capabilities, ArrayRef< Extension > extensions, MLIRContext *context)
Gets a VerCapExtAttr instance.
static StringRef getKindName()
Returns the attribute kind&#39;s name (without the &#39;spv.&#39; prefix).
Version getVersion() const
Returns the target version.
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
Definition: Builders.cpp:205
ArrayAttr getCapabilitiesAttr()
Returns the target capabilities as an integer array attribute.
StringAttr getStringAttr(const Twine &bytes)
Definition: Builders.cpp:201
An attribute that specifies the target version, allowed extensions and capabilities, and resource limits.
Optional< StorageClass > getStorageClass()
Returns spirv::StorageClass.
Version getVersion()
Returns the version.
VerCapExtAttr::ext_range getExtensions()
Returns the target extensions.
VerCapExtAttributeStorage(Attribute version, Attribute capabilities, Attribute extensions)