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