MLIR  16.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 <utility>
10 
11 #include "IRModule.h"
12 
13 #include "PybindUtils.h"
14 
16 #include "mlir-c/BuiltinTypes.h"
17 
18 namespace py = pybind11;
19 using namespace mlir;
20 using namespace mlir::python;
21 
22 using llvm::Optional;
23 using llvm::SmallVector;
24 using llvm::Twine;
25 
26 //------------------------------------------------------------------------------
27 // Docstrings (trivial, non-duplicated docstrings are included inline).
28 //------------------------------------------------------------------------------
29 
30 static const char kDenseElementsAttrGetDocstring[] =
31  R"(Gets a DenseElementsAttr from a Python buffer or array.
32 
33 When `type` is not provided, then some limited type inferencing is done based
34 on the buffer format. Support presently exists for 8/16/32/64 signed and
35 unsigned integers and float16/float32/float64. DenseElementsAttrs of these
36 types can also be converted back to a corresponding buffer.
37 
38 For conversions outside of these types, a `type=` must be explicitly provided
39 and the buffer contents must be bit-castable to the MLIR internal
40 representation:
41 
42  * Integer types (except for i1): the buffer must be byte aligned to the
43  next byte boundary.
44  * Floating point types: Must be bit-castable to the given floating point
45  size.
46  * i1 (bool): Bit packed into 8bit words where the bit pattern matches a
47  row major ordering. An arbitrary Numpy `bool_` array can be bit packed to
48  this specification with: `np.packbits(ary, axis=None, bitorder='little')`.
49 
50 If a single element buffer is passed (or for i1, a single byte with value 0
51 or 255), then a splat will be created.
52 
53 Args:
54  array: The array or buffer to convert.
55  signless: If inferring an appropriate MLIR type, use signless types for
56  integers (defaults True).
57  type: Skips inference of the MLIR element type and uses this instead. The
58  storage size must be consistent with the actual contents of the buffer.
59  shape: Overrides the shape of the buffer when constructing the MLIR
60  shaped type. This is needed when the physical and logical shape differ (as
61  for i1).
62  context: Explicit context, if not from context manager.
63 
64 Returns:
65  DenseElementsAttr on success.
66 
67 Raises:
68  ValueError: If the type of the buffer or array cannot be matched to an MLIR
69  type or if the buffer does not meet expectations.
70 )";
71 
72 namespace {
73 
74 static MlirStringRef toMlirStringRef(const std::string &s) {
75  return mlirStringRefCreate(s.data(), s.size());
76 }
77 
78 class PyAffineMapAttribute : public PyConcreteAttribute<PyAffineMapAttribute> {
79 public:
80  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAAffineMap;
81  static constexpr const char *pyClassName = "AffineMapAttr";
83 
84  static void bindDerived(ClassTy &c) {
85  c.def_static(
86  "get",
87  [](PyAffineMap &affineMap) {
88  MlirAttribute attr = mlirAffineMapAttrGet(affineMap.get());
89  return PyAffineMapAttribute(affineMap.getContext(), attr);
90  },
91  py::arg("affine_map"), "Gets an attribute wrapping an AffineMap.");
92  }
93 };
94 
95 template <typename T>
96 static T pyTryCast(py::handle object) {
97  try {
98  return object.cast<T>();
99  } catch (py::cast_error &err) {
100  std::string msg =
101  std::string(
102  "Invalid attribute when attempting to create an ArrayAttribute (") +
103  err.what() + ")";
104  throw py::cast_error(msg);
105  } catch (py::reference_cast_error &err) {
106  std::string msg = std::string("Invalid attribute (None?) when attempting "
107  "to create an ArrayAttribute (") +
108  err.what() + ")";
109  throw py::cast_error(msg);
110  }
111 }
112 
113 /// A python-wrapped dense array attribute with an element type and a derived
114 /// implementation class.
115 template <typename EltTy, typename DerivedT>
116 class PyDenseArrayAttribute
117  : public PyConcreteAttribute<PyDenseArrayAttribute<EltTy, DerivedT>> {
118 public:
119  static constexpr typename PyConcreteAttribute<
120  PyDenseArrayAttribute<EltTy, DerivedT>>::IsAFunctionTy isaFunction =
121  DerivedT::isaFunction;
122  static constexpr const char *pyClassName = DerivedT::pyClassName;
123  using PyConcreteAttribute<
124  PyDenseArrayAttribute<EltTy, DerivedT>>::PyConcreteAttribute;
125 
126  /// Iterator over the integer elements of a dense array.
127  class PyDenseArrayIterator {
128  public:
129  PyDenseArrayIterator(PyAttribute attr) : attr(attr) {}
130 
131  /// Return a copy of the iterator.
132  PyDenseArrayIterator dunderIter() { return *this; }
133 
134  /// Return the next element.
135  EltTy dunderNext() {
136  // Throw if the index has reached the end.
137  if (nextIndex >= mlirDenseArrayGetNumElements(attr.get()))
138  throw py::stop_iteration();
139  return DerivedT::getElement(attr.get(), nextIndex++);
140  }
141 
142  /// Bind the iterator class.
143  static void bind(py::module &m) {
144  py::class_<PyDenseArrayIterator>(m, DerivedT::pyIteratorName,
145  py::module_local())
146  .def("__iter__", &PyDenseArrayIterator::dunderIter)
147  .def("__next__", &PyDenseArrayIterator::dunderNext);
148  }
149 
150  private:
151  /// The referenced dense array attribute.
152  PyAttribute attr;
153  /// The next index to read.
154  int nextIndex = 0;
155  };
156 
157  /// Get the element at the given index.
158  EltTy getItem(intptr_t i) { return DerivedT::getElement(*this, i); }
159 
160  /// Bind the attribute class.
161  static void bindDerived(typename PyConcreteAttribute<
162  PyDenseArrayAttribute<EltTy, DerivedT>>::ClassTy &c) {
163  // Bind the constructor.
164  c.def_static(
165  "get",
166  [](const std::vector<EltTy> &values, DefaultingPyMlirContext ctx) {
167  MlirAttribute attr =
168  DerivedT::getAttribute(ctx->get(), values.size(), values.data());
169  return PyDenseArrayAttribute<EltTy, DerivedT>(ctx->getRef(), attr);
170  },
171  py::arg("values"), py::arg("context") = py::none(),
172  "Gets a uniqued dense array attribute");
173  // Bind the array methods.
174  c.def("__getitem__",
175  [](PyDenseArrayAttribute<EltTy, DerivedT> &arr, intptr_t i) {
176  if (i >= mlirDenseArrayGetNumElements(arr))
177  throw py::index_error("DenseArray index out of range");
178  return arr.getItem(i);
179  });
180  c.def("__len__", [](const PyDenseArrayAttribute<EltTy, DerivedT> &arr) {
181  return mlirDenseArrayGetNumElements(arr);
182  });
183  c.def("__iter__", [](const PyDenseArrayAttribute<EltTy, DerivedT> &arr) {
184  return PyDenseArrayIterator(arr);
185  });
186  c.def("__add__", [](PyDenseArrayAttribute<EltTy, DerivedT> &arr,
187  py::list extras) {
188  std::vector<EltTy> values;
189  intptr_t numOldElements = mlirDenseArrayGetNumElements(arr);
190  values.reserve(numOldElements + py::len(extras));
191  for (intptr_t i = 0; i < numOldElements; ++i)
192  values.push_back(arr.getItem(i));
193  for (py::handle attr : extras)
194  values.push_back(pyTryCast<EltTy>(attr));
195  MlirAttribute attr = DerivedT::getAttribute(arr.getContext()->get(),
196  values.size(), values.data());
197  return PyDenseArrayAttribute<EltTy, DerivedT>(arr.getContext(), attr);
198  });
199  }
200 };
201 
202 /// Instantiate the python dense array classes.
203 struct PyDenseBoolArrayAttribute
204  : public PyDenseArrayAttribute<int, PyDenseBoolArrayAttribute> {
205  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseBoolArray;
206  static constexpr auto getAttribute = mlirDenseBoolArrayGet;
207  static constexpr auto getElement = mlirDenseBoolArrayGetElement;
208  static constexpr const char *pyClassName = "DenseBoolArrayAttr";
209  static constexpr const char *pyIteratorName = "DenseBoolArrayIterator";
210  using PyDenseArrayAttribute::PyDenseArrayAttribute;
211 };
212 struct PyDenseI8ArrayAttribute
213  : public PyDenseArrayAttribute<int8_t, PyDenseI8ArrayAttribute> {
214  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseI8Array;
215  static constexpr auto getAttribute = mlirDenseI8ArrayGet;
216  static constexpr auto getElement = mlirDenseI8ArrayGetElement;
217  static constexpr const char *pyClassName = "DenseI8ArrayAttr";
218  static constexpr const char *pyIteratorName = "DenseI8ArrayIterator";
219  using PyDenseArrayAttribute::PyDenseArrayAttribute;
220 };
221 struct PyDenseI16ArrayAttribute
222  : public PyDenseArrayAttribute<int16_t, PyDenseI16ArrayAttribute> {
223  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseI16Array;
224  static constexpr auto getAttribute = mlirDenseI16ArrayGet;
225  static constexpr auto getElement = mlirDenseI16ArrayGetElement;
226  static constexpr const char *pyClassName = "DenseI16ArrayAttr";
227  static constexpr const char *pyIteratorName = "DenseI16ArrayIterator";
228  using PyDenseArrayAttribute::PyDenseArrayAttribute;
229 };
230 struct PyDenseI32ArrayAttribute
231  : public PyDenseArrayAttribute<int32_t, PyDenseI32ArrayAttribute> {
232  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseI32Array;
233  static constexpr auto getAttribute = mlirDenseI32ArrayGet;
234  static constexpr auto getElement = mlirDenseI32ArrayGetElement;
235  static constexpr const char *pyClassName = "DenseI32ArrayAttr";
236  static constexpr const char *pyIteratorName = "DenseI32ArrayIterator";
237  using PyDenseArrayAttribute::PyDenseArrayAttribute;
238 };
239 struct PyDenseI64ArrayAttribute
240  : public PyDenseArrayAttribute<int64_t, PyDenseI64ArrayAttribute> {
241  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseI64Array;
242  static constexpr auto getAttribute = mlirDenseI64ArrayGet;
243  static constexpr auto getElement = mlirDenseI64ArrayGetElement;
244  static constexpr const char *pyClassName = "DenseI64ArrayAttr";
245  static constexpr const char *pyIteratorName = "DenseI64ArrayIterator";
246  using PyDenseArrayAttribute::PyDenseArrayAttribute;
247 };
248 struct PyDenseF32ArrayAttribute
249  : public PyDenseArrayAttribute<float, PyDenseF32ArrayAttribute> {
250  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseF32Array;
251  static constexpr auto getAttribute = mlirDenseF32ArrayGet;
252  static constexpr auto getElement = mlirDenseF32ArrayGetElement;
253  static constexpr const char *pyClassName = "DenseF32ArrayAttr";
254  static constexpr const char *pyIteratorName = "DenseF32ArrayIterator";
255  using PyDenseArrayAttribute::PyDenseArrayAttribute;
256 };
257 struct PyDenseF64ArrayAttribute
258  : public PyDenseArrayAttribute<double, PyDenseF64ArrayAttribute> {
259  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseF64Array;
260  static constexpr auto getAttribute = mlirDenseF64ArrayGet;
261  static constexpr auto getElement = mlirDenseF64ArrayGetElement;
262  static constexpr const char *pyClassName = "DenseF64ArrayAttr";
263  static constexpr const char *pyIteratorName = "DenseF64ArrayIterator";
264  using PyDenseArrayAttribute::PyDenseArrayAttribute;
265 };
266 
267 class PyArrayAttribute : public PyConcreteAttribute<PyArrayAttribute> {
268 public:
269  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAArray;
270  static constexpr const char *pyClassName = "ArrayAttr";
272 
273  class PyArrayAttributeIterator {
274  public:
275  PyArrayAttributeIterator(PyAttribute attr) : attr(std::move(attr)) {}
276 
277  PyArrayAttributeIterator &dunderIter() { return *this; }
278 
279  PyAttribute dunderNext() {
280  // TODO: Throw is an inefficient way to stop iteration.
281  if (nextIndex >= mlirArrayAttrGetNumElements(attr.get()))
282  throw py::stop_iteration();
283  return PyAttribute(attr.getContext(),
284  mlirArrayAttrGetElement(attr.get(), nextIndex++));
285  }
286 
287  static void bind(py::module &m) {
288  py::class_<PyArrayAttributeIterator>(m, "ArrayAttributeIterator",
289  py::module_local())
290  .def("__iter__", &PyArrayAttributeIterator::dunderIter)
291  .def("__next__", &PyArrayAttributeIterator::dunderNext);
292  }
293 
294  private:
295  PyAttribute attr;
296  int nextIndex = 0;
297  };
298 
299  PyAttribute getItem(intptr_t i) {
300  return PyAttribute(getContext(), mlirArrayAttrGetElement(*this, i));
301  }
302 
303  static void bindDerived(ClassTy &c) {
304  c.def_static(
305  "get",
306  [](py::list attributes, DefaultingPyMlirContext context) {
307  SmallVector<MlirAttribute> mlirAttributes;
308  mlirAttributes.reserve(py::len(attributes));
309  for (auto attribute : attributes) {
310  mlirAttributes.push_back(pyTryCast<PyAttribute>(attribute));
311  }
312  MlirAttribute attr = mlirArrayAttrGet(
313  context->get(), mlirAttributes.size(), mlirAttributes.data());
314  return PyArrayAttribute(context->getRef(), attr);
315  },
316  py::arg("attributes"), py::arg("context") = py::none(),
317  "Gets a uniqued Array attribute");
318  c.def("__getitem__",
319  [](PyArrayAttribute &arr, intptr_t i) {
320  if (i >= mlirArrayAttrGetNumElements(arr))
321  throw py::index_error("ArrayAttribute index out of range");
322  return arr.getItem(i);
323  })
324  .def("__len__",
325  [](const PyArrayAttribute &arr) {
326  return mlirArrayAttrGetNumElements(arr);
327  })
328  .def("__iter__", [](const PyArrayAttribute &arr) {
329  return PyArrayAttributeIterator(arr);
330  });
331  c.def("__add__", [](PyArrayAttribute arr, py::list extras) {
332  std::vector<MlirAttribute> attributes;
333  intptr_t numOldElements = mlirArrayAttrGetNumElements(arr);
334  attributes.reserve(numOldElements + py::len(extras));
335  for (intptr_t i = 0; i < numOldElements; ++i)
336  attributes.push_back(arr.getItem(i));
337  for (py::handle attr : extras)
338  attributes.push_back(pyTryCast<PyAttribute>(attr));
339  MlirAttribute arrayAttr = mlirArrayAttrGet(
340  arr.getContext()->get(), attributes.size(), attributes.data());
341  return PyArrayAttribute(arr.getContext(), arrayAttr);
342  });
343  }
344 };
345 
346 /// Float Point Attribute subclass - FloatAttr.
347 class PyFloatAttribute : public PyConcreteAttribute<PyFloatAttribute> {
348 public:
349  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAFloat;
350  static constexpr const char *pyClassName = "FloatAttr";
352 
353  static void bindDerived(ClassTy &c) {
354  c.def_static(
355  "get",
356  [](PyType &type, double value, DefaultingPyLocation loc) {
357  MlirAttribute attr = mlirFloatAttrDoubleGetChecked(loc, type, value);
358  // TODO: Rework error reporting once diagnostic engine is exposed
359  // in C API.
360  if (mlirAttributeIsNull(attr)) {
361  throw SetPyError(PyExc_ValueError,
362  Twine("invalid '") +
363  py::repr(py::cast(type)).cast<std::string>() +
364  "' and expected floating point type.");
365  }
366  return PyFloatAttribute(type.getContext(), attr);
367  },
368  py::arg("type"), py::arg("value"), py::arg("loc") = py::none(),
369  "Gets an uniqued float point attribute associated to a type");
370  c.def_static(
371  "get_f32",
372  [](double value, DefaultingPyMlirContext context) {
373  MlirAttribute attr = mlirFloatAttrDoubleGet(
374  context->get(), mlirF32TypeGet(context->get()), value);
375  return PyFloatAttribute(context->getRef(), attr);
376  },
377  py::arg("value"), py::arg("context") = py::none(),
378  "Gets an uniqued float point attribute associated to a f32 type");
379  c.def_static(
380  "get_f64",
381  [](double value, DefaultingPyMlirContext context) {
382  MlirAttribute attr = mlirFloatAttrDoubleGet(
383  context->get(), mlirF64TypeGet(context->get()), value);
384  return PyFloatAttribute(context->getRef(), attr);
385  },
386  py::arg("value"), py::arg("context") = py::none(),
387  "Gets an uniqued float point attribute associated to a f64 type");
388  c.def_property_readonly(
389  "value",
390  [](PyFloatAttribute &self) {
391  return mlirFloatAttrGetValueDouble(self);
392  },
393  "Returns the value of the float point attribute");
394  }
395 };
396 
397 /// Integer Attribute subclass - IntegerAttr.
398 class PyIntegerAttribute : public PyConcreteAttribute<PyIntegerAttribute> {
399 public:
400  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAInteger;
401  static constexpr const char *pyClassName = "IntegerAttr";
403 
404  static void bindDerived(ClassTy &c) {
405  c.def_static(
406  "get",
407  [](PyType &type, int64_t value) {
408  MlirAttribute attr = mlirIntegerAttrGet(type, value);
409  return PyIntegerAttribute(type.getContext(), attr);
410  },
411  py::arg("type"), py::arg("value"),
412  "Gets an uniqued integer attribute associated to a type");
413  c.def_property_readonly(
414  "value",
415  [](PyIntegerAttribute &self) -> py::int_ {
416  MlirType type = mlirAttributeGetType(self);
417  if (mlirTypeIsAIndex(type) || mlirIntegerTypeIsSignless(type))
418  return mlirIntegerAttrGetValueInt(self);
419  if (mlirIntegerTypeIsSigned(type))
420  return mlirIntegerAttrGetValueSInt(self);
421  return mlirIntegerAttrGetValueUInt(self);
422  },
423  "Returns the value of the integer attribute");
424  }
425 };
426 
427 /// Bool Attribute subclass - BoolAttr.
428 class PyBoolAttribute : public PyConcreteAttribute<PyBoolAttribute> {
429 public:
430  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsABool;
431  static constexpr const char *pyClassName = "BoolAttr";
433 
434  static void bindDerived(ClassTy &c) {
435  c.def_static(
436  "get",
437  [](bool value, DefaultingPyMlirContext context) {
438  MlirAttribute attr = mlirBoolAttrGet(context->get(), value);
439  return PyBoolAttribute(context->getRef(), attr);
440  },
441  py::arg("value"), py::arg("context") = py::none(),
442  "Gets an uniqued bool attribute");
443  c.def_property_readonly(
444  "value",
445  [](PyBoolAttribute &self) { return mlirBoolAttrGetValue(self); },
446  "Returns the value of the bool attribute");
447  }
448 };
449 
450 class PyFlatSymbolRefAttribute
451  : public PyConcreteAttribute<PyFlatSymbolRefAttribute> {
452 public:
453  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAFlatSymbolRef;
454  static constexpr const char *pyClassName = "FlatSymbolRefAttr";
456 
457  static void bindDerived(ClassTy &c) {
458  c.def_static(
459  "get",
460  [](std::string value, DefaultingPyMlirContext context) {
461  MlirAttribute attr =
462  mlirFlatSymbolRefAttrGet(context->get(), toMlirStringRef(value));
463  return PyFlatSymbolRefAttribute(context->getRef(), attr);
464  },
465  py::arg("value"), py::arg("context") = py::none(),
466  "Gets a uniqued FlatSymbolRef attribute");
467  c.def_property_readonly(
468  "value",
469  [](PyFlatSymbolRefAttribute &self) {
471  return py::str(stringRef.data, stringRef.length);
472  },
473  "Returns the value of the FlatSymbolRef attribute as a string");
474  }
475 };
476 
477 class PyOpaqueAttribute : public PyConcreteAttribute<PyOpaqueAttribute> {
478 public:
479  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAOpaque;
480  static constexpr const char *pyClassName = "OpaqueAttr";
482 
483  static void bindDerived(ClassTy &c) {
484  c.def_static(
485  "get",
486  [](std::string dialectNamespace, py::buffer buffer, PyType &type,
487  DefaultingPyMlirContext context) {
488  const py::buffer_info bufferInfo = buffer.request();
489  intptr_t bufferSize = bufferInfo.size;
490  MlirAttribute attr = mlirOpaqueAttrGet(
491  context->get(), toMlirStringRef(dialectNamespace), bufferSize,
492  static_cast<char *>(bufferInfo.ptr), type);
493  return PyOpaqueAttribute(context->getRef(), attr);
494  },
495  py::arg("dialect_namespace"), py::arg("buffer"), py::arg("type"),
496  py::arg("context") = py::none(), "Gets an Opaque attribute.");
497  c.def_property_readonly(
498  "dialect_namespace",
499  [](PyOpaqueAttribute &self) {
501  return py::str(stringRef.data, stringRef.length);
502  },
503  "Returns the dialect namespace for the Opaque attribute as a string");
504  c.def_property_readonly(
505  "data",
506  [](PyOpaqueAttribute &self) {
507  MlirStringRef stringRef = mlirOpaqueAttrGetData(self);
508  return py::str(stringRef.data, stringRef.length);
509  },
510  "Returns the data for the Opaqued attributes as a string");
511  }
512 };
513 
514 class PyStringAttribute : public PyConcreteAttribute<PyStringAttribute> {
515 public:
516  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAString;
517  static constexpr const char *pyClassName = "StringAttr";
519 
520  static void bindDerived(ClassTy &c) {
521  c.def_static(
522  "get",
523  [](std::string value, DefaultingPyMlirContext context) {
524  MlirAttribute attr =
525  mlirStringAttrGet(context->get(), toMlirStringRef(value));
526  return PyStringAttribute(context->getRef(), attr);
527  },
528  py::arg("value"), py::arg("context") = py::none(),
529  "Gets a uniqued string attribute");
530  c.def_static(
531  "get_typed",
532  [](PyType &type, std::string value) {
533  MlirAttribute attr =
535  return PyStringAttribute(type.getContext(), attr);
536  },
537  py::arg("type"), py::arg("value"),
538  "Gets a uniqued string attribute associated to a type");
539  c.def_property_readonly(
540  "value",
541  [](PyStringAttribute &self) {
542  MlirStringRef stringRef = mlirStringAttrGetValue(self);
543  return py::str(stringRef.data, stringRef.length);
544  },
545  "Returns the value of the string attribute");
546  }
547 };
548 
549 // TODO: Support construction of string elements.
550 class PyDenseElementsAttribute
551  : public PyConcreteAttribute<PyDenseElementsAttribute> {
552 public:
553  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseElements;
554  static constexpr const char *pyClassName = "DenseElementsAttr";
556 
557  static PyDenseElementsAttribute
558  getFromBuffer(py::buffer array, bool signless, Optional<PyType> explicitType,
559  Optional<std::vector<int64_t>> explicitShape,
560  DefaultingPyMlirContext contextWrapper) {
561  // Request a contiguous view. In exotic cases, this will cause a copy.
562  int flags = PyBUF_C_CONTIGUOUS | PyBUF_FORMAT;
563  Py_buffer *view = new Py_buffer();
564  if (PyObject_GetBuffer(array.ptr(), view, flags) != 0) {
565  delete view;
566  throw py::error_already_set();
567  }
568  py::buffer_info arrayInfo(view);
569  SmallVector<int64_t> shape;
570  if (explicitShape) {
571  shape.append(explicitShape->begin(), explicitShape->end());
572  } else {
573  shape.append(arrayInfo.shape.begin(),
574  arrayInfo.shape.begin() + arrayInfo.ndim);
575  }
576 
577  MlirAttribute encodingAttr = mlirAttributeGetNull();
578  MlirContext context = contextWrapper->get();
579 
580  // Detect format codes that are suitable for bulk loading. This includes
581  // all byte aligned integer and floating point types up to 8 bytes.
582  // Notably, this excludes, bool (which needs to be bit-packed) and
583  // other exotics which do not have a direct representation in the buffer
584  // protocol (i.e. complex, etc).
585  Optional<MlirType> bulkLoadElementType;
586  if (explicitType) {
587  bulkLoadElementType = *explicitType;
588  } else if (arrayInfo.format == "f") {
589  // f32
590  assert(arrayInfo.itemsize == 4 && "mismatched array itemsize");
591  bulkLoadElementType = mlirF32TypeGet(context);
592  } else if (arrayInfo.format == "d") {
593  // f64
594  assert(arrayInfo.itemsize == 8 && "mismatched array itemsize");
595  bulkLoadElementType = mlirF64TypeGet(context);
596  } else if (arrayInfo.format == "e") {
597  // f16
598  assert(arrayInfo.itemsize == 2 && "mismatched array itemsize");
599  bulkLoadElementType = mlirF16TypeGet(context);
600  } else if (isSignedIntegerFormat(arrayInfo.format)) {
601  if (arrayInfo.itemsize == 4) {
602  // i32
603  bulkLoadElementType = signless ? mlirIntegerTypeGet(context, 32)
604  : mlirIntegerTypeSignedGet(context, 32);
605  } else if (arrayInfo.itemsize == 8) {
606  // i64
607  bulkLoadElementType = signless ? mlirIntegerTypeGet(context, 64)
608  : mlirIntegerTypeSignedGet(context, 64);
609  } else if (arrayInfo.itemsize == 1) {
610  // i8
611  bulkLoadElementType = signless ? mlirIntegerTypeGet(context, 8)
612  : mlirIntegerTypeSignedGet(context, 8);
613  } else if (arrayInfo.itemsize == 2) {
614  // i16
615  bulkLoadElementType = signless ? mlirIntegerTypeGet(context, 16)
616  : mlirIntegerTypeSignedGet(context, 16);
617  }
618  } else if (isUnsignedIntegerFormat(arrayInfo.format)) {
619  if (arrayInfo.itemsize == 4) {
620  // unsigned i32
621  bulkLoadElementType = signless
622  ? mlirIntegerTypeGet(context, 32)
623  : mlirIntegerTypeUnsignedGet(context, 32);
624  } else if (arrayInfo.itemsize == 8) {
625  // unsigned i64
626  bulkLoadElementType = signless
627  ? mlirIntegerTypeGet(context, 64)
628  : mlirIntegerTypeUnsignedGet(context, 64);
629  } else if (arrayInfo.itemsize == 1) {
630  // i8
631  bulkLoadElementType = signless ? mlirIntegerTypeGet(context, 8)
632  : mlirIntegerTypeUnsignedGet(context, 8);
633  } else if (arrayInfo.itemsize == 2) {
634  // i16
635  bulkLoadElementType = signless
636  ? mlirIntegerTypeGet(context, 16)
637  : mlirIntegerTypeUnsignedGet(context, 16);
638  }
639  }
640  if (bulkLoadElementType) {
641  auto shapedType = mlirRankedTensorTypeGet(
642  shape.size(), shape.data(), *bulkLoadElementType, encodingAttr);
643  size_t rawBufferSize = arrayInfo.size * arrayInfo.itemsize;
644  MlirAttribute attr = mlirDenseElementsAttrRawBufferGet(
645  shapedType, rawBufferSize, arrayInfo.ptr);
646  if (mlirAttributeIsNull(attr)) {
647  throw std::invalid_argument(
648  "DenseElementsAttr could not be constructed from the given buffer. "
649  "This may mean that the Python buffer layout does not match that "
650  "MLIR expected layout and is a bug.");
651  }
652  return PyDenseElementsAttribute(contextWrapper->getRef(), attr);
653  }
654 
655  throw std::invalid_argument(
656  std::string("unimplemented array format conversion from format: ") +
657  arrayInfo.format);
658  }
659 
660  static PyDenseElementsAttribute getSplat(const PyType &shapedType,
661  PyAttribute &elementAttr) {
662  auto contextWrapper =
664  if (!mlirAttributeIsAInteger(elementAttr) &&
665  !mlirAttributeIsAFloat(elementAttr)) {
666  std::string message = "Illegal element type for DenseElementsAttr: ";
667  message.append(py::repr(py::cast(elementAttr)));
668  throw SetPyError(PyExc_ValueError, message);
669  }
670  if (!mlirTypeIsAShaped(shapedType) ||
671  !mlirShapedTypeHasStaticShape(shapedType)) {
672  std::string message =
673  "Expected a static ShapedType for the shaped_type parameter: ";
674  message.append(py::repr(py::cast(shapedType)));
675  throw SetPyError(PyExc_ValueError, message);
676  }
677  MlirType shapedElementType = mlirShapedTypeGetElementType(shapedType);
678  MlirType attrType = mlirAttributeGetType(elementAttr);
679  if (!mlirTypeEqual(shapedElementType, attrType)) {
680  std::string message =
681  "Shaped element type and attribute type must be equal: shaped=";
682  message.append(py::repr(py::cast(shapedType)));
683  message.append(", element=");
684  message.append(py::repr(py::cast(elementAttr)));
685  throw SetPyError(PyExc_ValueError, message);
686  }
687 
688  MlirAttribute elements =
689  mlirDenseElementsAttrSplatGet(shapedType, elementAttr);
690  return PyDenseElementsAttribute(contextWrapper->getRef(), elements);
691  }
692 
693  intptr_t dunderLen() { return mlirElementsAttrGetNumElements(*this); }
694 
695  py::buffer_info accessBuffer() {
696  if (mlirDenseElementsAttrIsSplat(*this)) {
697  // TODO: Currently crashes the program.
698  // Reported as https://github.com/pybind/pybind11/issues/3336
699  throw std::invalid_argument(
700  "unsupported data type for conversion to Python buffer");
701  }
702 
703  MlirType shapedType = mlirAttributeGetType(*this);
704  MlirType elementType = mlirShapedTypeGetElementType(shapedType);
705  std::string format;
706 
707  if (mlirTypeIsAF32(elementType)) {
708  // f32
709  return bufferInfo<float>(shapedType);
710  }
711  if (mlirTypeIsAF64(elementType)) {
712  // f64
713  return bufferInfo<double>(shapedType);
714  }
715  if (mlirTypeIsAF16(elementType)) {
716  // f16
717  return bufferInfo<uint16_t>(shapedType, "e");
718  }
719  if (mlirTypeIsAInteger(elementType) &&
720  mlirIntegerTypeGetWidth(elementType) == 32) {
721  if (mlirIntegerTypeIsSignless(elementType) ||
722  mlirIntegerTypeIsSigned(elementType)) {
723  // i32
724  return bufferInfo<int32_t>(shapedType);
725  }
726  if (mlirIntegerTypeIsUnsigned(elementType)) {
727  // unsigned i32
728  return bufferInfo<uint32_t>(shapedType);
729  }
730  } else if (mlirTypeIsAInteger(elementType) &&
731  mlirIntegerTypeGetWidth(elementType) == 64) {
732  if (mlirIntegerTypeIsSignless(elementType) ||
733  mlirIntegerTypeIsSigned(elementType)) {
734  // i64
735  return bufferInfo<int64_t>(shapedType);
736  }
737  if (mlirIntegerTypeIsUnsigned(elementType)) {
738  // unsigned i64
739  return bufferInfo<uint64_t>(shapedType);
740  }
741  } else if (mlirTypeIsAInteger(elementType) &&
742  mlirIntegerTypeGetWidth(elementType) == 8) {
743  if (mlirIntegerTypeIsSignless(elementType) ||
744  mlirIntegerTypeIsSigned(elementType)) {
745  // i8
746  return bufferInfo<int8_t>(shapedType);
747  }
748  if (mlirIntegerTypeIsUnsigned(elementType)) {
749  // unsigned i8
750  return bufferInfo<uint8_t>(shapedType);
751  }
752  } else if (mlirTypeIsAInteger(elementType) &&
753  mlirIntegerTypeGetWidth(elementType) == 16) {
754  if (mlirIntegerTypeIsSignless(elementType) ||
755  mlirIntegerTypeIsSigned(elementType)) {
756  // i16
757  return bufferInfo<int16_t>(shapedType);
758  }
759  if (mlirIntegerTypeIsUnsigned(elementType)) {
760  // unsigned i16
761  return bufferInfo<uint16_t>(shapedType);
762  }
763  }
764 
765  // TODO: Currently crashes the program.
766  // Reported as https://github.com/pybind/pybind11/issues/3336
767  throw std::invalid_argument(
768  "unsupported data type for conversion to Python buffer");
769  }
770 
771  static void bindDerived(ClassTy &c) {
772  c.def("__len__", &PyDenseElementsAttribute::dunderLen)
773  .def_static("get", PyDenseElementsAttribute::getFromBuffer,
774  py::arg("array"), py::arg("signless") = true,
775  py::arg("type") = py::none(), py::arg("shape") = py::none(),
776  py::arg("context") = py::none(),
778  .def_static("get_splat", PyDenseElementsAttribute::getSplat,
779  py::arg("shaped_type"), py::arg("element_attr"),
780  "Gets a DenseElementsAttr where all values are the same")
781  .def_property_readonly("is_splat",
782  [](PyDenseElementsAttribute &self) -> bool {
783  return mlirDenseElementsAttrIsSplat(self);
784  })
785  .def_buffer(&PyDenseElementsAttribute::accessBuffer);
786  }
787 
788 private:
789  static bool isUnsignedIntegerFormat(const std::string &format) {
790  if (format.empty())
791  return false;
792  char code = format[0];
793  return code == 'I' || code == 'B' || code == 'H' || code == 'L' ||
794  code == 'Q';
795  }
796 
797  static bool isSignedIntegerFormat(const std::string &format) {
798  if (format.empty())
799  return false;
800  char code = format[0];
801  return code == 'i' || code == 'b' || code == 'h' || code == 'l' ||
802  code == 'q';
803  }
804 
805  template <typename Type>
806  py::buffer_info bufferInfo(MlirType shapedType,
807  const char *explicitFormat = nullptr) {
808  intptr_t rank = mlirShapedTypeGetRank(shapedType);
809  // Prepare the data for the buffer_info.
810  // Buffer is configured for read-only access below.
811  Type *data = static_cast<Type *>(
812  const_cast<void *>(mlirDenseElementsAttrGetRawData(*this)));
813  // Prepare the shape for the buffer_info.
815  for (intptr_t i = 0; i < rank; ++i)
816  shape.push_back(mlirShapedTypeGetDimSize(shapedType, i));
817  // Prepare the strides for the buffer_info.
818  SmallVector<intptr_t, 4> strides;
819  intptr_t strideFactor = 1;
820  for (intptr_t i = 1; i < rank; ++i) {
821  strideFactor = 1;
822  for (intptr_t j = i; j < rank; ++j) {
823  strideFactor *= mlirShapedTypeGetDimSize(shapedType, j);
824  }
825  strides.push_back(sizeof(Type) * strideFactor);
826  }
827  strides.push_back(sizeof(Type));
828  std::string format;
829  if (explicitFormat) {
830  format = explicitFormat;
831  } else {
832  format = py::format_descriptor<Type>::format();
833  }
834  return py::buffer_info(data, sizeof(Type), format, rank, shape, strides,
835  /*readonly=*/true);
836  }
837 }; // namespace
838 
839 /// Refinement of the PyDenseElementsAttribute for attributes containing integer
840 /// (and boolean) values. Supports element access.
841 class PyDenseIntElementsAttribute
842  : public PyConcreteAttribute<PyDenseIntElementsAttribute,
843  PyDenseElementsAttribute> {
844 public:
845  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseIntElements;
846  static constexpr const char *pyClassName = "DenseIntElementsAttr";
848 
849  /// Returns the element at the given linear position. Asserts if the index is
850  /// out of range.
851  py::int_ dunderGetItem(intptr_t pos) {
852  if (pos < 0 || pos >= dunderLen()) {
853  throw SetPyError(PyExc_IndexError,
854  "attempt to access out of bounds element");
855  }
856 
857  MlirType type = mlirAttributeGetType(*this);
858  type = mlirShapedTypeGetElementType(type);
859  assert(mlirTypeIsAInteger(type) &&
860  "expected integer element type in dense int elements attribute");
861  // Dispatch element extraction to an appropriate C function based on the
862  // elemental type of the attribute. py::int_ is implicitly constructible
863  // from any C++ integral type and handles bitwidth correctly.
864  // TODO: consider caching the type properties in the constructor to avoid
865  // querying them on each element access.
866  unsigned width = mlirIntegerTypeGetWidth(type);
867  bool isUnsigned = mlirIntegerTypeIsUnsigned(type);
868  if (isUnsigned) {
869  if (width == 1) {
870  return mlirDenseElementsAttrGetBoolValue(*this, pos);
871  }
872  if (width == 8) {
873  return mlirDenseElementsAttrGetUInt8Value(*this, pos);
874  }
875  if (width == 16) {
876  return mlirDenseElementsAttrGetUInt16Value(*this, pos);
877  }
878  if (width == 32) {
879  return mlirDenseElementsAttrGetUInt32Value(*this, pos);
880  }
881  if (width == 64) {
882  return mlirDenseElementsAttrGetUInt64Value(*this, pos);
883  }
884  } else {
885  if (width == 1) {
886  return mlirDenseElementsAttrGetBoolValue(*this, pos);
887  }
888  if (width == 8) {
889  return mlirDenseElementsAttrGetInt8Value(*this, pos);
890  }
891  if (width == 16) {
892  return mlirDenseElementsAttrGetInt16Value(*this, pos);
893  }
894  if (width == 32) {
895  return mlirDenseElementsAttrGetInt32Value(*this, pos);
896  }
897  if (width == 64) {
898  return mlirDenseElementsAttrGetInt64Value(*this, pos);
899  }
900  }
901  throw SetPyError(PyExc_TypeError, "Unsupported integer type");
902  }
903 
904  static void bindDerived(ClassTy &c) {
905  c.def("__getitem__", &PyDenseIntElementsAttribute::dunderGetItem);
906  }
907 };
908 
909 class PyDictAttribute : public PyConcreteAttribute<PyDictAttribute> {
910 public:
911  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADictionary;
912  static constexpr const char *pyClassName = "DictAttr";
914 
915  intptr_t dunderLen() { return mlirDictionaryAttrGetNumElements(*this); }
916 
917  bool dunderContains(const std::string &name) {
918  return !mlirAttributeIsNull(
920  }
921 
922  static void bindDerived(ClassTy &c) {
923  c.def("__contains__", &PyDictAttribute::dunderContains);
924  c.def("__len__", &PyDictAttribute::dunderLen);
925  c.def_static(
926  "get",
927  [](py::dict attributes, DefaultingPyMlirContext context) {
928  SmallVector<MlirNamedAttribute> mlirNamedAttributes;
929  mlirNamedAttributes.reserve(attributes.size());
930  for (auto &it : attributes) {
931  auto &mlirAttr = it.second.cast<PyAttribute &>();
932  auto name = it.first.cast<std::string>();
933  mlirNamedAttributes.push_back(mlirNamedAttributeGet(
935  toMlirStringRef(name)),
936  mlirAttr));
937  }
938  MlirAttribute attr =
939  mlirDictionaryAttrGet(context->get(), mlirNamedAttributes.size(),
940  mlirNamedAttributes.data());
941  return PyDictAttribute(context->getRef(), attr);
942  },
943  py::arg("value") = py::dict(), py::arg("context") = py::none(),
944  "Gets an uniqued dict attribute");
945  c.def("__getitem__", [](PyDictAttribute &self, const std::string &name) {
946  MlirAttribute attr =
948  if (mlirAttributeIsNull(attr)) {
949  throw SetPyError(PyExc_KeyError,
950  "attempt to access a non-existent attribute");
951  }
952  return PyAttribute(self.getContext(), attr);
953  });
954  c.def("__getitem__", [](PyDictAttribute &self, intptr_t index) {
955  if (index < 0 || index >= self.dunderLen()) {
956  throw SetPyError(PyExc_IndexError,
957  "attempt to access out of bounds attribute");
958  }
959  MlirNamedAttribute namedAttr = mlirDictionaryAttrGetElement(self, index);
960  return PyNamedAttribute(
961  namedAttr.attribute,
962  std::string(mlirIdentifierStr(namedAttr.name).data));
963  });
964  }
965 };
966 
967 /// Refinement of PyDenseElementsAttribute for attributes containing
968 /// floating-point values. Supports element access.
969 class PyDenseFPElementsAttribute
970  : public PyConcreteAttribute<PyDenseFPElementsAttribute,
971  PyDenseElementsAttribute> {
972 public:
973  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsADenseFPElements;
974  static constexpr const char *pyClassName = "DenseFPElementsAttr";
976 
977  py::float_ dunderGetItem(intptr_t pos) {
978  if (pos < 0 || pos >= dunderLen()) {
979  throw SetPyError(PyExc_IndexError,
980  "attempt to access out of bounds element");
981  }
982 
983  MlirType type = mlirAttributeGetType(*this);
984  type = mlirShapedTypeGetElementType(type);
985  // Dispatch element extraction to an appropriate C function based on the
986  // elemental type of the attribute. py::float_ is implicitly constructible
987  // from float and double.
988  // TODO: consider caching the type properties in the constructor to avoid
989  // querying them on each element access.
990  if (mlirTypeIsAF32(type)) {
991  return mlirDenseElementsAttrGetFloatValue(*this, pos);
992  }
993  if (mlirTypeIsAF64(type)) {
994  return mlirDenseElementsAttrGetDoubleValue(*this, pos);
995  }
996  throw SetPyError(PyExc_TypeError, "Unsupported floating-point type");
997  }
998 
999  static void bindDerived(ClassTy &c) {
1000  c.def("__getitem__", &PyDenseFPElementsAttribute::dunderGetItem);
1001  }
1002 };
1003 
1004 class PyTypeAttribute : public PyConcreteAttribute<PyTypeAttribute> {
1005 public:
1006  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAType;
1007  static constexpr const char *pyClassName = "TypeAttr";
1009 
1010  static void bindDerived(ClassTy &c) {
1011  c.def_static(
1012  "get",
1013  [](PyType value, DefaultingPyMlirContext context) {
1014  MlirAttribute attr = mlirTypeAttrGet(value.get());
1015  return PyTypeAttribute(context->getRef(), attr);
1016  },
1017  py::arg("value"), py::arg("context") = py::none(),
1018  "Gets a uniqued Type attribute");
1019  c.def_property_readonly("value", [](PyTypeAttribute &self) {
1020  return PyType(self.getContext()->getRef(),
1021  mlirTypeAttrGetValue(self.get()));
1022  });
1023  }
1024 };
1025 
1026 /// Unit Attribute subclass. Unit attributes don't have values.
1027 class PyUnitAttribute : public PyConcreteAttribute<PyUnitAttribute> {
1028 public:
1029  static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAUnit;
1030  static constexpr const char *pyClassName = "UnitAttr";
1032 
1033  static void bindDerived(ClassTy &c) {
1034  c.def_static(
1035  "get",
1036  [](DefaultingPyMlirContext context) {
1037  return PyUnitAttribute(context->getRef(),
1038  mlirUnitAttrGet(context->get()));
1039  },
1040  py::arg("context") = py::none(), "Create a Unit attribute.");
1041  }
1042 };
1043 
1044 } // namespace
1045 
1046 void mlir::python::populateIRAttributes(py::module &m) {
1047  PyAffineMapAttribute::bind(m);
1048 
1049  PyDenseBoolArrayAttribute::bind(m);
1050  PyDenseBoolArrayAttribute::PyDenseArrayIterator::bind(m);
1051  PyDenseI8ArrayAttribute::bind(m);
1052  PyDenseI8ArrayAttribute::PyDenseArrayIterator::bind(m);
1053  PyDenseI16ArrayAttribute::bind(m);
1054  PyDenseI16ArrayAttribute::PyDenseArrayIterator::bind(m);
1055  PyDenseI32ArrayAttribute::bind(m);
1056  PyDenseI32ArrayAttribute::PyDenseArrayIterator::bind(m);
1057  PyDenseI64ArrayAttribute::bind(m);
1058  PyDenseI64ArrayAttribute::PyDenseArrayIterator::bind(m);
1059  PyDenseF32ArrayAttribute::bind(m);
1060  PyDenseF32ArrayAttribute::PyDenseArrayIterator::bind(m);
1061  PyDenseF64ArrayAttribute::bind(m);
1062  PyDenseF64ArrayAttribute::PyDenseArrayIterator::bind(m);
1063 
1064  PyArrayAttribute::bind(m);
1065  PyArrayAttribute::PyArrayAttributeIterator::bind(m);
1066  PyBoolAttribute::bind(m);
1067  PyDenseElementsAttribute::bind(m);
1068  PyDenseFPElementsAttribute::bind(m);
1069  PyDenseIntElementsAttribute::bind(m);
1070  PyDictAttribute::bind(m);
1071  PyFlatSymbolRefAttribute::bind(m);
1072  PyOpaqueAttribute::bind(m);
1073  PyFloatAttribute::bind(m);
1074  PyIntegerAttribute::bind(m);
1075  PyStringAttribute::bind(m);
1076  PyTypeAttribute::bind(m);
1077  PyUnitAttribute::bind(m);
1078 }
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseBoolArrayGet(MlirContext ctx, intptr_t size, int const *values)
Create a dense array attribute with the given elements.
static MlirStringRef toMlirStringRef(const std::string &s)
Definition: IRCore.cpp:172
Include the generated interface declarations.
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseI16Array(MlirAttribute attr)
MLIR_CAPI_EXPORTED MlirType mlirAttributeGetType(MlirAttribute attribute)
Gets the type of this attribute.
Definition: IR.cpp:755
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseF64ArrayGet(MlirContext ctx, intptr_t size, double const *values)
const char * data
Pointer to the first symbol.
Definition: Support.h:72
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 bool mlirAttributeIsADenseI64Array(MlirAttribute attr)
MLIR_CAPI_EXPORTED int64_t mlirElementsAttrGetNumElements(MlirAttribute attr)
Gets the total number of elements in the given elements 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 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 mlirAttributeIsAOpaque(MlirAttribute attr)
Checks whether the given attribute is an opaque attribute.
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseI32Array(MlirAttribute attr)
MLIR_CAPI_EXPORTED MlirAttribute mlirAffineMapAttrGet(MlirAffineMap map)
Creates an affine map attribute wrapping the given map.
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 int16_t mlirDenseElementsAttrGetInt16Value(MlirAttribute attr, intptr_t pos)
static bool mlirAttributeIsNull(MlirAttribute attr)
Checks whether an attribute is null.
Definition: IR.h:771
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseI32ArrayGet(MlirContext ctx, intptr_t size, int32_t const *values)
MLIR_CAPI_EXPORTED bool mlirAttributeIsAInteger(MlirAttribute attr)
Checks whether the given attribute is an integer attribute.
MLIR_CAPI_EXPORTED uint8_t mlirDenseElementsAttrGetUInt8Value(MlirAttribute attr, intptr_t pos)
Used in function arguments when None should resolve to the current context manager set instance...
Definition: IRModule.h:449
MLIR_CAPI_EXPORTED bool mlirDenseBoolArrayGetElement(MlirAttribute attr, intptr_t pos)
Get an element of a dense array.
MLIR_CAPI_EXPORTED double mlirDenseElementsAttrGetDoubleValue(MlirAttribute attr, intptr_t pos)
ReferrentTy * get() const
Definition: PybindUtils.h:53
MLIR_CAPI_EXPORTED intptr_t mlirDenseArrayGetNumElements(MlirAttribute attr)
Get the size of a dense array.
MLIR_CAPI_EXPORTED bool mlirTypeIsAF32(MlirType type)
Checks whether the given type is an f32 type.
MLIR_CAPI_EXPORTED MlirAttribute mlirBoolAttrGet(MlirContext ctx, int value)
Creates a bool attribute in the given context with the given value.
MLIR_CAPI_EXPORTED bool mlirTypeIsAShaped(MlirType type)
Checks whether the given type is a Shaped type.
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseF32ArrayGet(MlirContext ctx, intptr_t size, float const *values)
Named MLIR attribute.
Definition: IR.h:74
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 int64_t mlirShapedTypeGetDimSize(MlirType type, intptr_t dim)
Returns the dim-th dimension of the given ranked shaped type.
MLIR_CAPI_EXPORTED bool mlirTypeIsAInteger(MlirType type)
Checks whether the given type is an integer type.
MLIR_CAPI_EXPORTED int64_t mlirDenseElementsAttrGetInt64Value(MlirAttribute attr, intptr_t pos)
static PyMlirContextRef forContext(MlirContext context)
Returns a context reference for the singleton PyMlirContext wrapper for the given context...
Definition: IRCore.cpp:480
MLIR_CAPI_EXPORTED MlirType mlirF32TypeGet(MlirContext ctx)
Creates an f32 type in the given context.
Used in function arguments when None should resolve to the current context manager set instance...
Definition: IRModule.h:258
MLIR_CAPI_EXPORTED MlirContext mlirAttributeGetContext(MlirAttribute attribute)
Gets the context that an attribute was created with.
Definition: IR.cpp:751
static constexpr const bool value
MlirAttribute get() const
Definition: IRModule.h:821
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 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 bool mlirIntegerTypeIsSigned(MlirType type)
Checks whether the given integer type is signed.
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseF64Array(MlirAttribute attr)
MLIR_CAPI_EXPORTED uint16_t mlirDenseElementsAttrGetUInt16Value(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED bool mlirAttributeIsAArray(MlirAttribute attr)
Checks whether the given attribute is an array attribute.
MLIR_CAPI_EXPORTED MlirType mlirTypeAttrGetValue(MlirAttribute attr)
Returns the type stored in the given type attribute.
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseBoolArray(MlirAttribute attr)
Checks whether the given attribute is a dense array attribute.
MLIR_CAPI_EXPORTED MlirType mlirF64TypeGet(MlirContext ctx)
Creates a f64 type in the given context.
Wrapper around the generic MlirType.
Definition: IRModule.h:745
MLIR_CAPI_EXPORTED intptr_t mlirArrayAttrGetNumElements(MlirAttribute attr)
Returns the number of elements stored in the given array attribute.
void populateIRAttributes(pybind11::module &m)
MLIR_CAPI_EXPORTED MlirStringRef mlirFlatSymbolRefAttrGetValue(MlirAttribute attr)
Returns the referenced symbol as a string reference.
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseFPElements(MlirAttribute attr)
MLIR_CAPI_EXPORTED intptr_t mlirDictionaryAttrGetNumElements(MlirAttribute attr)
Returns the number of attributes contained in a dictionary attribute.
MLIR_CAPI_EXPORTED int64_t mlirDenseI64ArrayGetElement(MlirAttribute attr, intptr_t pos)
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 MlirType mlirIntegerTypeSignedGet(MlirContext ctx, unsigned bitwidth)
Creates a signed integer type of the given bitwidth in the context.
MLIR_CAPI_EXPORTED unsigned mlirIntegerTypeGetWidth(MlirType type)
Returns the bitwidth of an integer type.
MLIR_CAPI_EXPORTED bool mlirIntegerTypeIsUnsigned(MlirType type)
Checks whether the given integer type is unsigned.
MLIR_CAPI_EXPORTED int64_t mlirShapedTypeGetRank(MlirType type)
Returns the rank of the given ranked shaped type.
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 bool mlirAttributeIsADenseIntElements(MlirAttribute attr)
pybind11::error_already_set SetPyError(PyObject *excClass, const llvm::Twine &message)
Definition: PybindUtils.cpp:12
MlirAffineMap get() const
Definition: IRModule.h:973
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 MlirNamedAttribute mlirNamedAttributeGet(MlirIdentifier name, MlirAttribute attr)
Associates an attribute with the name. Takes ownership of neither.
Definition: IR.cpp:778
Wrapper around the generic MlirAttribute.
Definition: IRModule.h:815
MLIR_CAPI_EXPORTED bool mlirAttributeIsAType(MlirAttribute attr)
Checks whether the given attribute is a type attribute.
MLIR_CAPI_EXPORTED int16_t mlirDenseI16ArrayGetElement(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED bool mlirTypeEqual(MlirType t1, MlirType t2)
Checks if two types are equal.
Definition: IR.cpp:732
MLIR_CAPI_EXPORTED MlirStringRef mlirOpaqueAttrGetData(MlirAttribute attr)
Returns the raw data as a string reference.
MLIR_CAPI_EXPORTED uint64_t mlirDenseElementsAttrGetUInt64Value(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseI64ArrayGet(MlirContext ctx, intptr_t size, int64_t const *values)
MLIR_CAPI_EXPORTED int8_t mlirDenseI8ArrayGetElement(MlirAttribute attr, intptr_t pos)
size_t length
Length of the fragment.
Definition: Support.h:73
MLIR_CAPI_EXPORTED MlirType mlirF16TypeGet(MlirContext ctx)
Creates an f16 type in the given context.
MLIR_CAPI_EXPORTED MlirStringRef mlirStringAttrGetValue(MlirAttribute attr)
Returns the attribute values as a string reference.
MlirIdentifier name
Definition: IR.h:75
MlirType get() const
Definition: IRModule.h:751
MLIR_CAPI_EXPORTED MlirType mlirIntegerTypeUnsignedGet(MlirContext ctx, unsigned bitwidth)
Creates an unsigned integer type of the given bitwidth in the context.
static MlirStringRef mlirStringRefCreate(const char *str, size_t length)
Constructs a string reference from the pointer and length.
Definition: Support.h:80
MLIR_CAPI_EXPORTED bool mlirDenseElementsAttrIsSplat(MlirAttribute attr)
Checks whether the given dense elements attribute contains a single replicated value (splat)...
MLIR_CAPI_EXPORTED int8_t mlirDenseElementsAttrGetInt8Value(MlirAttribute attr, intptr_t pos)
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.
MLIR_CAPI_EXPORTED MlirAttribute mlirAttributeGetNull()
Returns an empty attribute.
MLIR_CAPI_EXPORTED MlirAttribute mlirStringAttrTypedGet(MlirType type, 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. ...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:72
MLIR_CAPI_EXPORTED MlirAttribute mlirArrayAttrGetElement(MlirAttribute attr, intptr_t pos)
Returns pos-th element stored in the given array attribute.
MLIR_CAPI_EXPORTED MlirContext mlirTypeGetContext(MlirType type)
Gets the context that a type was created with.
Definition: IR.cpp:724
A pointer to a sized fragment of a string, not necessarily null-terminated.
Definition: Support.h:71
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 mlirAttributeIsAFloat(MlirAttribute attr)
Checks whether the given attribute is a floating point 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...
PyMlirContextRef & getContext()
Accesses the context reference.
Definition: IRModule.h:278
MlirAttribute attribute
Definition: IR.h:76
Represents a Python MlirNamedAttr, carrying an optional owned name.
Definition: IRModule.h:839
MLIR_CAPI_EXPORTED int32_t mlirDenseI32ArrayGetElement(MlirAttribute attr, intptr_t pos)
CRTP base classes for Python attributes that subclass Attribute and should be castable from it (i...
Definition: IRModule.h:865
MLIR_CAPI_EXPORTED uint32_t mlirDenseElementsAttrGetUInt32Value(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED bool mlirAttributeIsAString(MlirAttribute attr)
Checks whether the given attribute is a string 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 mlirTypeIsAIndex(MlirType type)
Checks whether the given type is an index type.
MLIR_CAPI_EXPORTED bool mlirAttributeIsABool(MlirAttribute attr)
Checks whether the given attribute is a bool attribute.
MLIR_CAPI_EXPORTED const void * mlirDenseElementsAttrGetRawData(MlirAttribute attr)
Returns the raw data of the given dense elements 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 bool mlirAttributeIsADenseF32Array(MlirAttribute attr)
MLIR_CAPI_EXPORTED float mlirDenseElementsAttrGetFloatValue(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED bool mlirIntegerTypeIsSignless(MlirType type)
Checks whether the given integer type is signless.
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 int32_t mlirDenseElementsAttrGetInt32Value(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED MlirIdentifier mlirIdentifierGet(MlirContext context, MlirStringRef str)
Gets an identifier with the given string value.
Definition: IR.cpp:787
MLIR_CAPI_EXPORTED bool mlirAttributeIsADictionary(MlirAttribute attr)
Checks whether the given attribute is a dictionary attribute.
MLIR_CAPI_EXPORTED MlirType mlirShapedTypeGetElementType(MlirType type)
Returns the element type of the shaped type.
MLIR_CAPI_EXPORTED MlirStringRef mlirIdentifierStr(MlirIdentifier ident)
Gets the string value of the identifier.
Definition: IR.cpp:799
MLIR_CAPI_EXPORTED double mlirDenseF64ArrayGetElement(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED bool mlirBoolAttrGetValue(MlirAttribute attr)
Returns the value stored in the given bool attribute.
MLIR_CAPI_EXPORTED bool mlirAttributeIsADenseI8Array(MlirAttribute attr)
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.
static const char kDenseElementsAttrGetDocstring[]
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseI16ArrayGet(MlirContext ctx, intptr_t size, int16_t const *values)
MLIR_CAPI_EXPORTED bool mlirTypeIsAF64(MlirType type)
Checks whether the given type is an f64 type.
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseI8ArrayGet(MlirContext ctx, intptr_t size, int8_t const *values)
MLIR_CAPI_EXPORTED float mlirDenseF32ArrayGetElement(MlirAttribute attr, intptr_t pos)
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 mlirAttributeIsAFlatSymbolRef(MlirAttribute attr)
Checks whether the given attribute is a flat symbol reference attribute.
MLIR_CAPI_EXPORTED MlirAttribute mlirUnitAttrGet(MlirContext ctx)
Creates a unit attribute in the given context.
MLIR_CAPI_EXPORTED bool mlirAttributeIsAUnit(MlirAttribute attr)
Checks whether the given attribute is a unit attribute.
MLIR_CAPI_EXPORTED bool mlirShapedTypeHasStaticShape(MlirType type)
Checks whether the given shaped type has a static shape.
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 bool mlirTypeIsAF16(MlirType type)
Checks whether the given type is an f16 type.
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 MlirNamedAttribute mlirDictionaryAttrGetElement(MlirAttribute attr, intptr_t pos)
Returns pos-th element of the given dictionary attribute.
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...