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