MLIR  19.0.0git
IRAttributes.cpp
Go to the documentation of this file.
1 //===- IRAttributes.cpp - Exports builtin and standard attributes ---------===//
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 <optional>
10 #include <string_view>
11 #include <utility>
12 
13 #include "IRModule.h"
14 
15 #include "PybindUtils.h"
16 
17 #include "llvm/ADT/ScopeExit.h"
18 
20 #include "mlir-c/BuiltinTypes.h"
22 
23 namespace py = pybind11;
24 using namespace mlir;
25 using namespace mlir::python;
26 
27 using llvm::SmallVector;
28 
29 //------------------------------------------------------------------------------
30 // Docstrings (trivial, non-duplicated docstrings are included inline).
31 //------------------------------------------------------------------------------
32 
33 static const char kDenseElementsAttrGetDocstring[] =
34  R"(Gets a DenseElementsAttr from a Python buffer or array.
35 
36 When `type` is not provided, then some limited type inferencing is done based
37 on the buffer format. Support presently exists for 8/16/32/64 signed and
38 unsigned integers and float16/float32/float64. DenseElementsAttrs of these
39 types can also be converted back to a corresponding buffer.
40 
41 For conversions outside of these types, a `type=` must be explicitly provided
42 and the buffer contents must be bit-castable to the MLIR internal
43 representation:
44 
45  * Integer types (except for i1): the buffer must be byte aligned to the
46  next byte boundary.
47  * Floating point types: Must be bit-castable to the given floating point
48  size.
49  * i1 (bool): Bit packed into 8bit words where the bit pattern matches a
50  row major ordering. An arbitrary Numpy `bool_` array can be bit packed to
51  this specification with: `np.packbits(ary, axis=None, bitorder='little')`.
52 
53 If a single element buffer is passed (or for i1, a single byte with value 0
54 or 255), then a splat will be created.
55 
56 Args:
57  array: The array or buffer to convert.
58  signless: If inferring an appropriate MLIR type, use signless types for
59  integers (defaults True).
60  type: Skips inference of the MLIR element type and uses this instead. The
61  storage size must be consistent with the actual contents of the buffer.
62  shape: Overrides the shape of the buffer when constructing the MLIR
63  shaped type. This is needed when the physical and logical shape differ (as
64  for i1).
65  context: Explicit context, if not from context manager.
66 
67 Returns:
68  DenseElementsAttr on success.
69 
70 Raises:
71  ValueError: If the type of the buffer or array cannot be matched to an MLIR
72  type or if the buffer does not meet expectations.
73 )";
74 
76  R"(Gets a DenseResourceElementsAttr from a Python buffer or array.
77 
78 This function does minimal validation or massaging of the data, and it is
79 up to the caller to ensure that the buffer meets the characteristics
80 implied by the shape.
81 
82 The backing buffer and any user objects will be retained for the lifetime
83 of the resource blob. This is typically bounded to the context but the
84 resource can have a shorter lifespan depending on how it is used in
85 subsequent processing.
86 
87 Args:
88  buffer: The array or buffer to convert.
89  name: Name to provide to the resource (may be changed upon collision).
90  type: The explicit ShapedType to construct the attribute with.
91  context: Explicit context, if not from context manager.
92 
93 Returns:
94  DenseResourceElementsAttr on success.
95 
96 Raises:
97  ValueError: If the type of the buffer or array cannot be matched to an MLIR
98  type or if the buffer does not meet expectations.
99 )";
100 
101 namespace {
102 
103 static MlirStringRef toMlirStringRef(const std::string &s) {
104  return mlirStringRefCreate(s.data(), s.size());
105 }
106 
107 class PyAffineMapAttribute : public PyConcreteAttribute<PyAffineMapAttribute> {
108 public:
109  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAAffineMap;
110  static constexpr const char *pyClassName = "AffineMapAttr";
112  static constexpr GetTypeIDFunctionTy getTypeIdFunction =
114 
115  static void bindDerived(ClassTy &c) {
116  c.def_static(
117  "get",
118  [](PyAffineMap &affineMap) {
119  MlirAttribute attr = mlirAffineMapAttrGet(affineMap.get());
120  return PyAffineMapAttribute(affineMap.getContext(), attr);
121  },
122  py::arg("affine_map"), "Gets an attribute wrapping an AffineMap.");
123  }
124 };
125 
126 template <typename T>
127 static T pyTryCast(py::handle object) {
128  try {
129  return object.cast<T>();
130  } catch (py::cast_error &err) {
131  std::string msg =
132  std::string(
133  "Invalid attribute when attempting to create an ArrayAttribute (") +
134  err.what() + ")";
135  throw py::cast_error(msg);
136  } catch (py::reference_cast_error &err) {
137  std::string msg = std::string("Invalid attribute (None?) when attempting "
138  "to create an ArrayAttribute (") +
139  err.what() + ")";
140  throw py::cast_error(msg);
141  }
142 }
143 
144 /// A python-wrapped dense array attribute with an element type and a derived
145 /// implementation class.
146 template <typename EltTy, typename DerivedT>
147 class PyDenseArrayAttribute : public PyConcreteAttribute<DerivedT> {
148 public:
150 
151  /// Iterator over the integer elements of a dense array.
152  class PyDenseArrayIterator {
153  public:
154  PyDenseArrayIterator(PyAttribute attr) : attr(std::move(attr)) {}
155 
156  /// Return a copy of the iterator.
157  PyDenseArrayIterator dunderIter() { return *this; }
158 
159  /// Return the next element.
160  EltTy dunderNext() {
161  // Throw if the index has reached the end.
163  throw py::stop_iteration();
164  return DerivedT::getElement(attr.get(), nextIndex++);
165  }
166 
167  /// Bind the iterator class.
168  static void bind(py::module &m) {
169  py::class_<PyDenseArrayIterator>(m, DerivedT::pyIteratorName,
170  py::module_local())
171  .def("__iter__", &PyDenseArrayIterator::dunderIter)
172  .def("__next__", &PyDenseArrayIterator::dunderNext);
173  }
174 
175  private:
176  /// The referenced dense array attribute.
177  PyAttribute attr;
178  /// The next index to read.
179  int nextIndex = 0;
180  };
181 
182  /// Get the element at the given index.
183  EltTy getItem(intptr_t i) { return DerivedT::getElement(*this, i); }
184 
185  /// Bind the attribute class.
186  static void bindDerived(typename PyConcreteAttribute<DerivedT>::ClassTy &c) {
187  // Bind the constructor.
188  c.def_static(
189  "get",
190  [](const std::vector<EltTy> &values, DefaultingPyMlirContext ctx) {
191  return getAttribute(values, ctx->getRef());
192  },
193  py::arg("values"), py::arg("context") = py::none(),
194  "Gets a uniqued dense array attribute");
195  // Bind the array methods.
196  c.def("__getitem__", [](DerivedT &arr, intptr_t i) {
197  if (i >= mlirDenseArrayGetNumElements(arr))
198  throw py::index_error("DenseArray index out of range");
199  return arr.getItem(i);
200  });
201  c.def("__len__", [](const DerivedT &arr) {
202  return mlirDenseArrayGetNumElements(arr);
203  });
204  c.def("__iter__",
205  [](const DerivedT &arr) { return PyDenseArrayIterator(arr); });
206  c.def("__add__", [](DerivedT &arr, const py::list &extras) {
207  std::vector<EltTy> values;
208  intptr_t numOldElements = mlirDenseArrayGetNumElements(arr);
209  values.reserve(numOldElements + py::len(extras));
210  for (intptr_t i = 0; i < numOldElements; ++i)
211  values.push_back(arr.getItem(i));
212  for (py::handle attr : extras)
213  values.push_back(pyTryCast<EltTy>(attr));
214  return getAttribute(values, arr.getContext());
215  });
216  }
217 
218 private:
219  static DerivedT getAttribute(const std::vector<EltTy> &values,
220  PyMlirContextRef ctx) {
221  if constexpr (std::is_same_v<EltTy, bool>) {
222  std::vector<int> intValues(values.begin(), values.end());
223  MlirAttribute attr = DerivedT::getAttribute(ctx->get(), intValues.size(),
224  intValues.data());
225  return DerivedT(ctx, attr);
226  } else {
227  MlirAttribute attr =
228  DerivedT::getAttribute(ctx->get(), values.size(), values.data());
229  return DerivedT(ctx, attr);
230  }
231  }
232 };
233 
234 /// Instantiate the python dense array classes.
235 struct PyDenseBoolArrayAttribute
236  : public PyDenseArrayAttribute<bool, PyDenseBoolArrayAttribute> {
237  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseBoolArray;
238  static constexpr auto getAttribute = mlirDenseBoolArrayGet;
239  static constexpr auto getElement = mlirDenseBoolArrayGetElement;
240  static constexpr const char *pyClassName = "DenseBoolArrayAttr";
241  static constexpr const char *pyIteratorName = "DenseBoolArrayIterator";
242  using PyDenseArrayAttribute::PyDenseArrayAttribute;
243 };
244 struct PyDenseI8ArrayAttribute
245  : public PyDenseArrayAttribute<int8_t, PyDenseI8ArrayAttribute> {
246  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseI8Array;
247  static constexpr auto getAttribute = mlirDenseI8ArrayGet;
248  static constexpr auto getElement = mlirDenseI8ArrayGetElement;
249  static constexpr const char *pyClassName = "DenseI8ArrayAttr";
250  static constexpr const char *pyIteratorName = "DenseI8ArrayIterator";
251  using PyDenseArrayAttribute::PyDenseArrayAttribute;
252 };
253 struct PyDenseI16ArrayAttribute
254  : public PyDenseArrayAttribute<int16_t, PyDenseI16ArrayAttribute> {
255  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseI16Array;
256  static constexpr auto getAttribute = mlirDenseI16ArrayGet;
257  static constexpr auto getElement = mlirDenseI16ArrayGetElement;
258  static constexpr const char *pyClassName = "DenseI16ArrayAttr";
259  static constexpr const char *pyIteratorName = "DenseI16ArrayIterator";
260  using PyDenseArrayAttribute::PyDenseArrayAttribute;
261 };
262 struct PyDenseI32ArrayAttribute
263  : public PyDenseArrayAttribute<int32_t, PyDenseI32ArrayAttribute> {
264  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseI32Array;
265  static constexpr auto getAttribute = mlirDenseI32ArrayGet;
266  static constexpr auto getElement = mlirDenseI32ArrayGetElement;
267  static constexpr const char *pyClassName = "DenseI32ArrayAttr";
268  static constexpr const char *pyIteratorName = "DenseI32ArrayIterator";
269  using PyDenseArrayAttribute::PyDenseArrayAttribute;
270 };
271 struct PyDenseI64ArrayAttribute
272  : public PyDenseArrayAttribute<int64_t, PyDenseI64ArrayAttribute> {
273  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseI64Array;
274  static constexpr auto getAttribute = mlirDenseI64ArrayGet;
275  static constexpr auto getElement = mlirDenseI64ArrayGetElement;
276  static constexpr const char *pyClassName = "DenseI64ArrayAttr";
277  static constexpr const char *pyIteratorName = "DenseI64ArrayIterator";
278  using PyDenseArrayAttribute::PyDenseArrayAttribute;
279 };
280 struct PyDenseF32ArrayAttribute
281  : public PyDenseArrayAttribute<float, PyDenseF32ArrayAttribute> {
282  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseF32Array;
283  static constexpr auto getAttribute = mlirDenseF32ArrayGet;
284  static constexpr auto getElement = mlirDenseF32ArrayGetElement;
285  static constexpr const char *pyClassName = "DenseF32ArrayAttr";
286  static constexpr const char *pyIteratorName = "DenseF32ArrayIterator";
287  using PyDenseArrayAttribute::PyDenseArrayAttribute;
288 };
289 struct PyDenseF64ArrayAttribute
290  : public PyDenseArrayAttribute<double, PyDenseF64ArrayAttribute> {
291  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseF64Array;
292  static constexpr auto getAttribute = mlirDenseF64ArrayGet;
293  static constexpr auto getElement = mlirDenseF64ArrayGetElement;
294  static constexpr const char *pyClassName = "DenseF64ArrayAttr";
295  static constexpr const char *pyIteratorName = "DenseF64ArrayIterator";
296  using PyDenseArrayAttribute::PyDenseArrayAttribute;
297 };
298 
299 class PyArrayAttribute : public PyConcreteAttribute<PyArrayAttribute> {
300 public:
301  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAArray;
302  static constexpr const char *pyClassName = "ArrayAttr";
304  static constexpr GetTypeIDFunctionTy getTypeIdFunction =
306 
307  class PyArrayAttributeIterator {
308  public:
309  PyArrayAttributeIterator(PyAttribute attr) : attr(std::move(attr)) {}
310 
311  PyArrayAttributeIterator &dunderIter() { return *this; }
312 
313  MlirAttribute dunderNext() {
314  // TODO: Throw is an inefficient way to stop iteration.
316  throw py::stop_iteration();
317  return mlirArrayAttrGetElement(attr.get(), nextIndex++);
318  }
319 
320  static void bind(py::module &m) {
321  py::class_<PyArrayAttributeIterator>(m, "ArrayAttributeIterator",
322  py::module_local())
323  .def("__iter__", &PyArrayAttributeIterator::dunderIter)
324  .def("__next__", &PyArrayAttributeIterator::dunderNext);
325  }
326 
327  private:
328  PyAttribute attr;
329  int nextIndex = 0;
330  };
331 
332  MlirAttribute getItem(intptr_t i) {
333  return mlirArrayAttrGetElement(*this, i);
334  }
335 
336  static void bindDerived(ClassTy &c) {
337  c.def_static(
338  "get",
339  [](py::list attributes, DefaultingPyMlirContext context) {
340  SmallVector<MlirAttribute> mlirAttributes;
341  mlirAttributes.reserve(py::len(attributes));
342  for (auto attribute : attributes) {
343  mlirAttributes.push_back(pyTryCast<PyAttribute>(attribute));
344  }
345  MlirAttribute attr = mlirArrayAttrGet(
346  context->get(), mlirAttributes.size(), mlirAttributes.data());
347  return PyArrayAttribute(context->getRef(), attr);
348  },
349  py::arg("attributes"), py::arg("context") = py::none(),
350  "Gets a uniqued Array attribute");
351  c.def("__getitem__",
352  [](PyArrayAttribute &arr, intptr_t i) {
353  if (i >= mlirArrayAttrGetNumElements(arr))
354  throw py::index_error("ArrayAttribute index out of range");
355  return arr.getItem(i);
356  })
357  .def("__len__",
358  [](const PyArrayAttribute &arr) {
359  return mlirArrayAttrGetNumElements(arr);
360  })
361  .def("__iter__", [](const PyArrayAttribute &arr) {
362  return PyArrayAttributeIterator(arr);
363  });
364  c.def("__add__", [](PyArrayAttribute arr, py::list extras) {
365  std::vector<MlirAttribute> attributes;
366  intptr_t numOldElements = mlirArrayAttrGetNumElements(arr);
367  attributes.reserve(numOldElements + py::len(extras));
368  for (intptr_t i = 0; i < numOldElements; ++i)
369  attributes.push_back(arr.getItem(i));
370  for (py::handle attr : extras)
371  attributes.push_back(pyTryCast<PyAttribute>(attr));
372  MlirAttribute arrayAttr = mlirArrayAttrGet(
373  arr.getContext()->get(), attributes.size(), attributes.data());
374  return PyArrayAttribute(arr.getContext(), arrayAttr);
375  });
376  }
377 };
378 
379 /// Float Point Attribute subclass - FloatAttr.
380 class PyFloatAttribute : public PyConcreteAttribute<PyFloatAttribute> {
381 public:
382  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAFloat;
383  static constexpr const char *pyClassName = "FloatAttr";
385  static constexpr GetTypeIDFunctionTy getTypeIdFunction =
387 
388  static void bindDerived(ClassTy &c) {
389  c.def_static(
390  "get",
391  [](PyType &type, double value, DefaultingPyLocation loc) {
392  PyMlirContext::ErrorCapture errors(loc->getContext());
393  MlirAttribute attr = mlirFloatAttrDoubleGetChecked(loc, type, value);
394  if (mlirAttributeIsNull(attr))
395  throw MLIRError("Invalid attribute", errors.take());
396  return PyFloatAttribute(type.getContext(), attr);
397  },
398  py::arg("type"), py::arg("value"), py::arg("loc") = py::none(),
399  "Gets an uniqued float point attribute associated to a type");
400  c.def_static(
401  "get_f32",
402  [](double value, DefaultingPyMlirContext context) {
403  MlirAttribute attr = mlirFloatAttrDoubleGet(
404  context->get(), mlirF32TypeGet(context->get()), value);
405  return PyFloatAttribute(context->getRef(), attr);
406  },
407  py::arg("value"), py::arg("context") = py::none(),
408  "Gets an uniqued float point attribute associated to a f32 type");
409  c.def_static(
410  "get_f64",
411  [](double value, DefaultingPyMlirContext context) {
412  MlirAttribute attr = mlirFloatAttrDoubleGet(
413  context->get(), mlirF64TypeGet(context->get()), value);
414  return PyFloatAttribute(context->getRef(), attr);
415  },
416  py::arg("value"), py::arg("context") = py::none(),
417  "Gets an uniqued float point attribute associated to a f64 type");
418  c.def_property_readonly("value", mlirFloatAttrGetValueDouble,
419  "Returns the value of the float attribute");
420  c.def("__float__", mlirFloatAttrGetValueDouble,
421  "Converts the value of the float attribute to a Python float");
422  }
423 };
424 
425 /// Integer Attribute subclass - IntegerAttr.
426 class PyIntegerAttribute : public PyConcreteAttribute<PyIntegerAttribute> {
427 public:
428  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAInteger;
429  static constexpr const char *pyClassName = "IntegerAttr";
431 
432  static void bindDerived(ClassTy &c) {
433  c.def_static(
434  "get",
435  [](PyType &type, int64_t value) {
436  MlirAttribute attr = mlirIntegerAttrGet(type, value);
437  return PyIntegerAttribute(type.getContext(), attr);
438  },
439  py::arg("type"), py::arg("value"),
440  "Gets an uniqued integer attribute associated to a type");
441  c.def_property_readonly("value", toPyInt,
442  "Returns the value of the integer attribute");
443  c.def("__int__", toPyInt,
444  "Converts the value of the integer attribute to a Python int");
445  c.def_property_readonly_static("static_typeid",
446  [](py::object & /*class*/) -> MlirTypeID {
447  return mlirIntegerAttrGetTypeID();
448  });
449  }
450 
451 private:
452  static py::int_ toPyInt(PyIntegerAttribute &self) {
453  MlirType type = mlirAttributeGetType(self);
454  if (mlirTypeIsAIndex(type) || mlirIntegerTypeIsSignless(type))
455  return mlirIntegerAttrGetValueInt(self);
456  if (mlirIntegerTypeIsSigned(type))
457  return mlirIntegerAttrGetValueSInt(self);
458  return mlirIntegerAttrGetValueUInt(self);
459  }
460 };
461 
462 /// Bool Attribute subclass - BoolAttr.
463 class PyBoolAttribute : public PyConcreteAttribute<PyBoolAttribute> {
464 public:
465  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsABool;
466  static constexpr const char *pyClassName = "BoolAttr";
468 
469  static void bindDerived(ClassTy &c) {
470  c.def_static(
471  "get",
472  [](bool value, DefaultingPyMlirContext context) {
473  MlirAttribute attr = mlirBoolAttrGet(context->get(), value);
474  return PyBoolAttribute(context->getRef(), attr);
475  },
476  py::arg("value"), py::arg("context") = py::none(),
477  "Gets an uniqued bool attribute");
478  c.def_property_readonly("value", mlirBoolAttrGetValue,
479  "Returns the value of the bool attribute");
480  c.def("__bool__", mlirBoolAttrGetValue,
481  "Converts the value of the bool attribute to a Python bool");
482  }
483 };
484 
485 class PySymbolRefAttribute : public PyConcreteAttribute<PySymbolRefAttribute> {
486 public:
487  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsASymbolRef;
488  static constexpr const char *pyClassName = "SymbolRefAttr";
490 
491  static MlirAttribute fromList(const std::vector<std::string> &symbols,
492  PyMlirContext &context) {
493  if (symbols.empty())
494  throw std::runtime_error("SymbolRefAttr must be composed of at least "
495  "one symbol.");
496  MlirStringRef rootSymbol = toMlirStringRef(symbols[0]);
497  SmallVector<MlirAttribute, 3> referenceAttrs;
498  for (size_t i = 1; i < symbols.size(); ++i) {
499  referenceAttrs.push_back(
500  mlirFlatSymbolRefAttrGet(context.get(), toMlirStringRef(symbols[i])));
501  }
502  return mlirSymbolRefAttrGet(context.get(), rootSymbol,
503  referenceAttrs.size(), referenceAttrs.data());
504  }
505 
506  static void bindDerived(ClassTy &c) {
507  c.def_static(
508  "get",
509  [](const std::vector<std::string> &symbols,
510  DefaultingPyMlirContext context) {
511  return PySymbolRefAttribute::fromList(symbols, context.resolve());
512  },
513  py::arg("symbols"), py::arg("context") = py::none(),
514  "Gets a uniqued SymbolRef attribute from a list of symbol names");
515  c.def_property_readonly(
516  "value",
517  [](PySymbolRefAttribute &self) {
518  std::vector<std::string> symbols = {
520  for (int i = 0; i < mlirSymbolRefAttrGetNumNestedReferences(self);
521  ++i)
522  symbols.push_back(
525  .str());
526  return symbols;
527  },
528  "Returns the value of the SymbolRef attribute as a list[str]");
529  }
530 };
531 
532 class PyFlatSymbolRefAttribute
533  : public PyConcreteAttribute<PyFlatSymbolRefAttribute> {
534 public:
535  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAFlatSymbolRef;
536  static constexpr const char *pyClassName = "FlatSymbolRefAttr";
538 
539  static void bindDerived(ClassTy &c) {
540  c.def_static(
541  "get",
542  [](std::string value, DefaultingPyMlirContext context) {
543  MlirAttribute attr =
544  mlirFlatSymbolRefAttrGet(context->get(), toMlirStringRef(value));
545  return PyFlatSymbolRefAttribute(context->getRef(), attr);
546  },
547  py::arg("value"), py::arg("context") = py::none(),
548  "Gets a uniqued FlatSymbolRef attribute");
549  c.def_property_readonly(
550  "value",
551  [](PyFlatSymbolRefAttribute &self) {
553  return py::str(stringRef.data, stringRef.length);
554  },
555  "Returns the value of the FlatSymbolRef attribute as a string");
556  }
557 };
558 
559 class PyOpaqueAttribute : public PyConcreteAttribute<PyOpaqueAttribute> {
560 public:
561  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAOpaque;
562  static constexpr const char *pyClassName = "OpaqueAttr";
564  static constexpr GetTypeIDFunctionTy getTypeIdFunction =
566 
567  static void bindDerived(ClassTy &c) {
568  c.def_static(
569  "get",
570  [](std::string dialectNamespace, py::buffer buffer, PyType &type,
571  DefaultingPyMlirContext context) {
572  const py::buffer_info bufferInfo = buffer.request();
573  intptr_t bufferSize = bufferInfo.size;
574  MlirAttribute attr = mlirOpaqueAttrGet(
575  context->get(), toMlirStringRef(dialectNamespace), bufferSize,
576  static_cast<char *>(bufferInfo.ptr), type);
577  return PyOpaqueAttribute(context->getRef(), attr);
578  },
579  py::arg("dialect_namespace"), py::arg("buffer"), py::arg("type"),
580  py::arg("context") = py::none(), "Gets an Opaque attribute.");
581  c.def_property_readonly(
582  "dialect_namespace",
583  [](PyOpaqueAttribute &self) {
585  return py::str(stringRef.data, stringRef.length);
586  },
587  "Returns the dialect namespace for the Opaque attribute as a string");
588  c.def_property_readonly(
589  "data",
590  [](PyOpaqueAttribute &self) {
591  MlirStringRef stringRef = mlirOpaqueAttrGetData(self);
592  return py::bytes(stringRef.data, stringRef.length);
593  },
594  "Returns the data for the Opaqued attributes as `bytes`");
595  }
596 };
597 
598 class PyStringAttribute : public PyConcreteAttribute<PyStringAttribute> {
599 public:
600  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAString;
601  static constexpr const char *pyClassName = "StringAttr";
603  static constexpr GetTypeIDFunctionTy getTypeIdFunction =
605 
606  static void bindDerived(ClassTy &c) {
607  c.def_static(
608  "get",
609  [](std::string value, DefaultingPyMlirContext context) {
610  MlirAttribute attr =
611  mlirStringAttrGet(context->get(), toMlirStringRef(value));
612  return PyStringAttribute(context->getRef(), attr);
613  },
614  py::arg("value"), py::arg("context") = py::none(),
615  "Gets a uniqued string attribute");
616  c.def_static(
617  "get_typed",
618  [](PyType &type, std::string value) {
619  MlirAttribute attr =
621  return PyStringAttribute(type.getContext(), attr);
622  },
623  py::arg("type"), py::arg("value"),
624  "Gets a uniqued string attribute associated to a type");
625  c.def_property_readonly(
626  "value",
627  [](PyStringAttribute &self) {
628  MlirStringRef stringRef = mlirStringAttrGetValue(self);
629  return py::str(stringRef.data, stringRef.length);
630  },
631  "Returns the value of the string attribute");
632  c.def_property_readonly(
633  "value_bytes",
634  [](PyStringAttribute &self) {
635  MlirStringRef stringRef = mlirStringAttrGetValue(self);
636  return py::bytes(stringRef.data, stringRef.length);
637  },
638  "Returns the value of the string attribute as `bytes`");
639  }
640 };
641 
642 // TODO: Support construction of string elements.
643 class PyDenseElementsAttribute
644  : public PyConcreteAttribute<PyDenseElementsAttribute> {
645 public:
646  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseElements;
647  static constexpr const char *pyClassName = "DenseElementsAttr";
649 
650  static PyDenseElementsAttribute
651  getFromBuffer(py::buffer array, bool signless,
652  std::optional<PyType> explicitType,
653  std::optional<std::vector<int64_t>> explicitShape,
654  DefaultingPyMlirContext contextWrapper) {
655  // Request a contiguous view. In exotic cases, this will cause a copy.
656  int flags = PyBUF_ND;
657  if (!explicitType) {
658  flags |= PyBUF_FORMAT;
659  }
660  Py_buffer view;
661  if (PyObject_GetBuffer(array.ptr(), &view, flags) != 0) {
662  throw py::error_already_set();
663  }
664  auto freeBuffer = llvm::make_scope_exit([&]() { PyBuffer_Release(&view); });
665  SmallVector<int64_t> shape;
666  if (explicitShape) {
667  shape.append(explicitShape->begin(), explicitShape->end());
668  } else {
669  shape.append(view.shape, view.shape + view.ndim);
670  }
671 
672  MlirAttribute encodingAttr = mlirAttributeGetNull();
673  MlirContext context = contextWrapper->get();
674 
675  // Detect format codes that are suitable for bulk loading. This includes
676  // all byte aligned integer and floating point types up to 8 bytes.
677  // Notably, this excludes, bool (which needs to be bit-packed) and
678  // other exotics which do not have a direct representation in the buffer
679  // protocol (i.e. complex, etc).
680  std::optional<MlirType> bulkLoadElementType;
681  if (explicitType) {
682  bulkLoadElementType = *explicitType;
683  } else {
684  std::string_view format(view.format);
685  if (format == "f") {
686  // f32
687  assert(view.itemsize == 4 && "mismatched array itemsize");
688  bulkLoadElementType = mlirF32TypeGet(context);
689  } else if (format == "d") {
690  // f64
691  assert(view.itemsize == 8 && "mismatched array itemsize");
692  bulkLoadElementType = mlirF64TypeGet(context);
693  } else if (format == "e") {
694  // f16
695  assert(view.itemsize == 2 && "mismatched array itemsize");
696  bulkLoadElementType = mlirF16TypeGet(context);
697  } else if (isSignedIntegerFormat(format)) {
698  if (view.itemsize == 4) {
699  // i32
700  bulkLoadElementType = signless
701  ? mlirIntegerTypeGet(context, 32)
702  : mlirIntegerTypeSignedGet(context, 32);
703  } else if (view.itemsize == 8) {
704  // i64
705  bulkLoadElementType = signless
706  ? mlirIntegerTypeGet(context, 64)
707  : mlirIntegerTypeSignedGet(context, 64);
708  } else if (view.itemsize == 1) {
709  // i8
710  bulkLoadElementType = signless ? mlirIntegerTypeGet(context, 8)
711  : mlirIntegerTypeSignedGet(context, 8);
712  } else if (view.itemsize == 2) {
713  // i16
714  bulkLoadElementType = signless
715  ? mlirIntegerTypeGet(context, 16)
716  : mlirIntegerTypeSignedGet(context, 16);
717  }
718  } else if (isUnsignedIntegerFormat(format)) {
719  if (view.itemsize == 4) {
720  // unsigned i32
721  bulkLoadElementType = signless
722  ? mlirIntegerTypeGet(context, 32)
723  : mlirIntegerTypeUnsignedGet(context, 32);
724  } else if (view.itemsize == 8) {
725  // unsigned i64
726  bulkLoadElementType = signless
727  ? mlirIntegerTypeGet(context, 64)
728  : mlirIntegerTypeUnsignedGet(context, 64);
729  } else if (view.itemsize == 1) {
730  // i8
731  bulkLoadElementType = signless
732  ? mlirIntegerTypeGet(context, 8)
733  : mlirIntegerTypeUnsignedGet(context, 8);
734  } else if (view.itemsize == 2) {
735  // i16
736  bulkLoadElementType = signless
737  ? mlirIntegerTypeGet(context, 16)
738  : mlirIntegerTypeUnsignedGet(context, 16);
739  }
740  }
741  if (!bulkLoadElementType) {
742  throw std::invalid_argument(
743  std::string("unimplemented array format conversion from format: ") +
744  std::string(format));
745  }
746  }
747 
748  MlirType shapedType;
749  if (mlirTypeIsAShaped(*bulkLoadElementType)) {
750  if (explicitShape) {
751  throw std::invalid_argument("Shape can only be specified explicitly "
752  "when the type is not a shaped type.");
753  }
754  shapedType = *bulkLoadElementType;
755  } else {
756  shapedType = mlirRankedTensorTypeGet(shape.size(), shape.data(),
757  *bulkLoadElementType, encodingAttr);
758  }
759  size_t rawBufferSize = view.len;
760  MlirAttribute attr =
761  mlirDenseElementsAttrRawBufferGet(shapedType, rawBufferSize, view.buf);
762  if (mlirAttributeIsNull(attr)) {
763  throw std::invalid_argument(
764  "DenseElementsAttr could not be constructed from the given buffer. "
765  "This may mean that the Python buffer layout does not match that "
766  "MLIR expected layout and is a bug.");
767  }
768  return PyDenseElementsAttribute(contextWrapper->getRef(), attr);
769  }
770 
771  static PyDenseElementsAttribute getSplat(const PyType &shapedType,
772  PyAttribute &elementAttr) {
773  auto contextWrapper =
775  if (!mlirAttributeIsAInteger(elementAttr) &&
776  !mlirAttributeIsAFloat(elementAttr)) {
777  std::string message = "Illegal element type for DenseElementsAttr: ";
778  message.append(py::repr(py::cast(elementAttr)));
779  throw py::value_error(message);
780  }
781  if (!mlirTypeIsAShaped(shapedType) ||
782  !mlirShapedTypeHasStaticShape(shapedType)) {
783  std::string message =
784  "Expected a static ShapedType for the shaped_type parameter: ";
785  message.append(py::repr(py::cast(shapedType)));
786  throw py::value_error(message);
787  }
788  MlirType shapedElementType = mlirShapedTypeGetElementType(shapedType);
789  MlirType attrType = mlirAttributeGetType(elementAttr);
790  if (!mlirTypeEqual(shapedElementType, attrType)) {
791  std::string message =
792  "Shaped element type and attribute type must be equal: shaped=";
793  message.append(py::repr(py::cast(shapedType)));
794  message.append(", element=");
795  message.append(py::repr(py::cast(elementAttr)));
796  throw py::value_error(message);
797  }
798 
799  MlirAttribute elements =
800  mlirDenseElementsAttrSplatGet(shapedType, elementAttr);
801  return PyDenseElementsAttribute(contextWrapper->getRef(), elements);
802  }
803 
804  intptr_t dunderLen() { return mlirElementsAttrGetNumElements(*this); }
805 
806  py::buffer_info accessBuffer() {
807  MlirType shapedType = mlirAttributeGetType(*this);
808  MlirType elementType = mlirShapedTypeGetElementType(shapedType);
809  std::string format;
810 
811  if (mlirTypeIsAF32(elementType)) {
812  // f32
813  return bufferInfo<float>(shapedType);
814  }
815  if (mlirTypeIsAF64(elementType)) {
816  // f64
817  return bufferInfo<double>(shapedType);
818  }
819  if (mlirTypeIsAF16(elementType)) {
820  // f16
821  return bufferInfo<uint16_t>(shapedType, "e");
822  }
823  if (mlirTypeIsAIndex(elementType)) {
824  // Same as IndexType::kInternalStorageBitWidth
825  return bufferInfo<int64_t>(shapedType);
826  }
827  if (mlirTypeIsAInteger(elementType) &&
828  mlirIntegerTypeGetWidth(elementType) == 32) {
829  if (mlirIntegerTypeIsSignless(elementType) ||
830  mlirIntegerTypeIsSigned(elementType)) {
831  // i32
832  return bufferInfo<int32_t>(shapedType);
833  }
834  if (mlirIntegerTypeIsUnsigned(elementType)) {
835  // unsigned i32
836  return bufferInfo<uint32_t>(shapedType);
837  }
838  } else if (mlirTypeIsAInteger(elementType) &&
839  mlirIntegerTypeGetWidth(elementType) == 64) {
840  if (mlirIntegerTypeIsSignless(elementType) ||
841  mlirIntegerTypeIsSigned(elementType)) {
842  // i64
843  return bufferInfo<int64_t>(shapedType);
844  }
845  if (mlirIntegerTypeIsUnsigned(elementType)) {
846  // unsigned i64
847  return bufferInfo<uint64_t>(shapedType);
848  }
849  } else if (mlirTypeIsAInteger(elementType) &&
850  mlirIntegerTypeGetWidth(elementType) == 8) {
851  if (mlirIntegerTypeIsSignless(elementType) ||
852  mlirIntegerTypeIsSigned(elementType)) {
853  // i8
854  return bufferInfo<int8_t>(shapedType);
855  }
856  if (mlirIntegerTypeIsUnsigned(elementType)) {
857  // unsigned i8
858  return bufferInfo<uint8_t>(shapedType);
859  }
860  } else if (mlirTypeIsAInteger(elementType) &&
861  mlirIntegerTypeGetWidth(elementType) == 16) {
862  if (mlirIntegerTypeIsSignless(elementType) ||
863  mlirIntegerTypeIsSigned(elementType)) {
864  // i16
865  return bufferInfo<int16_t>(shapedType);
866  }
867  if (mlirIntegerTypeIsUnsigned(elementType)) {
868  // unsigned i16
869  return bufferInfo<uint16_t>(shapedType);
870  }
871  }
872 
873  // TODO: Currently crashes the program.
874  // Reported as https://github.com/pybind/pybind11/issues/3336
875  throw std::invalid_argument(
876  "unsupported data type for conversion to Python buffer");
877  }
878 
879  static void bindDerived(ClassTy &c) {
880  c.def("__len__", &PyDenseElementsAttribute::dunderLen)
881  .def_static("get", PyDenseElementsAttribute::getFromBuffer,
882  py::arg("array"), py::arg("signless") = true,
883  py::arg("type") = py::none(), py::arg("shape") = py::none(),
884  py::arg("context") = py::none(),
886  .def_static("get_splat", PyDenseElementsAttribute::getSplat,
887  py::arg("shaped_type"), py::arg("element_attr"),
888  "Gets a DenseElementsAttr where all values are the same")
889  .def_property_readonly("is_splat",
890  [](PyDenseElementsAttribute &self) -> bool {
891  return mlirDenseElementsAttrIsSplat(self);
892  })
893  .def("get_splat_value",
894  [](PyDenseElementsAttribute &self) {
895  if (!mlirDenseElementsAttrIsSplat(self))
896  throw py::value_error(
897  "get_splat_value called on a non-splat attribute");
899  })
900  .def_buffer(&PyDenseElementsAttribute::accessBuffer);
901  }
902 
903 private:
904  static bool isUnsignedIntegerFormat(std::string_view format) {
905  if (format.empty())
906  return false;
907  char code = format[0];
908  return code == 'I' || code == 'B' || code == 'H' || code == 'L' ||
909  code == 'Q';
910  }
911 
912  static bool isSignedIntegerFormat(std::string_view format) {
913  if (format.empty())
914  return false;
915  char code = format[0];
916  return code == 'i' || code == 'b' || code == 'h' || code == 'l' ||
917  code == 'q';
918  }
919 
920  template <typename Type>
921  py::buffer_info bufferInfo(MlirType shapedType,
922  const char *explicitFormat = nullptr) {
923  intptr_t rank = mlirShapedTypeGetRank(shapedType);
924  // Prepare the data for the buffer_info.
925  // Buffer is configured for read-only access below.
926  Type *data = static_cast<Type *>(
927  const_cast<void *>(mlirDenseElementsAttrGetRawData(*this)));
928  // Prepare the shape for the buffer_info.
930  for (intptr_t i = 0; i < rank; ++i)
931  shape.push_back(mlirShapedTypeGetDimSize(shapedType, i));
932  // Prepare the strides for the buffer_info.
933  SmallVector<intptr_t, 4> strides;
934  if (mlirDenseElementsAttrIsSplat(*this)) {
935  // Splats are special, only the single value is stored.
936  strides.assign(rank, 0);
937  } else {
938  for (intptr_t i = 1; i < rank; ++i) {
939  intptr_t strideFactor = 1;
940  for (intptr_t j = i; j < rank; ++j)
941  strideFactor *= mlirShapedTypeGetDimSize(shapedType, j);
942  strides.push_back(sizeof(Type) * strideFactor);
943  }
944  strides.push_back(sizeof(Type));
945  }
946  std::string format;
947  if (explicitFormat) {
948  format = explicitFormat;
949  } else {
950  format = py::format_descriptor<Type>::format();
951  }
952  return py::buffer_info(data, sizeof(Type), format, rank, shape, strides,
953  /*readonly=*/true);
954  }
955 }; // namespace
956 
957 /// Refinement of the PyDenseElementsAttribute for attributes containing integer
958 /// (and boolean) values. Supports element access.
959 class PyDenseIntElementsAttribute
960  : public PyConcreteAttribute<PyDenseIntElementsAttribute,
961  PyDenseElementsAttribute> {
962 public:
963  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseIntElements;
964  static constexpr const char *pyClassName = "DenseIntElementsAttr";
966 
967  /// Returns the element at the given linear position. Asserts if the index is
968  /// out of range.
969  py::int_ dunderGetItem(intptr_t pos) {
970  if (pos < 0 || pos >= dunderLen()) {
971  throw py::index_error("attempt to access out of bounds element");
972  }
973 
974  MlirType type = mlirAttributeGetType(*this);
975  type = mlirShapedTypeGetElementType(type);
976  assert(mlirTypeIsAInteger(type) &&
977  "expected integer element type in dense int elements attribute");
978  // Dispatch element extraction to an appropriate C function based on the
979  // elemental type of the attribute. py::int_ is implicitly constructible
980  // from any C++ integral type and handles bitwidth correctly.
981  // TODO: consider caching the type properties in the constructor to avoid
982  // querying them on each element access.
983  unsigned width = mlirIntegerTypeGetWidth(type);
984  bool isUnsigned = mlirIntegerTypeIsUnsigned(type);
985  if (isUnsigned) {
986  if (width == 1) {
987  return mlirDenseElementsAttrGetBoolValue(*this, pos);
988  }
989  if (width == 8) {
990  return mlirDenseElementsAttrGetUInt8Value(*this, pos);
991  }
992  if (width == 16) {
993  return mlirDenseElementsAttrGetUInt16Value(*this, pos);
994  }
995  if (width == 32) {
996  return mlirDenseElementsAttrGetUInt32Value(*this, pos);
997  }
998  if (width == 64) {
999  return mlirDenseElementsAttrGetUInt64Value(*this, pos);
1000  }
1001  } else {
1002  if (width == 1) {
1003  return mlirDenseElementsAttrGetBoolValue(*this, pos);
1004  }
1005  if (width == 8) {
1006  return mlirDenseElementsAttrGetInt8Value(*this, pos);
1007  }
1008  if (width == 16) {
1009  return mlirDenseElementsAttrGetInt16Value(*this, pos);
1010  }
1011  if (width == 32) {
1012  return mlirDenseElementsAttrGetInt32Value(*this, pos);
1013  }
1014  if (width == 64) {
1015  return mlirDenseElementsAttrGetInt64Value(*this, pos);
1016  }
1017  }
1018  throw py::type_error("Unsupported integer type");
1019  }
1020 
1021  static void bindDerived(ClassTy &c) {
1022  c.def("__getitem__", &PyDenseIntElementsAttribute::dunderGetItem);
1023  }
1024 };
1025 
1026 class PyDenseResourceElementsAttribute
1027  : public PyConcreteAttribute<PyDenseResourceElementsAttribute> {
1028 public:
1029  static constexpr IsAFunctionTy isaFunction =
1031  static constexpr const char *pyClassName = "DenseResourceElementsAttr";
1033 
1034  static PyDenseResourceElementsAttribute
1035  getFromBuffer(py::buffer buffer, const std::string &name, const PyType &type,
1036  std::optional<size_t> alignment, bool isMutable,
1037  DefaultingPyMlirContext contextWrapper) {
1038  if (!mlirTypeIsAShaped(type)) {
1039  throw std::invalid_argument(
1040  "Constructing a DenseResourceElementsAttr requires a ShapedType.");
1041  }
1042 
1043  // Do not request any conversions as we must ensure to use caller
1044  // managed memory.
1045  int flags = PyBUF_STRIDES;
1046  std::unique_ptr<Py_buffer> view = std::make_unique<Py_buffer>();
1047  if (PyObject_GetBuffer(buffer.ptr(), view.get(), flags) != 0) {
1048  throw py::error_already_set();
1049  }
1050 
1051  // This scope releaser will only release if we haven't yet transferred
1052  // ownership.
1053  auto freeBuffer = llvm::make_scope_exit([&]() {
1054  if (view)
1055  PyBuffer_Release(view.get());
1056  });
1057 
1058  if (!PyBuffer_IsContiguous(view.get(), 'A')) {
1059  throw std::invalid_argument("Contiguous buffer is required.");
1060  }
1061 
1062  // Infer alignment to be the stride of one element if not explicit.
1063  size_t inferredAlignment;
1064  if (alignment)
1065  inferredAlignment = *alignment;
1066  else
1067  inferredAlignment = view->strides[view->ndim - 1];
1068 
1069  // The userData is a Py_buffer* that the deleter owns.
1070  auto deleter = [](void *userData, const void *data, size_t size,
1071  size_t align) {
1072  Py_buffer *ownedView = static_cast<Py_buffer *>(userData);
1073  PyBuffer_Release(ownedView);
1074  delete ownedView;
1075  };
1076 
1077  size_t rawBufferSize = view->len;
1078  MlirAttribute attr = mlirUnmanagedDenseResourceElementsAttrGet(
1079  type, toMlirStringRef(name), view->buf, rawBufferSize,
1080  inferredAlignment, isMutable, deleter, static_cast<void *>(view.get()));
1081  if (mlirAttributeIsNull(attr)) {
1082  throw std::invalid_argument(
1083  "DenseResourceElementsAttr could not be constructed from the given "
1084  "buffer. "
1085  "This may mean that the Python buffer layout does not match that "
1086  "MLIR expected layout and is a bug.");
1087  }
1088  view.release();
1089  return PyDenseResourceElementsAttribute(contextWrapper->getRef(), attr);
1090  }
1091 
1092  static void bindDerived(ClassTy &c) {
1093  c.def_static("get_from_buffer",
1094  PyDenseResourceElementsAttribute::getFromBuffer,
1095  py::arg("array"), py::arg("name"), py::arg("type"),
1096  py::arg("alignment") = py::none(),
1097  py::arg("is_mutable") = false, py::arg("context") = py::none(),
1099  }
1100 };
1101 
1102 class PyDictAttribute : public PyConcreteAttribute<PyDictAttribute> {
1103 public:
1104  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADictionary;
1105  static constexpr const char *pyClassName = "DictAttr";
1107  static constexpr GetTypeIDFunctionTy getTypeIdFunction =
1109 
1110  intptr_t dunderLen() { return mlirDictionaryAttrGetNumElements(*this); }
1111 
1112  bool dunderContains(const std::string &name) {
1113  return !mlirAttributeIsNull(
1115  }
1116 
1117  static void bindDerived(ClassTy &c) {
1118  c.def("__contains__", &PyDictAttribute::dunderContains);
1119  c.def("__len__", &PyDictAttribute::dunderLen);
1120  c.def_static(
1121  "get",
1122  [](py::dict attributes, DefaultingPyMlirContext context) {
1123  SmallVector<MlirNamedAttribute> mlirNamedAttributes;
1124  mlirNamedAttributes.reserve(attributes.size());
1125  for (auto &it : attributes) {
1126  auto &mlirAttr = it.second.cast<PyAttribute &>();
1127  auto name = it.first.cast<std::string>();
1128  mlirNamedAttributes.push_back(mlirNamedAttributeGet(
1130  toMlirStringRef(name)),
1131  mlirAttr));
1132  }
1133  MlirAttribute attr =
1134  mlirDictionaryAttrGet(context->get(), mlirNamedAttributes.size(),
1135  mlirNamedAttributes.data());
1136  return PyDictAttribute(context->getRef(), attr);
1137  },
1138  py::arg("value") = py::dict(), py::arg("context") = py::none(),
1139  "Gets an uniqued dict attribute");
1140  c.def("__getitem__", [](PyDictAttribute &self, const std::string &name) {
1141  MlirAttribute attr =
1143  if (mlirAttributeIsNull(attr))
1144  throw py::key_error("attempt to access a non-existent attribute");
1145  return attr;
1146  });
1147  c.def("__getitem__", [](PyDictAttribute &self, intptr_t index) {
1148  if (index < 0 || index >= self.dunderLen()) {
1149  throw py::index_error("attempt to access out of bounds attribute");
1150  }
1151  MlirNamedAttribute namedAttr = mlirDictionaryAttrGetElement(self, index);
1152  return PyNamedAttribute(
1153  namedAttr.attribute,
1154  std::string(mlirIdentifierStr(namedAttr.name).data));
1155  });
1156  }
1157 };
1158 
1159 /// Refinement of PyDenseElementsAttribute for attributes containing
1160 /// floating-point values. Supports element access.
1161 class PyDenseFPElementsAttribute
1162  : public PyConcreteAttribute<PyDenseFPElementsAttribute,
1163  PyDenseElementsAttribute> {
1164 public:
1165  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseFPElements;
1166  static constexpr const char *pyClassName = "DenseFPElementsAttr";
1168 
1169  py::float_ dunderGetItem(intptr_t pos) {
1170  if (pos < 0 || pos >= dunderLen()) {
1171  throw py::index_error("attempt to access out of bounds element");
1172  }
1173 
1174  MlirType type = mlirAttributeGetType(*this);
1175  type = mlirShapedTypeGetElementType(type);
1176  // Dispatch element extraction to an appropriate C function based on the
1177  // elemental type of the attribute. py::float_ is implicitly constructible
1178  // from float and double.
1179  // TODO: consider caching the type properties in the constructor to avoid
1180  // querying them on each element access.
1181  if (mlirTypeIsAF32(type)) {
1182  return mlirDenseElementsAttrGetFloatValue(*this, pos);
1183  }
1184  if (mlirTypeIsAF64(type)) {
1185  return mlirDenseElementsAttrGetDoubleValue(*this, pos);
1186  }
1187  throw py::type_error("Unsupported floating-point type");
1188  }
1189 
1190  static void bindDerived(ClassTy &c) {
1191  c.def("__getitem__", &PyDenseFPElementsAttribute::dunderGetItem);
1192  }
1193 };
1194 
1195 class PyTypeAttribute : public PyConcreteAttribute<PyTypeAttribute> {
1196 public:
1197  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAType;
1198  static constexpr const char *pyClassName = "TypeAttr";
1200  static constexpr GetTypeIDFunctionTy getTypeIdFunction =
1202 
1203  static void bindDerived(ClassTy &c) {
1204  c.def_static(
1205  "get",
1206  [](PyType value, DefaultingPyMlirContext context) {
1207  MlirAttribute attr = mlirTypeAttrGet(value.get());
1208  return PyTypeAttribute(context->getRef(), attr);
1209  },
1210  py::arg("value"), py::arg("context") = py::none(),
1211  "Gets a uniqued Type attribute");
1212  c.def_property_readonly("value", [](PyTypeAttribute &self) {
1213  return mlirTypeAttrGetValue(self.get());
1214  });
1215  }
1216 };
1217 
1218 /// Unit Attribute subclass. Unit attributes don't have values.
1219 class PyUnitAttribute : public PyConcreteAttribute<PyUnitAttribute> {
1220 public:
1221  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAUnit;
1222  static constexpr const char *pyClassName = "UnitAttr";
1224  static constexpr GetTypeIDFunctionTy getTypeIdFunction =
1226 
1227  static void bindDerived(ClassTy &c) {
1228  c.def_static(
1229  "get",
1230  [](DefaultingPyMlirContext context) {
1231  return PyUnitAttribute(context->getRef(),
1232  mlirUnitAttrGet(context->get()));
1233  },
1234  py::arg("context") = py::none(), "Create a Unit attribute.");
1235  }
1236 };
1237 
1238 /// Strided layout attribute subclass.
1239 class PyStridedLayoutAttribute
1240  : public PyConcreteAttribute<PyStridedLayoutAttribute> {
1241 public:
1242  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAStridedLayout;
1243  static constexpr const char *pyClassName = "StridedLayoutAttr";
1245  static constexpr GetTypeIDFunctionTy getTypeIdFunction =
1247 
1248  static void bindDerived(ClassTy &c) {
1249  c.def_static(
1250  "get",
1251  [](int64_t offset, const std::vector<int64_t> strides,
1253  MlirAttribute attr = mlirStridedLayoutAttrGet(
1254  ctx->get(), offset, strides.size(), strides.data());
1255  return PyStridedLayoutAttribute(ctx->getRef(), attr);
1256  },
1257  py::arg("offset"), py::arg("strides"), py::arg("context") = py::none(),
1258  "Gets a strided layout attribute.");
1259  c.def_static(
1260  "get_fully_dynamic",
1261  [](int64_t rank, DefaultingPyMlirContext ctx) {
1262  auto dynamic = mlirShapedTypeGetDynamicStrideOrOffset();
1263  std::vector<int64_t> strides(rank);
1264  std::fill(strides.begin(), strides.end(), dynamic);
1265  MlirAttribute attr = mlirStridedLayoutAttrGet(
1266  ctx->get(), dynamic, strides.size(), strides.data());
1267  return PyStridedLayoutAttribute(ctx->getRef(), attr);
1268  },
1269  py::arg("rank"), py::arg("context") = py::none(),
1270  "Gets a strided layout attribute with dynamic offset and strides of a "
1271  "given rank.");
1272  c.def_property_readonly(
1273  "offset",
1274  [](PyStridedLayoutAttribute &self) {
1275  return mlirStridedLayoutAttrGetOffset(self);
1276  },
1277  "Returns the value of the float point attribute");
1278  c.def_property_readonly(
1279  "strides",
1280  [](PyStridedLayoutAttribute &self) {
1281  intptr_t size = mlirStridedLayoutAttrGetNumStrides(self);
1282  std::vector<int64_t> strides(size);
1283  for (intptr_t i = 0; i < size; i++) {
1284  strides[i] = mlirStridedLayoutAttrGetStride(self, i);
1285  }
1286  return strides;
1287  },
1288  "Returns the value of the float point attribute");
1289  }
1290 };
1291 
1292 py::object denseArrayAttributeCaster(PyAttribute &pyAttribute) {
1293  if (PyDenseBoolArrayAttribute::isaFunction(pyAttribute))
1294  return py::cast(PyDenseBoolArrayAttribute(pyAttribute));
1295  if (PyDenseI8ArrayAttribute::isaFunction(pyAttribute))
1296  return py::cast(PyDenseI8ArrayAttribute(pyAttribute));
1297  if (PyDenseI16ArrayAttribute::isaFunction(pyAttribute))
1298  return py::cast(PyDenseI16ArrayAttribute(pyAttribute));
1299  if (PyDenseI32ArrayAttribute::isaFunction(pyAttribute))
1300  return py::cast(PyDenseI32ArrayAttribute(pyAttribute));
1301  if (PyDenseI64ArrayAttribute::isaFunction(pyAttribute))
1302  return py::cast(PyDenseI64ArrayAttribute(pyAttribute));
1303  if (PyDenseF32ArrayAttribute::isaFunction(pyAttribute))
1304  return py::cast(PyDenseF32ArrayAttribute(pyAttribute));
1305  if (PyDenseF64ArrayAttribute::isaFunction(pyAttribute))
1306  return py::cast(PyDenseF64ArrayAttribute(pyAttribute));
1307  std::string msg =
1308  std::string("Can't cast unknown element type DenseArrayAttr (") +
1309  std::string(py::repr(py::cast(pyAttribute))) + ")";
1310  throw py::cast_error(msg);
1311 }
1312 
1313 py::object denseIntOrFPElementsAttributeCaster(PyAttribute &pyAttribute) {
1314  if (PyDenseFPElementsAttribute::isaFunction(pyAttribute))
1315  return py::cast(PyDenseFPElementsAttribute(pyAttribute));
1316  if (PyDenseIntElementsAttribute::isaFunction(pyAttribute))
1317  return py::cast(PyDenseIntElementsAttribute(pyAttribute));
1318  std::string msg =
1319  std::string(
1320  "Can't cast unknown element type DenseIntOrFPElementsAttr (") +
1321  std::string(py::repr(py::cast(pyAttribute))) + ")";
1322  throw py::cast_error(msg);
1323 }
1324 
1325 py::object integerOrBoolAttributeCaster(PyAttribute &pyAttribute) {
1326  if (PyBoolAttribute::isaFunction(pyAttribute))
1327  return py::cast(PyBoolAttribute(pyAttribute));
1328  if (PyIntegerAttribute::isaFunction(pyAttribute))
1329  return py::cast(PyIntegerAttribute(pyAttribute));
1330  std::string msg =
1331  std::string("Can't cast unknown element type DenseArrayAttr (") +
1332  std::string(py::repr(py::cast(pyAttribute))) + ")";
1333  throw py::cast_error(msg);
1334 }
1335 
1336 py::object symbolRefOrFlatSymbolRefAttributeCaster(PyAttribute &pyAttribute) {
1337  if (PyFlatSymbolRefAttribute::isaFunction(pyAttribute))
1338  return py::cast(PyFlatSymbolRefAttribute(pyAttribute));
1339  if (PySymbolRefAttribute::isaFunction(pyAttribute))
1340  return py::cast(PySymbolRefAttribute(pyAttribute));
1341  std::string msg = std::string("Can't cast unknown SymbolRef attribute (") +
1342  std::string(py::repr(py::cast(pyAttribute))) + ")";
1343  throw py::cast_error(msg);
1344 }
1345 
1346 } // namespace
1347 
1348 void mlir::python::populateIRAttributes(py::module &m) {
1349  PyAffineMapAttribute::bind(m);
1350 
1351  PyDenseBoolArrayAttribute::bind(m);
1352  PyDenseBoolArrayAttribute::PyDenseArrayIterator::bind(m);
1353  PyDenseI8ArrayAttribute::bind(m);
1354  PyDenseI8ArrayAttribute::PyDenseArrayIterator::bind(m);
1355  PyDenseI16ArrayAttribute::bind(m);
1356  PyDenseI16ArrayAttribute::PyDenseArrayIterator::bind(m);
1357  PyDenseI32ArrayAttribute::bind(m);
1358  PyDenseI32ArrayAttribute::PyDenseArrayIterator::bind(m);
1359  PyDenseI64ArrayAttribute::bind(m);
1360  PyDenseI64ArrayAttribute::PyDenseArrayIterator::bind(m);
1361  PyDenseF32ArrayAttribute::bind(m);
1362  PyDenseF32ArrayAttribute::PyDenseArrayIterator::bind(m);
1363  PyDenseF64ArrayAttribute::bind(m);
1364  PyDenseF64ArrayAttribute::PyDenseArrayIterator::bind(m);
1367  pybind11::cpp_function(denseArrayAttributeCaster));
1368 
1369  PyArrayAttribute::bind(m);
1370  PyArrayAttribute::PyArrayAttributeIterator::bind(m);
1371  PyBoolAttribute::bind(m);
1372  PyDenseElementsAttribute::bind(m);
1373  PyDenseFPElementsAttribute::bind(m);
1374  PyDenseIntElementsAttribute::bind(m);
1377  pybind11::cpp_function(denseIntOrFPElementsAttributeCaster));
1378  PyDenseResourceElementsAttribute::bind(m);
1379 
1380  PyDictAttribute::bind(m);
1381  PySymbolRefAttribute::bind(m);
1384  pybind11::cpp_function(symbolRefOrFlatSymbolRefAttributeCaster));
1385 
1386  PyFlatSymbolRefAttribute::bind(m);
1387  PyOpaqueAttribute::bind(m);
1388  PyFloatAttribute::bind(m);
1389  PyIntegerAttribute::bind(m);
1390  PyStringAttribute::bind(m);
1391  PyTypeAttribute::bind(m);
1394  pybind11::cpp_function(integerOrBoolAttributeCaster));
1395  PyUnitAttribute::bind(m);
1396 
1397  PyStridedLayoutAttribute::bind(m);
1398 }
static const char kDenseElementsAttrGetDocstring[]
static const char kDenseResourceElementsAttrGetFromBufferDocstring[]
static MlirStringRef toMlirStringRef(const std::string &s)
Definition: IRCore.cpp:204
static LogicalResult nextIndex(ArrayRef< int64_t > shape, MutableArrayRef< int64_t > index)
Walks over the indices of the elements of a tensor of a given shape by updating index in place to the...
std::string str() const
Converts the diagnostic to a string.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
PyMlirContextRef & getContext()
Accesses the context reference.
Definition: IRModule.h:303
Used in function arguments when None should resolve to the current context manager set instance.
Definition: IRModule.h:510
Used in function arguments when None should resolve to the current context manager set instance.
Definition: IRModule.h:284
static PyMlirContext & resolve()
Definition: IRCore.cpp:764
ReferrentTy * get() const
Definition: PybindUtils.h:47
MlirAffineMap get() const
Definition: IRModule.h:1187
Wrapper around the generic MlirAttribute.
Definition: IRModule.h:993
MlirAttribute get() const
Definition: IRModule.h:999
CRTP base classes for Python attributes that subclass Attribute and should be castable from it (i....
Definition: IRModule.h:1043
pybind11::class_< DerivedTy, BaseTy > ClassTy
Definition: IRModule.h:1048
void registerTypeCaster(MlirTypeID mlirTypeID, pybind11::function typeCaster, bool replace=false)
Adds a user-friendly type caster.
Definition: IRModule.cpp:81
static PyGlobals & get()
Most code should get the globals via this static accessor.
Definition: Globals.h:34
MlirContext get()
Accesses the underlying MlirContext.
Definition: IRModule.h:184
static PyMlirContextRef forContext(MlirContext context)
Returns a context reference for the singleton PyMlirContext wrapper for the given context.
Definition: IRCore.cpp:613
Represents a Python MlirNamedAttr, carrying an optional owned name.
Definition: IRModule.h:1017
Wrapper around the generic MlirType.
Definition: IRModule.h:871
MlirType get() const
Definition: IRModule.h:877
mlir::Diagnostic & unwrap(MlirDiagnostic diagnostic)
Definition: Diagnostics.h:19
MLIR_CAPI_EXPORTED MlirAttribute mlirAffineMapAttrGet(MlirAffineMap map)
Creates an affine map attribute wrapping the given map.
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseFPElements(MlirAttribute attr)
MLIR_CAPI_EXPORTED MlirAttribute mlirOpaqueAttrGet(MlirContext ctx, MlirStringRef dialectNamespace, intptr_t dataLength, const char *data, MlirType type)
Creates an opaque attribute in the given context associated with the dialect identified by its namesp...
MLIR_CAPI_EXPORTED MlirAttribute mlirFloatAttrDoubleGetChecked(MlirLocation loc, MlirType type, double value)
Same as "mlirFloatAttrDoubleGet", but if the type is not valid for a construction of a FloatAttr,...
MLIR_CAPI_EXPORTED int16_t mlirDenseI16ArrayGetElement(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED bool mlirAttributeIsAStridedLayout(MlirAttribute attr)
MLIR_CAPI_EXPORTED uint8_t mlirDenseElementsAttrGetUInt8Value(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED int64_t mlirStridedLayoutAttrGetOffset(MlirAttribute attr)
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseI64Array(MlirAttribute attr)
MLIR_CAPI_EXPORTED int64_t mlirStridedLayoutAttrGetStride(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED int8_t mlirDenseElementsAttrGetInt8Value(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED MlirAttribute mlirStridedLayoutAttrGet(MlirContext ctx, int64_t offset, intptr_t numStrides, const int64_t *strides)
MLIR_CAPI_EXPORTED MlirTypeID mlirStringAttrGetTypeID(void)
Returns the typeID of a String attribute.
MLIR_CAPI_EXPORTED bool mlirAttributeIsAUnit(MlirAttribute attr)
Checks whether the given attribute is a unit attribute.
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseElements(MlirAttribute attr)
Checks whether the given attribute is a dense elements attribute.
MLIR_CAPI_EXPORTED bool mlirAttributeIsAAffineMap(MlirAttribute attr)
Checks whether the given attribute is an affine map attribute.
MLIR_CAPI_EXPORTED int32_t mlirDenseI32ArrayGetElement(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED double mlirDenseF64ArrayGetElement(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED MlirAttribute mlirFlatSymbolRefAttrGet(MlirContext ctx, MlirStringRef symbol)
Creates a flat symbol reference attribute in the given context referencing a symbol identified by the...
MLIR_CAPI_EXPORTED MlirTypeID mlirStridedLayoutAttrGetTypeID(void)
Returns the typeID of a StridedLayout attribute.
MLIR_CAPI_EXPORTED MlirTypeID mlirIntegerAttrGetTypeID(void)
Returns the typeID of an Integer attribute.
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseResourceElements(MlirAttribute attr)
MLIR_CAPI_EXPORTED int16_t mlirDenseElementsAttrGetInt16Value(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED MlirStringRef mlirSymbolRefAttrGetRootReference(MlirAttribute attr)
Returns the string reference to the root referenced symbol.
MLIR_CAPI_EXPORTED bool mlirAttributeIsAType(MlirAttribute attr)
Checks whether the given attribute is a type attribute.
MLIR_CAPI_EXPORTED MlirTypeID mlirDenseIntOrFPElementsAttrGetTypeID(void)
Returns the typeID of an DenseIntOrFPElements attribute.
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseIntElements(MlirAttribute attr)
MLIR_CAPI_EXPORTED bool mlirAttributeIsAArray(MlirAttribute attr)
Checks whether the given attribute is an array attribute.
MLIR_CAPI_EXPORTED bool mlirAttributeIsAInteger(MlirAttribute attr)
Checks whether the given attribute is an integer attribute.
MLIR_CAPI_EXPORTED intptr_t mlirDictionaryAttrGetNumElements(MlirAttribute attr)
Returns the number of attributes contained in a dictionary attribute.
MLIR_CAPI_EXPORTED uint16_t mlirDenseElementsAttrGetUInt16Value(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED uint64_t mlirDenseElementsAttrGetUInt64Value(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED bool mlirBoolAttrGetValue(MlirAttribute attr)
Returns the value stored in the given bool attribute.
MLIR_CAPI_EXPORTED int64_t mlirDenseI64ArrayGetElement(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED MlirAttribute mlirIntegerAttrGet(MlirType type, int64_t value)
Creates an integer attribute of the given type with the given integer value.
MLIR_CAPI_EXPORTED bool mlirDenseElementsAttrGetBoolValue(MlirAttribute attr, intptr_t pos)
Returns the pos-th value (flat contiguous indexing) of a specific type contained by the given dense e...
MLIR_CAPI_EXPORTED MlirAttribute mlirDictionaryAttrGet(MlirContext ctx, intptr_t numElements, MlirNamedAttribute const *elements)
Creates a dictionary attribute containing the given list of elements in the provided context.
MLIR_CAPI_EXPORTED MlirAttribute mlirUnmanagedDenseResourceElementsAttrGet(MlirType shapedType, MlirStringRef name, void *data, size_t dataLength, size_t dataAlignment, bool dataIsMutable, void(*deleter)(void *userData, const void *data, size_t size, size_t align), void *userData)
Unlike the typed accessors below, constructs the attribute with a raw data buffer and no type/alignme...
MLIR_CAPI_EXPORTED bool mlirAttributeIsABool(MlirAttribute attr)
Checks whether the given attribute is a bool attribute.
MLIR_CAPI_EXPORTED bool mlirDenseBoolArrayGetElement(MlirAttribute attr, intptr_t pos)
Get an element of a dense array.
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseI64ArrayGet(MlirContext ctx, intptr_t size, int64_t const *values)
MLIR_CAPI_EXPORTED MlirTypeID mlirAffineMapAttrGetTypeID(void)
Returns the typeID of an AffineMap attribute.
MLIR_CAPI_EXPORTED MlirAttribute mlirSymbolRefAttrGetNestedReference(MlirAttribute attr, intptr_t pos)
Returns pos-th reference nested in the given symbol reference attribute.
MLIR_CAPI_EXPORTED MlirTypeID mlirArrayAttrGetTypeID(void)
Returns the typeID of an Array attribute.
MLIR_CAPI_EXPORTED float mlirDenseF32ArrayGetElement(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseF64ArrayGet(MlirContext ctx, intptr_t size, double const *values)
MLIR_CAPI_EXPORTED int64_t mlirIntegerAttrGetValueInt(MlirAttribute attr)
Returns the value stored in the given integer attribute, assuming the value is of signless type and f...
MLIR_CAPI_EXPORTED intptr_t mlirSymbolRefAttrGetNumNestedReferences(MlirAttribute attr)
Returns the number of references nested in the given symbol reference attribute.
MLIR_CAPI_EXPORTED MlirType mlirTypeAttrGetValue(MlirAttribute attr)
Returns the type stored in the given type attribute.
MLIR_CAPI_EXPORTED bool mlirDenseElementsAttrIsSplat(MlirAttribute attr)
Checks whether the given dense elements attribute contains a single replicated value (splat).
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseBoolArray(MlirAttribute attr)
Checks whether the given attribute is a dense array attribute.
MLIR_CAPI_EXPORTED MlirStringRef mlirOpaqueAttrGetData(MlirAttribute attr)
Returns the raw data as a string reference.
MLIR_CAPI_EXPORTED MlirAttribute mlirAttributeGetNull(void)
Returns an empty attribute.
MLIR_CAPI_EXPORTED MlirAttribute mlirBoolAttrGet(MlirContext ctx, int value)
Creates a bool attribute in the given context with the given value.
MLIR_CAPI_EXPORTED MlirTypeID mlirFloatAttrGetTypeID(void)
Returns the typeID of a Float attribute.
MLIR_CAPI_EXPORTED int64_t mlirIntegerAttrGetValueSInt(MlirAttribute attr)
Returns the value stored in the given integer attribute, assuming the value is of signed type and fit...
MLIR_CAPI_EXPORTED int8_t mlirDenseI8ArrayGetElement(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseI32ArrayGet(MlirContext ctx, intptr_t size, int32_t const *values)
MLIR_CAPI_EXPORTED int64_t mlirDenseElementsAttrGetInt64Value(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED MlirNamedAttribute mlirDictionaryAttrGetElement(MlirAttribute attr, intptr_t pos)
Returns pos-th element of the given dictionary attribute.
MLIR_CAPI_EXPORTED MlirTypeID mlirUnitAttrGetTypeID(void)
Returns the typeID of a Unit attribute.
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseF32ArrayGet(MlirContext ctx, intptr_t size, float const *values)
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseBoolArrayGet(MlirContext ctx, intptr_t size, int const *values)
Create a dense array attribute with the given elements.
MLIR_CAPI_EXPORTED bool mlirAttributeIsAOpaque(MlirAttribute attr)
Checks whether the given attribute is an opaque attribute.
MLIR_CAPI_EXPORTED MlirAttribute mlirArrayAttrGetElement(MlirAttribute attr, intptr_t pos)
Returns pos-th element stored in the given array attribute.
MLIR_CAPI_EXPORTED MlirAttribute mlirDictionaryAttrGetElementByName(MlirAttribute attr, MlirStringRef name)
Returns the dictionary attribute element with the given name or NULL if the given name does not exist...
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseF32Array(MlirAttribute attr)
MLIR_CAPI_EXPORTED MlirTypeID mlirSymbolRefAttrGetTypeID(void)
Returns the typeID of an SymbolRef attribute.
MLIR_CAPI_EXPORTED MlirTypeID mlirDenseArrayAttrGetTypeID(void)
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseElementsAttrGetSplatValue(MlirAttribute attr)
Returns the single replicated value (splat) of a specific type contained by the given dense elements ...
MLIR_CAPI_EXPORTED bool mlirAttributeIsASymbolRef(MlirAttribute attr)
Checks whether the given attribute is a symbol reference attribute.
MLIR_CAPI_EXPORTED float mlirDenseElementsAttrGetFloatValue(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED bool mlirAttributeIsAString(MlirAttribute attr)
Checks whether the given attribute is a string attribute.
MLIR_CAPI_EXPORTED int64_t mlirElementsAttrGetNumElements(MlirAttribute attr)
Gets the total number of elements in the given elements attribute.
MLIR_CAPI_EXPORTED MlirStringRef mlirOpaqueAttrGetDialectNamespace(MlirAttribute attr)
Returns the namespace of the dialect with which the given opaque attribute is associated.
MLIR_CAPI_EXPORTED bool mlirAttributeIsADictionary(MlirAttribute attr)
Checks whether the given attribute is a dictionary attribute.
MLIR_CAPI_EXPORTED int32_t mlirDenseElementsAttrGetInt32Value(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED MlirStringRef mlirStringAttrGetValue(MlirAttribute attr)
Returns the attribute values as a string reference.
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseI16ArrayGet(MlirContext ctx, intptr_t size, int16_t const *values)
MLIR_CAPI_EXPORTED MlirTypeID mlirOpaqueAttrGetTypeID(void)
Returns the typeID of an Opaque attribute.
MLIR_CAPI_EXPORTED double mlirFloatAttrGetValueDouble(MlirAttribute attr)
Returns the value stored in the given floating point attribute, interpreting the value as double.
MLIR_CAPI_EXPORTED uint64_t mlirIntegerAttrGetValueUInt(MlirAttribute attr)
Returns the value stored in the given integer attribute, assuming the value is of unsigned type and f...
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseI8ArrayGet(MlirContext ctx, intptr_t size, int8_t const *values)
MLIR_CAPI_EXPORTED MlirAttribute mlirUnitAttrGet(MlirContext ctx)
Creates a unit attribute in the given context.
MLIR_CAPI_EXPORTED double mlirDenseElementsAttrGetDoubleValue(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED intptr_t mlirStridedLayoutAttrGetNumStrides(MlirAttribute attr)
MLIR_CAPI_EXPORTED MlirAttribute mlirFloatAttrDoubleGet(MlirContext ctx, MlirType type, double value)
Creates a floating point attribute in the given context with the given double value and double-precis...
MLIR_CAPI_EXPORTED MlirAttribute mlirArrayAttrGet(MlirContext ctx, intptr_t numElements, MlirAttribute const *elements)
Creates an array element containing the given list of elements in the given context.
MLIR_CAPI_EXPORTED const void * mlirDenseElementsAttrGetRawData(MlirAttribute attr)
Returns the raw data of the given dense elements attribute.
MLIR_CAPI_EXPORTED intptr_t mlirDenseArrayGetNumElements(MlirAttribute attr)
Get the size of a dense array.
MLIR_CAPI_EXPORTED bool mlirAttributeIsAFloat(MlirAttribute attr)
Checks whether the given attribute is a floating point attribute.
MLIR_CAPI_EXPORTED MlirAttribute mlirSymbolRefAttrGet(MlirContext ctx, MlirStringRef symbol, intptr_t numReferences, MlirAttribute const *references)
Creates a symbol reference attribute in the given context referencing a symbol identified by the give...
MLIR_CAPI_EXPORTED MlirTypeID mlirTypeAttrGetTypeID(void)
Returns the typeID of a Type attribute.
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseElementsAttrSplatGet(MlirType shapedType, MlirAttribute element)
Creates a dense elements attribute with the given Shaped type containing a single replicated element ...
MLIR_CAPI_EXPORTED MlirTypeID mlirDictionaryAttrGetTypeID(void)
Returns the typeID of a Dictionary attribute.
MLIR_CAPI_EXPORTED MlirAttribute mlirStringAttrGet(MlirContext ctx, MlirStringRef str)
Creates a string attribute in the given context containing the given string.
MLIR_CAPI_EXPORTED MlirAttribute mlirTypeAttrGet(MlirType type)
Creates a type attribute wrapping the given type in the same context as the type.
MLIR_CAPI_EXPORTED intptr_t mlirArrayAttrGetNumElements(MlirAttribute attr)
Returns the number of elements stored in the given array attribute.
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseElementsAttrRawBufferGet(MlirType shapedType, size_t rawBufferSize, const void *rawBuffer)
Creates a dense elements attribute with the given Shaped type and elements populated from a packed,...
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseI32Array(MlirAttribute attr)
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseI8Array(MlirAttribute attr)
MLIR_CAPI_EXPORTED MlirAttribute mlirStringAttrTypedGet(MlirType type, MlirStringRef str)
Creates a string attribute in the given context containing the given string.
MLIR_CAPI_EXPORTED bool mlirAttributeIsAFlatSymbolRef(MlirAttribute attr)
Checks whether the given attribute is a flat symbol reference attribute.
MLIR_CAPI_EXPORTED MlirStringRef mlirFlatSymbolRefAttrGetValue(MlirAttribute attr)
Returns the referenced symbol as a string reference.
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseI16Array(MlirAttribute attr)
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseF64Array(MlirAttribute attr)
MLIR_CAPI_EXPORTED uint32_t mlirDenseElementsAttrGetUInt32Value(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED MlirType mlirRankedTensorTypeGet(intptr_t rank, const int64_t *shape, MlirType elementType, MlirAttribute encoding)
Creates a tensor type of a fixed rank with the given shape, element type, and optional encoding in th...
MLIR_CAPI_EXPORTED bool mlirIntegerTypeIsSignless(MlirType type)
Checks whether the given integer type is signless.
MLIR_CAPI_EXPORTED bool mlirTypeIsAInteger(MlirType type)
Checks whether the given type is an integer type.
MLIR_CAPI_EXPORTED int64_t mlirShapedTypeGetDimSize(MlirType type, intptr_t dim)
Returns the dim-th dimension of the given ranked shaped type.
MLIR_CAPI_EXPORTED MlirType mlirIntegerTypeGet(MlirContext ctx, unsigned bitwidth)
Creates a signless integer type of the given bitwidth in the context.
MLIR_CAPI_EXPORTED bool mlirIntegerTypeIsUnsigned(MlirType type)
Checks whether the given integer type is unsigned.
MLIR_CAPI_EXPORTED unsigned mlirIntegerTypeGetWidth(MlirType type)
Returns the bitwidth of an integer type.
MLIR_CAPI_EXPORTED int64_t mlirShapedTypeGetRank(MlirType type)
Returns the rank of the given ranked shaped type.
MLIR_CAPI_EXPORTED MlirType mlirF64TypeGet(MlirContext ctx)
Creates a f64 type in the given context.
MLIR_CAPI_EXPORTED MlirType mlirIntegerTypeSignedGet(MlirContext ctx, unsigned bitwidth)
Creates a signed integer type of the given bitwidth in the context.
MLIR_CAPI_EXPORTED MlirType mlirF16TypeGet(MlirContext ctx)
Creates an f16 type in the given context.
MLIR_CAPI_EXPORTED bool mlirTypeIsAF64(MlirType type)
Checks whether the given type is an f64 type.
MLIR_CAPI_EXPORTED bool mlirTypeIsAF16(MlirType type)
Checks whether the given type is an f16 type.
MLIR_CAPI_EXPORTED bool mlirIntegerTypeIsSigned(MlirType type)
Checks whether the given integer type is signed.
MLIR_CAPI_EXPORTED MlirType mlirShapedTypeGetElementType(MlirType type)
Returns the element type of the shaped type.
MLIR_CAPI_EXPORTED bool mlirShapedTypeHasStaticShape(MlirType type)
Checks whether the given shaped type has a static shape.
MLIR_CAPI_EXPORTED MlirType mlirF32TypeGet(MlirContext ctx)
Creates an f32 type in the given context.
MLIR_CAPI_EXPORTED bool mlirTypeIsAShaped(MlirType type)
Checks whether the given type is a Shaped type.
MLIR_CAPI_EXPORTED MlirType mlirIntegerTypeUnsignedGet(MlirContext ctx, unsigned bitwidth)
Creates an unsigned integer type of the given bitwidth in the context.
MLIR_CAPI_EXPORTED bool mlirTypeIsAF32(MlirType type)
Checks whether the given type is an f32 type.
MLIR_CAPI_EXPORTED bool mlirTypeIsAIndex(MlirType type)
Checks whether the given type is an index type.
MLIR_CAPI_EXPORTED int64_t mlirShapedTypeGetDynamicStrideOrOffset(void)
Returns the value indicating a dynamic stride or offset in a shaped type.
static bool mlirAttributeIsNull(MlirAttribute attr)
Checks whether an attribute is null.
Definition: IR.h:1019
MLIR_CAPI_EXPORTED MlirNamedAttribute mlirNamedAttributeGet(MlirIdentifier name, MlirAttribute attr)
Associates an attribute with the name. Takes ownership of neither.
Definition: IR.cpp:1100
MLIR_CAPI_EXPORTED MlirStringRef mlirIdentifierStr(MlirIdentifier ident)
Gets the string value of the identifier.
Definition: IR.cpp:1121
MLIR_CAPI_EXPORTED MlirType mlirAttributeGetType(MlirAttribute attribute)
Gets the type of this attribute.
Definition: IR.cpp:1073
MLIR_CAPI_EXPORTED MlirContext mlirTypeGetContext(MlirType type)
Gets the context that a type was created with.
Definition: IR.cpp:1038
MLIR_CAPI_EXPORTED bool mlirTypeEqual(MlirType t1, MlirType t2)
Checks if two types are equal.
Definition: IR.cpp:1050
MLIR_CAPI_EXPORTED MlirContext mlirAttributeGetContext(MlirAttribute attribute)
Gets the context that an attribute was created with.
Definition: IR.cpp:1069
MLIR_CAPI_EXPORTED MlirIdentifier mlirIdentifierGet(MlirContext context, MlirStringRef str)
Gets an identifier with the given string value.
Definition: IR.cpp:1109
static MlirStringRef mlirStringRefCreate(const char *str, size_t length)
Constructs a string reference from the pointer and length.
Definition: Support.h:82
void populateIRAttributes(pybind11::module &m)
Include the generated interface declarations.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
Named MLIR attribute.
Definition: IR.h:76
MlirAttribute attribute
Definition: IR.h:78
MlirIdentifier name
Definition: IR.h:77
A pointer to a sized fragment of a string, not necessarily null-terminated.
Definition: Support.h:73
const char * data
Pointer to the first symbol.
Definition: Support.h:74
size_t length
Length of the fragment.
Definition: Support.h:75
Custom exception that allows access to error diagnostic information.
Definition: IRModule.h:1275
RAII object that captures any error diagnostics emitted to the provided context.
Definition: IRModule.h:419
std::vector< PyDiagnostic::DiagnosticInfo > take()
Definition: IRModule.h:429
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.