MLIR 23.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 <cstdint>
10#include <optional>
11#include <string>
12#include <string_view>
13#include <utility>
14
16#include "mlir-c/BuiltinTypes.h"
22#include "llvm/ADT/ScopeExit.h"
23#include "llvm/Support/raw_ostream.h"
24
25namespace nb = nanobind;
26using namespace nanobind::literals;
27using namespace mlir;
29
31
32//------------------------------------------------------------------------------
33// Docstrings (trivial, non-duplicated docstrings are included inline).
34//------------------------------------------------------------------------------
35
36static const char kDenseElementsAttrGetDocstring[] =
37 R"(Gets a DenseElementsAttr from a Python buffer or array.
38
39When `type` is not provided, then some limited type inferencing is done based
40on the buffer format. Support presently exists for 8/16/32/64 signed and
41unsigned integers and float16/float32/float64. DenseElementsAttrs of these
42types can also be converted back to a corresponding buffer.
43
44For conversions outside of these types, a `type=` must be explicitly provided
45and the buffer contents must be bit-castable to the MLIR internal
46representation:
47
48 * Integer types (except for i1): the buffer must be byte aligned to the
49 next byte boundary.
50 * Floating point types: Must be bit-castable to the given floating point
51 size.
52 * i1 (bool): Bit packed into 8bit words where the bit pattern matches a
53 row major ordering. An arbitrary Numpy `bool_` array can be bit packed to
54 this specification with: `np.packbits(ary, axis=None, bitorder='little')`.
55
56If a single element buffer is passed (or for i1, a single byte with value 0
57or 255), then a splat will be created.
58
59Args:
60 array: The array or buffer to convert.
61 signless: If inferring an appropriate MLIR type, use signless types for
62 integers (defaults True).
63 type: Skips inference of the MLIR element type and uses this instead. The
64 storage size must be consistent with the actual contents of the buffer.
65 shape: Overrides the shape of the buffer when constructing the MLIR
66 shaped type. This is needed when the physical and logical shape differ (as
67 for i1).
68 context: Explicit context, if not from context manager.
69
70Returns:
71 DenseElementsAttr on success.
72
73Raises:
74 ValueError: If the type of the buffer or array cannot be matched to an MLIR
75 type or if the buffer does not meet expectations.
76)";
77
79 R"(Gets a DenseElementsAttr from a Python list of attributes.
80
81Note that it can be expensive to construct attributes individually.
82For a large number of elements, consider using a Python buffer or array instead.
83
84Args:
85 attrs: A list of attributes.
86 type: The desired shape and type of the resulting DenseElementsAttr.
87 If not provided, the element type is determined based on the type
88 of the 0th attribute and the shape is `[len(attrs)]`.
89 context: Explicit context, if not from context manager.
90
91Returns:
92 DenseElementsAttr on success.
93
94Raises:
95 ValueError: If the type of the attributes does not match the type
96 specified by `shaped_type`.
97)";
98
100 R"(Gets a DenseResourceElementsAttr from a Python buffer or array.
101
102This function does minimal validation or massaging of the data, and it is
103up to the caller to ensure that the buffer meets the characteristics
104implied by the shape.
105
106The backing buffer and any user objects will be retained for the lifetime
107of the resource blob. This is typically bounded to the context but the
108resource can have a shorter lifespan depending on how it is used in
109subsequent processing.
110
111Args:
112 buffer: The array or buffer to convert.
113 name: Name to provide to the resource (may be changed upon collision).
114 type: The explicit ShapedType to construct the attribute with.
115 context: Explicit context, if not from context manager.
116
117Returns:
118 DenseResourceElementsAttr on success.
119
120Raises:
121 ValueError: If the type of the buffer or array cannot be matched to an MLIR
122 type or if the buffer does not meet expectations.
123)";
124
125namespace mlir {
126namespace python {
128
130 void *ptr, ssize_t itemsize, const char *format, ssize_t ndim,
132 bool readonly,
133 std::unique_ptr<Py_buffer, void (*)(Py_buffer *)> owned_view_in)
135 shape(std::move(shape_in)), strides(std::move(strides_in)),
136 readonly(readonly), owned_view(std::move(owned_view_in)) {
137 size = 1;
138 for (ssize_t i = 0; i < ndim; ++i) {
139 size *= shape[i];
140 }
141}
142
143nb_buffer_info nb_buffer::request() const {
144 int flags = PyBUF_STRIDES | PyBUF_FORMAT;
145 auto *view = new Py_buffer();
146 if (PyObject_GetBuffer(ptr(), view, flags) != 0) {
147 delete view;
148 throw nb::python_error();
149 }
150 return nb_buffer_info(view);
151}
152
153template <>
155 static const char *format() { return "?"; }
156};
157template <>
158struct nb_format_descriptor<int8_t> {
159 static const char *format() { return "b"; }
160};
161template <>
162struct nb_format_descriptor<uint8_t> {
163 static const char *format() { return "B"; }
164};
165template <>
166struct nb_format_descriptor<int16_t> {
167 static const char *format() { return "h"; }
168};
169template <>
170struct nb_format_descriptor<uint16_t> {
171 static const char *format() { return "H"; }
172};
173template <>
174struct nb_format_descriptor<int32_t> {
175 static const char *format() { return "i"; }
176};
177template <>
178struct nb_format_descriptor<uint32_t> {
179 static const char *format() { return "I"; }
180};
181template <>
183 static const char *format() { return "q"; }
184};
185template <>
186struct nb_format_descriptor<uint64_t> {
187 static const char *format() { return "Q"; }
188};
189template <>
190struct nb_format_descriptor<float> {
191 static const char *format() { return "f"; }
192};
193template <>
194struct nb_format_descriptor<double> {
195 static const char *format() { return "d"; }
196};
197
199 c.def_static(
200 "get",
201 [](PyAffineMap &affineMap) {
202 MlirAttribute attr = mlirAffineMapAttrGet(affineMap.get());
203 return PyAffineMapAttribute(affineMap.getContext(), attr);
204 },
205 nb::arg("affine_map"), "Gets an attribute wrapping an AffineMap.");
206 c.def_prop_ro(
207 "value",
208 [](PyAffineMapAttribute &self) {
210 },
211 "Returns the value of the AffineMap attribute");
212}
213
215 c.def_static(
216 "get",
217 [](PyIntegerSet &integerSet) {
218 MlirAttribute attr = mlirIntegerSetAttrGet(integerSet.get());
219 return PyIntegerSetAttribute(integerSet.getContext(), attr);
220 },
221 nb::arg("integer_set"), "Gets an attribute wrapping an IntegerSet.");
222}
223
224nb::typed<nb::object, PyAttribute>
226 // TODO: Throw is an inefficient way to stop iteration.
227 if (PyArrayAttribute::PyArrayAttributeIterator::nextIndex >=
229 PyArrayAttribute::PyArrayAttributeIterator::attr.get()))
230 throw nb::stop_iteration();
231 return PyAttribute(
232 this->PyArrayAttribute::PyArrayAttributeIterator::attr
233 .getContext(),
235 PyArrayAttribute::PyArrayAttributeIterator::attr.get(),
236 PyArrayAttribute::PyArrayAttributeIterator::nextIndex++))
237 .maybeDownCast();
238}
239
241 nb::class_<PyArrayAttributeIterator>(m, "ArrayAttributeIterator")
242 .def("__iter__", &PyArrayAttributeIterator::dunderIter)
243 .def("__next__", &PyArrayAttributeIterator::dunderNext);
244}
245
246MlirAttribute PyArrayAttribute::getItem(intptr_t i) const {
247 return mlirArrayAttrGetElement(*this, i);
248}
249
251 c.def_static(
252 "get",
253 [](const nb::list &attributes, DefaultingPyMlirContext context) {
254 SmallVector<MlirAttribute> mlirAttributes;
255 mlirAttributes.reserve(nb::len(attributes));
256 for (auto attribute : attributes) {
257 mlirAttributes.push_back(pyTryCast<PyAttribute>(attribute));
258 }
259 MlirAttribute attr = mlirArrayAttrGet(
260 context->get(), mlirAttributes.size(), mlirAttributes.data());
261 return PyArrayAttribute(context->getRef(), attr);
262 },
263 nb::arg("attributes"), nb::arg("context") = nb::none(),
264 "Gets a uniqued Array attribute");
265 c.def("__getitem__",
266 [](PyArrayAttribute &arr,
267 intptr_t i) -> nb::typed<nb::object, PyAttribute> {
268 if (i >= mlirArrayAttrGetNumElements(arr))
269 throw nb::index_error("ArrayAttribute index out of range");
270 return PyAttribute(arr.getContext(), arr.getItem(i)).maybeDownCast();
271 })
272 .def("__len__",
273 [](const PyArrayAttribute &arr) {
274 return mlirArrayAttrGetNumElements(arr);
275 })
276 .def("__iter__", [](const PyArrayAttribute &arr) {
277 return PyArrayAttributeIterator(arr);
278 });
279 c.def("__add__", [](PyArrayAttribute arr, const nb::list &extras) {
280 std::vector<MlirAttribute> attributes;
281 intptr_t numOldElements = mlirArrayAttrGetNumElements(arr);
282 attributes.reserve(numOldElements + nb::len(extras));
283 for (intptr_t i = 0; i < numOldElements; ++i)
284 attributes.push_back(arr.getItem(i));
285 for (nb::handle attr : extras)
286 attributes.push_back(pyTryCast<PyAttribute>(attr));
287 MlirAttribute arrayAttr = mlirArrayAttrGet(
288 arr.getContext()->get(), attributes.size(), attributes.data());
289 return PyArrayAttribute(arr.getContext(), arrayAttr);
290 });
291}
293 c.def_static(
294 "get",
295 [](PyType &type, double value, DefaultingPyLocation loc) {
296 PyMlirContext::ErrorCapture errors(loc->getContext());
297 MlirAttribute attr = mlirFloatAttrDoubleGetChecked(loc, type, value);
298 if (mlirAttributeIsNull(attr))
299 throw MLIRError("Invalid attribute", errors.take());
300 return PyFloatAttribute(type.getContext(), attr);
301 },
302 nb::arg("type"), nb::arg("value"), nb::arg("loc") = nb::none(),
303 "Gets an uniqued float point attribute associated to a type");
304 c.def_static(
305 "get_unchecked",
306 [](PyType &type, double value, DefaultingPyMlirContext context) {
307 PyMlirContext::ErrorCapture errors(context->getRef());
308 MlirAttribute attr =
309 mlirFloatAttrDoubleGet(context.get()->get(), type, value);
310 if (mlirAttributeIsNull(attr))
311 throw MLIRError("Invalid attribute", errors.take());
312 return PyFloatAttribute(type.getContext(), attr);
313 },
314 nb::arg("type"), nb::arg("value"), nb::arg("context") = nb::none(),
315 "Gets an uniqued float point attribute associated to a type");
316 c.def_static(
317 "get_f32",
318 [](double value, DefaultingPyMlirContext context) {
319 MlirAttribute attr = mlirFloatAttrDoubleGet(
320 context->get(), mlirF32TypeGet(context->get()), value);
321 return PyFloatAttribute(context->getRef(), attr);
322 },
323 nb::arg("value"), nb::arg("context") = nb::none(),
324 "Gets an uniqued float point attribute associated to a f32 type");
325 c.def_static(
326 "get_f64",
327 [](double value, DefaultingPyMlirContext context) {
328 MlirAttribute attr = mlirFloatAttrDoubleGet(
329 context->get(), mlirF64TypeGet(context->get()), value);
330 return PyFloatAttribute(context->getRef(), attr);
331 },
332 nb::arg("value"), nb::arg("context") = nb::none(),
333 "Gets an uniqued float point attribute associated to a f64 type");
334 c.def_prop_ro("value", mlirFloatAttrGetValueDouble,
335 "Returns the value of the float attribute");
336 c.def("__float__", mlirFloatAttrGetValueDouble,
337 "Converts the value of the float attribute to a Python float");
338}
339
341 c.def_static(
342 "get",
343 [](PyType &type, int64_t value) {
344 MlirAttribute attr = mlirIntegerAttrGet(type, value);
345 return PyIntegerAttribute(type.getContext(), attr);
346 },
347 nb::arg("type"), nb::arg("value"),
348 "Gets an uniqued integer attribute associated to a type");
349 c.def_prop_ro("value", toPyInt, "Returns the value of the integer attribute");
350 c.def("__int__", toPyInt,
351 "Converts the value of the integer attribute to a Python int");
352 c.def_prop_ro_static(
353 "static_typeid",
354 [](nb::object & /*class*/) {
356 },
357 nb::sig("def static_typeid(/) -> TypeID"));
358}
359
360int64_t PyIntegerAttribute::toPyInt(PyIntegerAttribute &self) {
361 MlirType type = mlirAttributeGetType(self);
363 return mlirIntegerAttrGetValueInt(self);
364 if (mlirIntegerTypeIsSigned(type))
365 return mlirIntegerAttrGetValueSInt(self);
366 return mlirIntegerAttrGetValueUInt(self);
367}
368
370 c.def_static(
371 "get",
372 [](bool value, DefaultingPyMlirContext context) {
373 MlirAttribute attr = mlirBoolAttrGet(context->get(), value);
374 return PyBoolAttribute(context->getRef(), attr);
375 },
376 nb::arg("value"), nb::arg("context") = nb::none(),
377 "Gets an uniqued bool attribute");
378 c.def_prop_ro("value", mlirBoolAttrGetValue,
379 "Returns the value of the bool attribute");
380 c.def("__bool__", mlirBoolAttrGetValue,
381 "Converts the value of the bool attribute to a Python bool");
382}
383
385PySymbolRefAttribute::fromList(const std::vector<std::string> &symbols,
386 PyMlirContext &context) {
387 if (symbols.empty())
388 throw std::runtime_error("SymbolRefAttr must be composed of at least "
389 "one symbol.");
390 MlirStringRef rootSymbol = toMlirStringRef(symbols[0]);
391 SmallVector<MlirAttribute, 3> referenceAttrs;
392 for (size_t i = 1; i < symbols.size(); ++i) {
393 referenceAttrs.push_back(
394 mlirFlatSymbolRefAttrGet(context.get(), toMlirStringRef(symbols[i])));
395 }
396 return PySymbolRefAttribute(context.getRef(),
397 mlirSymbolRefAttrGet(context.get(), rootSymbol,
398 referenceAttrs.size(),
399 referenceAttrs.data()));
400}
401
403 c.def_static(
404 "get",
405 [](const std::vector<std::string> &symbols,
406 DefaultingPyMlirContext context) {
407 return PySymbolRefAttribute::fromList(symbols, context.resolve());
408 },
409 nb::arg("symbols"), nb::arg("context") = nb::none(),
410 "Gets a uniqued SymbolRef attribute from a list of symbol names");
411 c.def_prop_ro(
412 "value",
413 [](PySymbolRefAttribute &self) {
414 std::vector<std::string> symbols = {
416 for (int i = 0; i < mlirSymbolRefAttrGetNumNestedReferences(self); ++i)
417 symbols.push_back(
420 .str());
421 return symbols;
422 },
423 "Returns the value of the SymbolRef attribute as a list[str]");
424}
425
427 c.def_static(
428 "get",
429 [](const std::string &value, DefaultingPyMlirContext context) {
430 MlirAttribute attr =
431 mlirFlatSymbolRefAttrGet(context->get(), toMlirStringRef(value));
432 return PyFlatSymbolRefAttribute(context->getRef(), attr);
433 },
434 nb::arg("value"), nb::arg("context") = nb::none(),
435 "Gets a uniqued FlatSymbolRef attribute");
436 c.def_prop_ro(
437 "value",
438 [](PyFlatSymbolRefAttribute &self) {
440 return nb::str(stringRef.data, stringRef.length);
441 },
442 "Returns the value of the FlatSymbolRef attribute as a string");
443}
444
446 c.def_static(
447 "get",
448 [](const std::string &dialectNamespace, const nb_buffer &buffer,
449 PyType &type, DefaultingPyMlirContext context) {
450 const nb_buffer_info bufferInfo = buffer.request();
451 intptr_t bufferSize = bufferInfo.size;
452 MlirAttribute attr = mlirOpaqueAttrGet(
453 context->get(), toMlirStringRef(dialectNamespace), bufferSize,
454 static_cast<char *>(bufferInfo.ptr), type);
455 return PyOpaqueAttribute(context->getRef(), attr);
456 },
457 nb::arg("dialect_namespace"), nb::arg("buffer"), nb::arg("type"),
458 nb::arg("context") = nb::none(),
459 // clang-format off
460 nb::sig("def get(dialect_namespace: str, buffer: typing_extensions.Buffer, type: Type, context: Context | None = None) -> OpaqueAttr"),
461 // clang-format on
462 "Gets an Opaque attribute.");
463 c.def_prop_ro(
464 "dialect_namespace",
465 [](PyOpaqueAttribute &self) {
467 return nb::str(stringRef.data, stringRef.length);
468 },
469 "Returns the dialect namespace for the Opaque attribute as a string");
470 c.def_prop_ro(
471 "data",
472 [](PyOpaqueAttribute &self) {
473 MlirStringRef stringRef = mlirOpaqueAttrGetData(self);
474 return nb::bytes(stringRef.data, stringRef.length);
475 },
476 "Returns the data for the Opaqued attributes as `bytes`");
477}
478
480PyDenseElementsAttribute::getFromList(const nb::list &attributes,
481 std::optional<PyType> explicitType,
482 DefaultingPyMlirContext contextWrapper) {
483 const size_t numAttributes = nb::len(attributes);
484 if (numAttributes == 0)
485 throw nb::value_error("Attributes list must be non-empty.");
486
487 MlirType shapedType;
488 if (explicitType) {
489 if ((!mlirTypeIsAShaped(*explicitType) ||
490 !mlirShapedTypeHasStaticShape(*explicitType))) {
491
492 std::string message;
493 llvm::raw_string_ostream os(message);
494 os << "Expected a static ShapedType for the shaped_type parameter: "
495 << nb::cast<std::string>(nb::repr(nb::cast(*explicitType)));
496 throw nb::value_error(message.c_str());
497 }
498 shapedType = *explicitType;
499 } else {
500 SmallVector<int64_t> shape = {static_cast<int64_t>(numAttributes)};
501 shapedType = mlirRankedTensorTypeGet(
502 shape.size(), shape.data(),
505 }
506
507 SmallVector<MlirAttribute> mlirAttributes;
508 mlirAttributes.reserve(numAttributes);
509 for (const nb::handle &attribute : attributes) {
510 MlirAttribute mlirAttribute = pyTryCast<PyAttribute>(attribute);
511 MlirType attrType = mlirAttributeGetType(mlirAttribute);
512 mlirAttributes.push_back(mlirAttribute);
513
514 if (!mlirTypeEqual(mlirShapedTypeGetElementType(shapedType), attrType)) {
515 std::string message;
516 llvm::raw_string_ostream os(message);
517 os << "All attributes must be of the same type and match "
518 << "the type parameter: expected="
519 << nb::cast<std::string>(nb::repr(nb::cast(shapedType)))
520 << ", but got=" << nb::cast<std::string>(nb::repr(nb::cast(attrType)));
521 throw nb::value_error(message.c_str());
522 }
523 }
524
525 MlirAttribute elements = mlirDenseElementsAttrGet(
526 shapedType, mlirAttributes.size(), mlirAttributes.data());
527
528 return PyDenseElementsAttribute(contextWrapper->getRef(), elements);
529}
530
532 const nb_buffer &array, bool signless,
533 const std::optional<PyType> &explicitType,
534 std::optional<std::vector<int64_t>> explicitShape,
535 DefaultingPyMlirContext contextWrapper) {
536 // Request a contiguous view. In exotic cases, this will cause a copy.
537 int flags = PyBUF_ND;
538 if (!explicitType) {
539 flags |= PyBUF_FORMAT;
540 }
541 Py_buffer view;
542 if (PyObject_GetBuffer(array.ptr(), &view, flags) != 0) {
543 throw nb::python_error();
544 }
545 llvm::scope_exit freeBuffer([&]() { PyBuffer_Release(&view); });
546
547 MlirContext context = contextWrapper->get();
548 MlirAttribute attr = getAttributeFromBuffer(
549 view, signless, explicitType, std::move(explicitShape), context);
550 if (mlirAttributeIsNull(attr)) {
551 throw std::invalid_argument(
552 "DenseElementsAttr could not be constructed from the given buffer. "
553 "This may mean that the Python buffer layout does not match that "
554 "MLIR expected layout and is a bug.");
555 }
556 return PyDenseElementsAttribute(contextWrapper->getRef(), attr);
557}
558
561 PyAttribute &elementAttr) {
562 auto contextWrapper =
564 if (!mlirAttributeIsAInteger(elementAttr) &&
565 !mlirAttributeIsAFloat(elementAttr)) {
566 std::string message = "Illegal element type for DenseElementsAttr: ";
567 message.append(nb::cast<std::string>(nb::repr(nb::cast(elementAttr))));
568 throw nb::value_error(message.c_str());
569 }
570 if (!mlirTypeIsAShaped(shapedType) ||
571 !mlirShapedTypeHasStaticShape(shapedType)) {
572 std::string message =
573 "Expected a static ShapedType for the shaped_type parameter: ";
574 message.append(nb::cast<std::string>(nb::repr(nb::cast(shapedType))));
575 throw nb::value_error(message.c_str());
576 }
577 MlirType shapedElementType = mlirShapedTypeGetElementType(shapedType);
578 MlirType attrType = mlirAttributeGetType(elementAttr);
579 if (!mlirTypeEqual(shapedElementType, attrType)) {
580 std::string message =
581 "Shaped element type and attribute type must be equal: shaped=";
582 message.append(nb::cast<std::string>(nb::repr(nb::cast(shapedType))));
583 message.append(", element=");
584 message.append(nb::cast<std::string>(nb::repr(nb::cast(elementAttr))));
585 throw nb::value_error(message.c_str());
586 }
587
588 MlirAttribute elements =
589 mlirDenseElementsAttrSplatGet(shapedType, elementAttr);
590 return PyDenseElementsAttribute(contextWrapper->getRef(), elements);
591}
592
596
597std::unique_ptr<nb_buffer_info> PyDenseElementsAttribute::accessBuffer() {
598 MlirType shapedType = mlirAttributeGetType(*this);
599 MlirType elementType = mlirShapedTypeGetElementType(shapedType);
600 std::string format;
601
602 if (mlirTypeIsAF32(elementType)) {
603 // f32
604 return bufferInfo<float>(shapedType);
605 }
606 if (mlirTypeIsAF64(elementType)) {
607 // f64
608 return bufferInfo<double>(shapedType);
609 }
610 if (mlirTypeIsAF16(elementType)) {
611 // f16
612 return bufferInfo<uint16_t>(shapedType, "e");
613 }
614 if (mlirTypeIsAIndex(elementType)) {
615 // Same as IndexType::kInternalStorageBitWidth
616 return bufferInfo<int64_t>(shapedType);
617 }
618 if (mlirTypeIsAInteger(elementType) &&
619 mlirIntegerTypeGetWidth(elementType) == 32) {
620 if (mlirIntegerTypeIsSignless(elementType) ||
621 mlirIntegerTypeIsSigned(elementType)) {
622 // i32
623 return bufferInfo<int32_t>(shapedType);
624 }
625 if (mlirIntegerTypeIsUnsigned(elementType)) {
626 // unsigned i32
627 return bufferInfo<uint32_t>(shapedType);
628 }
629 } else if (mlirTypeIsAInteger(elementType) &&
630 mlirIntegerTypeGetWidth(elementType) == 64) {
631 if (mlirIntegerTypeIsSignless(elementType) ||
632 mlirIntegerTypeIsSigned(elementType)) {
633 // i64
634 return bufferInfo<int64_t>(shapedType);
635 }
636 if (mlirIntegerTypeIsUnsigned(elementType)) {
637 // unsigned i64
638 return bufferInfo<uint64_t>(shapedType);
639 }
640 } else if (mlirTypeIsAInteger(elementType) &&
641 mlirIntegerTypeGetWidth(elementType) == 8) {
642 if (mlirIntegerTypeIsSignless(elementType) ||
643 mlirIntegerTypeIsSigned(elementType)) {
644 // i8
645 return bufferInfo<int8_t>(shapedType);
646 }
647 if (mlirIntegerTypeIsUnsigned(elementType)) {
648 // unsigned i8
649 return bufferInfo<uint8_t>(shapedType);
650 }
651 } else if (mlirTypeIsAInteger(elementType) &&
652 mlirIntegerTypeGetWidth(elementType) == 16) {
653 if (mlirIntegerTypeIsSignless(elementType) ||
654 mlirIntegerTypeIsSigned(elementType)) {
655 // i16
656 return bufferInfo<int16_t>(shapedType);
657 }
658 if (mlirIntegerTypeIsUnsigned(elementType)) {
659 // unsigned i16
660 return bufferInfo<uint16_t>(shapedType);
661 }
662 } else if (mlirTypeIsAInteger(elementType) &&
663 mlirIntegerTypeGetWidth(elementType) == 1) {
664 // i1 / bool
665 // We can not send the buffer directly back to Python, because the i1
666 // values are bitpacked within MLIR. We call numpy's unpackbits function
667 // to convert the bytes.
668 return getBooleanBufferFromBitpackedAttribute();
669 }
670
671 // TODO: Currently crashes the program.
672 // Reported as https://github.com/pybind/pybind11/issues/3336
673 throw std::invalid_argument(
674 "unsupported data type for conversion to Python buffer");
675}
676
678#if PY_VERSION_HEX < 0x03090000
679 PyTypeObject *tp = reinterpret_cast<PyTypeObject *>(c.ptr());
680 tp->tp_as_buffer->bf_getbuffer = PyDenseElementsAttribute::bf_getbuffer;
681 tp->tp_as_buffer->bf_releasebuffer =
682 PyDenseElementsAttribute::bf_releasebuffer;
683#endif
684 c.def("__len__", &PyDenseElementsAttribute::dunderLen)
685 .def_static(
686 "get", PyDenseElementsAttribute::getFromBuffer, nb::arg("array"),
687 nb::arg("signless") = true, nb::arg("type") = nb::none(),
688 nb::arg("shape") = nb::none(), nb::arg("context") = nb::none(),
689 // clang-format off
690 nb::sig("def get(array: typing_extensions.Buffer, signless: bool = True, type: Type | None = None, shape: Sequence[int] | None = None, context: Context | None = None) -> DenseElementsAttr"),
691 // clang-format on
693 .def_static("get", PyDenseElementsAttribute::getFromList,
694 nb::arg("attrs"), nb::arg("type") = nb::none(),
695 nb::arg("context") = nb::none(),
697 .def_static("get_splat", PyDenseElementsAttribute::getSplat,
698 nb::arg("shaped_type"), nb::arg("element_attr"),
699 "Gets a DenseElementsAttr where all values are the same")
700 .def_prop_ro("is_splat",
701 [](PyDenseElementsAttribute &self) -> bool {
702 return mlirDenseElementsAttrIsSplat(self);
703 })
704 .def("get_splat_value",
706 -> nb::typed<nb::object, PyAttribute> {
708 throw nb::value_error(
709 "get_splat_value called on a non-splat attribute");
710 return PyAttribute(self.getContext(),
712 .maybeDownCast();
713 });
714}
715
716bool PyDenseElementsAttribute::isUnsignedIntegerFormat(
717 std::string_view format) {
718 if (format.empty())
719 return false;
720 char code = format[0];
721 return code == 'I' || code == 'B' || code == 'H' || code == 'L' ||
722 code == 'Q';
723}
724
725bool PyDenseElementsAttribute::isSignedIntegerFormat(std::string_view format) {
726 if (format.empty())
727 return false;
728 char code = format[0];
729 return code == 'i' || code == 'b' || code == 'h' || code == 'l' ||
730 code == 'q';
731}
732
733MlirType PyDenseElementsAttribute::getShapedType(
734 std::optional<MlirType> bulkLoadElementType,
735 std::optional<std::vector<int64_t>> explicitShape, Py_buffer &view) {
737 if (explicitShape) {
738 shape.append(explicitShape->begin(), explicitShape->end());
739 } else {
740 shape.append(view.shape, view.shape + view.ndim);
741 }
742
743 if (mlirTypeIsAShaped(*bulkLoadElementType)) {
744 if (explicitShape) {
745 throw std::invalid_argument("Shape can only be specified explicitly "
746 "when the type is not a shaped type.");
747 }
748 return *bulkLoadElementType;
749 }
750 MlirAttribute encodingAttr = mlirAttributeGetNull();
751 return mlirRankedTensorTypeGet(shape.size(), shape.data(),
752 *bulkLoadElementType, encodingAttr);
753}
754
755MlirAttribute PyDenseElementsAttribute::getAttributeFromBuffer(
756 Py_buffer &view, bool signless, std::optional<PyType> explicitType,
757 const std::optional<std::vector<int64_t>> &explicitShape,
758 MlirContext &context) {
759 // Detect format codes that are suitable for bulk loading. This includes
760 // all byte aligned integer and floating point types up to 8 bytes.
761 // Notably, this excludes exotics types which do not have a direct
762 // representation in the buffer protocol (i.e. complex, etc).
763 std::optional<MlirType> bulkLoadElementType;
764 if (explicitType) {
765 bulkLoadElementType = *explicitType;
766 } else {
767 std::string_view format(view.format);
768 if (format == "f") {
769 // f32
770 assert(view.itemsize == 4 && "mismatched array itemsize");
771 bulkLoadElementType = mlirF32TypeGet(context);
772 } else if (format == "d") {
773 // f64
774 assert(view.itemsize == 8 && "mismatched array itemsize");
775 bulkLoadElementType = mlirF64TypeGet(context);
776 } else if (format == "e") {
777 // f16
778 assert(view.itemsize == 2 && "mismatched array itemsize");
779 bulkLoadElementType = mlirF16TypeGet(context);
780 } else if (format == "?") {
781 // i1
782 // The i1 type needs to be bit-packed, so we will handle it separately
783 return getBitpackedAttributeFromBooleanBuffer(view, explicitShape,
784 context);
785 } else if (isSignedIntegerFormat(format)) {
786 if (view.itemsize == 4) {
787 // i32
788 bulkLoadElementType = signless ? mlirIntegerTypeGet(context, 32)
789 : mlirIntegerTypeSignedGet(context, 32);
790 } else if (view.itemsize == 8) {
791 // i64
792 bulkLoadElementType = signless ? mlirIntegerTypeGet(context, 64)
793 : mlirIntegerTypeSignedGet(context, 64);
794 } else if (view.itemsize == 1) {
795 // i8
796 bulkLoadElementType = signless ? mlirIntegerTypeGet(context, 8)
797 : mlirIntegerTypeSignedGet(context, 8);
798 } else if (view.itemsize == 2) {
799 // i16
800 bulkLoadElementType = signless ? mlirIntegerTypeGet(context, 16)
801 : mlirIntegerTypeSignedGet(context, 16);
802 }
803 } else if (isUnsignedIntegerFormat(format)) {
804 if (view.itemsize == 4) {
805 // unsigned i32
806 bulkLoadElementType = signless
807 ? mlirIntegerTypeGet(context, 32)
808 : mlirIntegerTypeUnsignedGet(context, 32);
809 } else if (view.itemsize == 8) {
810 // unsigned i64
811 bulkLoadElementType = signless
812 ? mlirIntegerTypeGet(context, 64)
813 : mlirIntegerTypeUnsignedGet(context, 64);
814 } else if (view.itemsize == 1) {
815 // i8
816 bulkLoadElementType = signless ? mlirIntegerTypeGet(context, 8)
817 : mlirIntegerTypeUnsignedGet(context, 8);
818 } else if (view.itemsize == 2) {
819 // i16
820 bulkLoadElementType = signless
821 ? mlirIntegerTypeGet(context, 16)
822 : mlirIntegerTypeUnsignedGet(context, 16);
823 }
824 }
825 if (!bulkLoadElementType) {
826 throw std::invalid_argument(
827 std::string("unimplemented array format conversion from format: ") +
828 std::string(format));
829 }
830 }
831
832 MlirType type = getShapedType(bulkLoadElementType, explicitShape, view);
833 return mlirDenseElementsAttrRawBufferGet(type, view.len, view.buf);
834}
835
836MlirAttribute PyDenseElementsAttribute::getBitpackedAttributeFromBooleanBuffer(
837 Py_buffer &view, std::optional<std::vector<int64_t>> explicitShape,
838 MlirContext &context) {
839 if (llvm::endianness::native != llvm::endianness::little) {
840 // Given we have no good way of testing the behavior on big-endian
841 // systems we will throw
842 throw nb::type_error("Constructing a bit-packed MLIR attribute is "
843 "unsupported on big-endian systems");
844 }
845 nb::ndarray<uint8_t, nb::numpy, nb::ndim<1>, nb::c_contig> unpackedArray(
846 /*data=*/static_cast<uint8_t *>(view.buf),
847 /*shape=*/{static_cast<size_t>(view.len)});
848
849 nb::module_ numpy = nb::module_::import_("numpy");
850 nb::object packbitsFunc = numpy.attr("packbits");
851 nb::object packedBooleans =
852 packbitsFunc(nb::cast(unpackedArray), "bitorder"_a = "little");
853 nb_buffer_info pythonBuffer = nb::cast<nb_buffer>(packedBooleans).request();
854
855 MlirType bitpackedType = getShapedType(mlirIntegerTypeGet(context, 1),
856 std::move(explicitShape), view);
857 assert(pythonBuffer.itemsize == 1 && "Packbits must return uint8");
858 // Notice that `mlirDenseElementsAttrRawBufferGet` copies the memory of
859 // packedBooleans, hence the MlirAttribute will remain valid even when
860 // packedBooleans get reclaimed by the end of the function.
861 return mlirDenseElementsAttrRawBufferGet(bitpackedType, pythonBuffer.size,
862 pythonBuffer.ptr);
863}
864
865std::unique_ptr<nb_buffer_info>
866PyDenseElementsAttribute::getBooleanBufferFromBitpackedAttribute() const {
867 if (llvm::endianness::native != llvm::endianness::little) {
868 // Given we have no good way of testing the behavior on big-endian
869 // systems we will throw
870 throw nb::type_error("Constructing a numpy array from a MLIR attribute "
871 "is unsupported on big-endian systems");
872 }
873
874 int64_t numBooleans = mlirElementsAttrGetNumElements(*this);
875 int64_t numBitpackedBytes = llvm::divideCeil(numBooleans, 8);
876 uint8_t *bitpackedData = static_cast<uint8_t *>(
877 const_cast<void *>(mlirDenseElementsAttrGetRawData(*this)));
878 nb::ndarray<uint8_t, nb::numpy, nb::ndim<1>, nb::c_contig> packedArray(
879 /*data=*/bitpackedData,
880 /*shape=*/{static_cast<size_t>(numBitpackedBytes)});
881
882 nb::module_ numpy = nb::module_::import_("numpy");
883 nb::object unpackbitsFunc = numpy.attr("unpackbits");
884 nb::object equalFunc = numpy.attr("equal");
885 nb::object reshapeFunc = numpy.attr("reshape");
886 nb::object unpackedBooleans =
887 unpackbitsFunc(nb::cast(packedArray), "bitorder"_a = "little");
888
889 // Unpackbits operates on bytes and gives back a flat 0 / 1 integer array.
890 // We need to:
891 // 1. Slice away the padded bits
892 // 2. Make the boolean array have the correct shape
893 // 3. Convert the array to a boolean array
894 unpackedBooleans = unpackedBooleans[nb::slice(
895 nb::int_(0), nb::int_(numBooleans), nb::int_(1))];
896 unpackedBooleans = equalFunc(unpackedBooleans, 1);
897
898 MlirType shapedType = mlirAttributeGetType(*this);
899 intptr_t rank = mlirShapedTypeGetRank(shapedType);
900 std::vector<intptr_t> shape(rank);
901 for (intptr_t i = 0; i < rank; ++i) {
902 shape[i] = mlirShapedTypeGetDimSize(shapedType, i);
903 }
904 unpackedBooleans = reshapeFunc(unpackedBooleans, shape);
905
906 // Make sure the returned nb::buffer_view claims ownership of the data
907 // in `pythonBuffer` so it remains valid when Python reads it
908 nb_buffer pythonBuffer = nb::cast<nb_buffer>(unpackedBooleans);
909 return std::make_unique<nb_buffer_info>(pythonBuffer.request());
910}
911
912PyType_Slot PyDenseElementsAttribute::slots[] = {
913// Python 3.8 doesn't allow setting the buffer protocol slots from a type spec.
914#if PY_VERSION_HEX >= 0x03090000
915 {Py_bf_getbuffer,
916 reinterpret_cast<void *>(PyDenseElementsAttribute::bf_getbuffer)},
917 {Py_bf_releasebuffer,
918 reinterpret_cast<void *>(PyDenseElementsAttribute::bf_releasebuffer)},
919#endif
920 {0, nullptr},
921};
922
923/*static*/ int PyDenseElementsAttribute::bf_getbuffer(PyObject *obj,
924 Py_buffer *view,
925 int flags) {
926 view->obj = nullptr;
927 std::unique_ptr<nb_buffer_info> info;
928 try {
929 auto *attr = nb::cast<PyDenseElementsAttribute *>(nb::handle(obj));
930 info = attr->accessBuffer();
931 } catch (nb::python_error &e) {
932 e.restore();
933 nb::chain_error(PyExc_BufferError, "Error converting attribute to buffer");
934 return -1;
935 } catch (std::exception &e) {
936 nb::chain_error(PyExc_BufferError,
937 "Error converting attribute to buffer: %s", e.what());
938 return -1;
939 }
940 view->obj = obj;
941 view->ndim = 1;
942 view->buf = info->ptr;
943 view->itemsize = info->itemsize;
944 view->len = info->itemsize;
945 for (auto s : info->shape) {
946 view->len *= s;
947 }
948 view->readonly = info->readonly;
949 if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
950 view->format = const_cast<char *>(info->format);
951 }
952 if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
953 view->ndim = static_cast<int>(info->ndim);
954 view->strides = info->strides.data();
955 view->shape = info->shape.data();
956 }
957 view->suboffsets = nullptr;
958 view->internal = info.release();
959 Py_INCREF(obj);
960 return 0;
961}
962
963/*static*/ void PyDenseElementsAttribute::bf_releasebuffer(PyObject *,
964 Py_buffer *view) {
965 delete reinterpret_cast<nb_buffer_info *>(view->internal);
966}
967
969 if (pos < 0 || pos >= dunderLen()) {
970 throw nb::index_error("attempt to access out of bounds element");
971 }
972
973 MlirType type = mlirAttributeGetType(*this);
974 type = mlirShapedTypeGetElementType(type);
975 // Index type can also appear as a DenseIntElementsAttr and therefore can be
976 // casted to integer.
977 assert(mlirTypeIsAInteger(type) ||
978 mlirTypeIsAIndex(type) && "expected integer/index element type in "
979 "dense int elements attribute");
980 // Dispatch element extraction to an appropriate C function based on the
981 // elemental type of the attribute. nb::int_ is implicitly
982 // constructible from any C++ integral type and handles bitwidth correctly.
983 // TODO: consider caching the type properties in the constructor to avoid
984 // querying them on each element access.
985 if (mlirTypeIsAIndex(type)) {
986 return nb::int_(mlirDenseElementsAttrGetIndexValue(*this, pos));
987 }
988 unsigned width = mlirIntegerTypeGetWidth(type);
989 bool isUnsigned = mlirIntegerTypeIsUnsigned(type);
990 if (isUnsigned) {
991 if (width == 1) {
992 return nb::int_(int(mlirDenseElementsAttrGetBoolValue(*this, pos)));
993 }
994 if (width == 8) {
995 return nb::int_(mlirDenseElementsAttrGetUInt8Value(*this, pos));
996 }
997 if (width == 16) {
998 return nb::int_(mlirDenseElementsAttrGetUInt16Value(*this, pos));
999 }
1000 if (width == 32) {
1001 return nb::int_(mlirDenseElementsAttrGetUInt32Value(*this, pos));
1002 }
1003 if (width == 64) {
1004 return nb::int_(mlirDenseElementsAttrGetUInt64Value(*this, pos));
1005 }
1006 } else {
1007 if (width == 1) {
1008 return nb::int_(int(mlirDenseElementsAttrGetBoolValue(*this, pos)));
1009 }
1010 if (width == 8) {
1011 return nb::int_(mlirDenseElementsAttrGetInt8Value(*this, pos));
1012 }
1013 if (width == 16) {
1014 return nb::int_(mlirDenseElementsAttrGetInt16Value(*this, pos));
1015 }
1016 if (width == 32) {
1017 return nb::int_(mlirDenseElementsAttrGetInt32Value(*this, pos));
1018 }
1019 if (width == 64) {
1020 return nb::int_(mlirDenseElementsAttrGetInt64Value(*this, pos));
1021 }
1022 }
1023 throw nb::type_error("Unsupported integer type");
1024}
1025
1029// Check if the python version is less than 3.13. Py_IsFinalizing is a part
1030// of stable ABI since 3.13 and before it was available as _Py_IsFinalizing.
1031#if PY_VERSION_HEX < 0x030d0000
1032#define Py_IsFinalizing _Py_IsFinalizing
1033#endif
1034
1037 const nb_buffer &buffer, const std::string &name, const PyType &type,
1038 std::optional<size_t> alignment, bool isMutable,
1039 DefaultingPyMlirContext contextWrapper) {
1040 if (!mlirTypeIsAShaped(type)) {
1041 throw std::invalid_argument(
1042 "Constructing a DenseResourceElementsAttr requires a ShapedType.");
1043 }
1044
1045 // Do not request any conversions as we must ensure to use caller
1046 // managed memory.
1047 int flags = PyBUF_STRIDES;
1048 std::unique_ptr<Py_buffer> view = std::make_unique<Py_buffer>();
1049 if (PyObject_GetBuffer(buffer.ptr(), view.get(), flags) != 0) {
1050 throw nb::python_error();
1051 }
1052
1053 // This scope releaser will only release if we haven't yet transferred
1054 // ownership.
1055 llvm::scope_exit freeBuffer([&]() {
1056 if (view)
1057 PyBuffer_Release(view.get());
1058 });
1059
1060 if (!PyBuffer_IsContiguous(view.get(), 'A')) {
1061 throw std::invalid_argument("Contiguous buffer is required.");
1062 }
1063
1064 // Infer alignment to be the stride of one element if not explicit.
1065 size_t inferredAlignment;
1066 if (alignment)
1067 inferredAlignment = *alignment;
1068 else
1069 inferredAlignment = view->strides[view->ndim - 1];
1070
1071 // The userData is a Py_buffer* that the deleter owns.
1072 auto deleter = [](void *userData, const void *data, size_t size,
1073 size_t align) {
1074 if (Py_IsFinalizing())
1075 return;
1076 assert(Py_IsInitialized() && "expected interpreter to be initialized");
1077 Py_buffer *ownedView = static_cast<Py_buffer *>(userData);
1078 nb::gil_scoped_acquire gil;
1079 PyBuffer_Release(ownedView);
1080 delete ownedView;
1081 };
1082
1083 size_t rawBufferSize = view->len;
1084 MlirAttribute attr = mlirUnmanagedDenseResourceElementsAttrGet(
1085 type, toMlirStringRef(name), view->buf, rawBufferSize, inferredAlignment,
1086 isMutable, deleter, static_cast<void *>(view.get()));
1087 if (mlirAttributeIsNull(attr)) {
1088 throw std::invalid_argument(
1089 "DenseResourceElementsAttr could not be constructed from the given "
1090 "buffer. "
1091 "This may mean that the Python buffer layout does not match that "
1092 "MLIR expected layout and is a bug.");
1093 }
1094 view.release();
1095 return PyDenseResourceElementsAttribute(contextWrapper->getRef(), attr);
1096}
1097
1099 c.def_static(
1101 nb::arg("array"), nb::arg("name"), nb::arg("type"),
1102 nb::arg("alignment") = nb::none(), nb::arg("is_mutable") = false,
1103 nb::arg("context") = nb::none(),
1104 // clang-format off
1105 nb::sig("def get_from_buffer(array: typing_extensions.Buffer, name: str, type: Type, alignment: int | None = None, is_mutable: bool = False, context: Context | None = None) -> DenseResourceElementsAttr"),
1106 // clang-format on
1108}
1109
1113
1114bool PyDictAttribute::dunderContains(const std::string &name) const {
1115 return !mlirAttributeIsNull(
1117}
1118
1120 c.def("__contains__", &PyDictAttribute::dunderContains);
1121 c.def("__len__", &PyDictAttribute::dunderLen);
1122 c.def_static(
1123 "get",
1124 [](const nb::dict &attributes, DefaultingPyMlirContext context) {
1125 SmallVector<MlirNamedAttribute> mlirNamedAttributes;
1126 mlirNamedAttributes.reserve(attributes.size());
1127 for (std::pair<nb::handle, nb::handle> it : attributes) {
1128 auto &mlirAttr = nb::cast<PyAttribute &>(it.second);
1129 auto name = nb::cast<std::string>(it.first);
1130 mlirNamedAttributes.push_back(mlirNamedAttributeGet(
1133 mlirAttr));
1134 }
1135 MlirAttribute attr =
1136 mlirDictionaryAttrGet(context->get(), mlirNamedAttributes.size(),
1137 mlirNamedAttributes.data());
1138 return PyDictAttribute(context->getRef(), attr);
1139 },
1140 nb::arg("value") = nb::dict(), nb::arg("context") = nb::none(),
1141 "Gets an uniqued dict attribute");
1142 c.def("__getitem__",
1143 [](PyDictAttribute &self,
1144 const std::string &name) -> nb::typed<nb::object, PyAttribute> {
1145 MlirAttribute attr =
1147 if (mlirAttributeIsNull(attr))
1148 throw nb::key_error("attempt to access a non-existent attribute");
1149 return PyAttribute(self.getContext(), attr).maybeDownCast();
1150 });
1151 c.def("__getitem__", [](PyDictAttribute &self, intptr_t index) {
1152 if (index < 0 || index >= self.dunderLen()) {
1153 throw nb::index_error("attempt to access out of bounds attribute");
1154 }
1156 return PyNamedAttribute(
1157 namedAttr.attribute,
1158 std::string(mlirIdentifierStr(namedAttr.name).data));
1159 });
1160}
1161
1163 if (pos < 0 || pos >= dunderLen()) {
1164 throw nb::index_error("attempt to access out of bounds element");
1165 }
1166
1167 MlirType type = mlirAttributeGetType(*this);
1168 type = mlirShapedTypeGetElementType(type);
1169 // Dispatch element extraction to an appropriate C function based on the
1170 // elemental type of the attribute. nb::float_ is implicitly
1171 // constructible from float and double.
1172 // TODO: consider caching the type properties in the constructor to avoid
1173 // querying them on each element access.
1174 if (mlirTypeIsAF32(type)) {
1175 return nb::float_(mlirDenseElementsAttrGetFloatValue(*this, pos));
1176 }
1177 if (mlirTypeIsAF64(type)) {
1178 return nb::float_(mlirDenseElementsAttrGetDoubleValue(*this, pos));
1179 }
1180 throw nb::type_error("Unsupported floating-point type");
1181}
1182
1186
1188 c.def_static(
1189 "get",
1190 [](const PyType &value, DefaultingPyMlirContext context) {
1191 MlirAttribute attr = mlirTypeAttrGet(value.get());
1192 return PyTypeAttribute(context->getRef(), attr);
1193 },
1194 nb::arg("value"), nb::arg("context") = nb::none(),
1195 "Gets a uniqued Type attribute");
1196 c.def_prop_ro(
1197 "value", [](PyTypeAttribute &self) -> nb::typed<nb::object, PyType> {
1198 return PyType(self.getContext(), mlirTypeAttrGetValue(self.get()))
1199 .maybeDownCast();
1200 });
1201}
1202
1204 c.def_static(
1205 "get",
1206 [](DefaultingPyMlirContext context) {
1207 return PyUnitAttribute(context->getRef(),
1208 mlirUnitAttrGet(context->get()));
1209 },
1210 nb::arg("context") = nb::none(), "Create a Unit attribute.");
1211}
1212
1214 c.def_static(
1215 "get",
1216 [](int64_t offset, const std::vector<int64_t> &strides,
1218 MlirAttribute attr = mlirStridedLayoutAttrGet(
1219 ctx->get(), offset, strides.size(), strides.data());
1220 return PyStridedLayoutAttribute(ctx->getRef(), attr);
1221 },
1222 nb::arg("offset"), nb::arg("strides"), nb::arg("context") = nb::none(),
1223 "Gets a strided layout attribute.");
1224 c.def_static(
1225 "get_fully_dynamic",
1226 [](int64_t rank, DefaultingPyMlirContext ctx) {
1228 std::vector<int64_t> strides(rank);
1229 llvm::fill(strides, dynamic);
1230 MlirAttribute attr = mlirStridedLayoutAttrGet(
1231 ctx->get(), dynamic, strides.size(), strides.data());
1232 return PyStridedLayoutAttribute(ctx->getRef(), attr);
1233 },
1234 nb::arg("rank"), nb::arg("context") = nb::none(),
1235 "Gets a strided layout attribute with dynamic offset and strides of "
1236 "a "
1237 "given rank.");
1238 c.def_prop_ro(
1239 "offset",
1240 [](PyStridedLayoutAttribute &self) {
1241 return mlirStridedLayoutAttrGetOffset(self);
1242 },
1243 "Returns the value of the float point attribute");
1244 c.def_prop_ro(
1245 "strides",
1246 [](PyStridedLayoutAttribute &self) {
1248 std::vector<int64_t> strides(size);
1249 for (intptr_t i = 0; i < size; i++) {
1250 strides[i] = mlirStridedLayoutAttrGetStride(self, i);
1251 }
1252 return strides;
1253 },
1254 "Returns the value of the float point attribute");
1255}
1256
1257nb::object denseArrayAttributeCaster(PyAttribute &pyAttribute) {
1259 return nb::cast(PyDenseBoolArrayAttribute(pyAttribute));
1260 if (PyDenseI8ArrayAttribute::isaFunction(pyAttribute))
1261 return nb::cast(PyDenseI8ArrayAttribute(pyAttribute));
1263 return nb::cast(PyDenseI16ArrayAttribute(pyAttribute));
1265 return nb::cast(PyDenseI32ArrayAttribute(pyAttribute));
1267 return nb::cast(PyDenseI64ArrayAttribute(pyAttribute));
1269 return nb::cast(PyDenseF32ArrayAttribute(pyAttribute));
1271 return nb::cast(PyDenseF64ArrayAttribute(pyAttribute));
1272 std::string msg =
1273 std::string("Can't cast unknown element type DenseArrayAttr (") +
1274 nb::cast<std::string>(nb::repr(nb::cast(pyAttribute))) + ")";
1275 throw nb::type_error(msg.c_str());
1276}
1277
1280 return nb::cast(PyDenseFPElementsAttribute(pyAttribute));
1282 return nb::cast(PyDenseIntElementsAttribute(pyAttribute));
1283 std::string msg =
1284 std::string(
1285 "Can't cast unknown element type DenseIntOrFPElementsAttr (") +
1286 nb::cast<std::string>(nb::repr(nb::cast(pyAttribute))) + ")";
1287 throw nb::type_error(msg.c_str());
1288}
1289
1291 if (PyBoolAttribute::isaFunction(pyAttribute))
1292 return nb::cast(PyBoolAttribute(pyAttribute));
1293 if (PyIntegerAttribute::isaFunction(pyAttribute))
1294 return nb::cast(PyIntegerAttribute(pyAttribute));
1295 std::string msg = std::string("Can't cast unknown attribute type Attr (") +
1296 nb::cast<std::string>(nb::repr(nb::cast(pyAttribute))) +
1297 ")";
1298 throw nb::type_error(msg.c_str());
1299}
1300
1303 return nb::cast(PyFlatSymbolRefAttribute(pyAttribute));
1304 if (PySymbolRefAttribute::isaFunction(pyAttribute))
1305 return nb::cast(PySymbolRefAttribute(pyAttribute));
1306 std::string msg = std::string("Can't cast unknown SymbolRef attribute (") +
1307 nb::cast<std::string>(nb::repr(nb::cast(pyAttribute))) +
1308 ")";
1309 throw nb::type_error(msg.c_str());
1310}
1311
1313 c.def_static(
1314 "get",
1315 [](const std::string &value, DefaultingPyMlirContext context) {
1316 MlirAttribute attr =
1317 mlirStringAttrGet(context->get(), toMlirStringRef(value));
1318 return PyStringAttribute(context->getRef(), attr);
1319 },
1320 nb::arg("value"), nb::arg("context") = nb::none(),
1321 "Gets a uniqued string attribute");
1322 c.def_static(
1323 "get",
1324 [](const nb::bytes &value, DefaultingPyMlirContext context) {
1325 MlirAttribute attr =
1326 mlirStringAttrGet(context->get(), toMlirStringRef(value));
1327 return PyStringAttribute(context->getRef(), attr);
1328 },
1329 nb::arg("value"), nb::arg("context") = nb::none(),
1330 "Gets a uniqued string attribute");
1331 c.def_static(
1332 "get_typed",
1333 [](PyType &type, const std::string &value) {
1334 MlirAttribute attr =
1336 return PyStringAttribute(type.getContext(), attr);
1337 },
1338 nb::arg("type"), nb::arg("value"),
1339 "Gets a uniqued string attribute associated to a type");
1340 c.def_prop_ro(
1341 "value",
1342 [](PyStringAttribute &self) {
1343 MlirStringRef stringRef = mlirStringAttrGetValue(self);
1344 return nb::str(stringRef.data, stringRef.length);
1345 },
1346 "Returns the value of the string attribute");
1347 c.def_prop_ro(
1348 "value_bytes",
1349 [](PyStringAttribute &self) {
1350 MlirStringRef stringRef = mlirStringAttrGetValue(self);
1351 return nb::bytes(stringRef.data, stringRef.length);
1352 },
1353 "Returns the value of the string attribute as `bytes`");
1354}
1355
1356void populateIRAttributes(nb::module_ &m) {
1359 PyDenseBoolArrayAttribute::PyDenseArrayIterator::bind(m);
1361 PyDenseI8ArrayAttribute::PyDenseArrayIterator::bind(m);
1363 PyDenseI16ArrayAttribute::PyDenseArrayIterator::bind(m);
1365 PyDenseI32ArrayAttribute::PyDenseArrayIterator::bind(m);
1367 PyDenseI64ArrayAttribute::PyDenseArrayIterator::bind(m);
1369 PyDenseF32ArrayAttribute::PyDenseArrayIterator::bind(m);
1371 PyDenseF64ArrayAttribute::PyDenseArrayIterator::bind(m);
1374 nb::cast<nb::callable>(nb::cpp_function(denseArrayAttributeCaster)));
1375
1384 nb::cast<nb::callable>(
1385 nb::cpp_function(denseIntOrFPElementsAttributeCaster)));
1387
1392 nb::cast<nb::callable>(
1393 nb::cpp_function(symbolRefOrFlatSymbolRefAttributeCaster)));
1394
1404 nb::cast<nb::callable>(nb::cpp_function(integerOrBoolAttributeCaster)));
1406
1408}
1409} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
1410} // namespace python
1411} // namespace mlir
#define Py_IsFinalizing
static const char kDenseElementsAttrGetDocstring[]
static const char kDenseResourceElementsAttrGetFromBufferDocstring[]
static const char kDenseElementsAttrGetFromListDocstring[]
MlirContext mlirAttributeGetContext(MlirAttribute attribute)
Definition IR.cpp:1281
MlirType mlirAttributeGetType(MlirAttribute attribute)
Definition IR.cpp:1285
std::string str() const
Converts the diagnostic to a string.
ReferrentTy * get() const
PyMlirContextRef & getContext()
Accesses the context reference.
Definition IRCore.h:299
Used in function arguments when None should resolve to the current context manager set instance.
Definition IRCore.h:526
Used in function arguments when None should resolve to the current context manager set instance.
Definition IRCore.h:280
Wrapper around the generic MlirAttribute.
Definition IRCore.h:1009
PyAttribute(PyMlirContextRef contextRef, MlirAttribute attr)
Definition IRCore.h:1011
static void bind(nanobind::module_ &m, PyType_Slot *slots=nullptr)
Definition IRCore.h:1092
nanobind::class_< PyAffineMapAttribute, PyAttribute > ClassTy
Definition IRCore.h:1066
static PyDenseElementsAttribute getSplat(const PyType &shapedType, PyAttribute &elementAttr)
static PyDenseElementsAttribute getFromList(const nanobind::list &attributes, std::optional< PyType > explicitType, DefaultingPyMlirContext contextWrapper)
static PyDenseElementsAttribute getFromBuffer(const nb_buffer &array, bool signless, const std::optional< PyType > &explicitType, std::optional< std::vector< int64_t > > explicitShape, DefaultingPyMlirContext contextWrapper)
Refinement of PyDenseElementsAttribute for attributes containing floating-point values.
Refinement of the PyDenseElementsAttribute for attributes containing integer (and boolean) values.
nanobind::int_ dunderGetItem(intptr_t pos) const
Returns the element at the given linear position.
static PyDenseResourceElementsAttribute getFromBuffer(const nb_buffer &buffer, const std::string &name, const PyType &type, std::optional< size_t > alignment, bool isMutable, DefaultingPyMlirContext contextWrapper)
Float Point Attribute subclass - FloatAttr.
static PyGlobals & get()
Most code should get the globals via this static accessor.
Definition Globals.cpp:44
void registerTypeCaster(MlirTypeID mlirTypeID, nanobind::callable typeCaster, bool replace=false)
Adds a user-friendly type caster.
Definition Globals.cpp:96
static PyMlirContextRef forContext(MlirContext context)
Returns a context reference for the singleton PyMlirContext wrapper for the given context.
Definition IRCore.cpp:474
MlirContext get()
Accesses the underlying MlirContext.
Definition IRCore.h:213
PyMlirContextRef getRef()
Gets a strong reference to this context, which will ensure it is kept alive for the life of the refer...
Definition IRCore.cpp:459
Represents a Python MlirNamedAttr, carrying an optional owned name.
Definition IRCore.h:1035
static PySymbolRefAttribute fromList(const std::vector< std::string > &symbols, PyMlirContext &context)
A TypeID provides an efficient and unique identifier for a specific C++ type.
Definition IRCore.h:902
Wrapper around the generic MlirType.
Definition IRCore.h:876
nanobind::typed< nanobind::object, PyType > maybeDownCast()
Definition IRCore.cpp:1958
Unit Attribute subclass. Unit attributes don't have values.
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 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 uint8_t mlirDenseElementsAttrGetUInt8Value(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED int64_t mlirStridedLayoutAttrGetOffset(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 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 uint64_t mlirDenseElementsAttrGetIndexValue(MlirAttribute attr, intptr_t pos)
MLIR_CAPI_EXPORTED const void * mlirDenseElementsAttrGetRawData(MlirAttribute attr)
Returns the raw data of the given dense elements attribute.
MLIR_CAPI_EXPORTED MlirTypeID mlirIntegerAttrGetTypeID(void)
Returns the typeID of an Integer attribute.
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 MlirTypeID mlirDenseIntOrFPElementsAttrGetTypeID(void)
Returns the typeID of an DenseIntOrFPElements 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 MlirAttribute mlirIntegerAttrGet(MlirType type, int64_t value)
Creates an integer attribute of the given type with the given integer value.
MLIR_CAPI_EXPORTED bool mlirDenseElementsAttrGetBoolValue(MlirAttribute attr, intptr_t pos)
Returns the pos-th value (flat contiguous indexing) of a specific type contained by the given dense e...
MLIR_CAPI_EXPORTED MlirAttribute mlirDictionaryAttrGet(MlirContext ctx, intptr_t numElements, MlirNamedAttribute const *elements)
Creates a dictionary attribute containing the given list of elements in the provided context.
MLIR_CAPI_EXPORTED MlirAttribute mlirUnmanagedDenseResourceElementsAttrGet(MlirType shapedType, MlirStringRef name, void *data, size_t dataLength, size_t dataAlignment, bool dataIsMutable, void(*deleter)(void *userData, const void *data, size_t size, size_t align), void *userData)
Unlike the typed accessors below, constructs the attribute with a raw data buffer and no type/alignme...
MLIR_CAPI_EXPORTED MlirAttribute mlirSymbolRefAttrGetNestedReference(MlirAttribute attr, intptr_t pos)
Returns pos-th reference nested in the given symbol reference 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...
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 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 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 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 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 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 float mlirDenseElementsAttrGetFloatValue(MlirAttribute attr, intptr_t pos)
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 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 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 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 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 MlirAttribute mlirDenseElementsAttrSplatGet(MlirType shapedType, MlirAttribute element)
Creates a dense elements attribute with the given Shaped type containing a single replicated element ...
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 MlirAttribute mlirStringAttrTypedGet(MlirType type, MlirStringRef str)
Creates a string attribute in the given context containing the given string.
MLIR_CAPI_EXPORTED MlirStringRef mlirFlatSymbolRefAttrGetValue(MlirAttribute attr)
Returns the referenced symbol as a string reference.
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.
MLIR_CAPI_EXPORTED MlirNamedAttribute mlirNamedAttributeGet(MlirIdentifier name, MlirAttribute attr)
Associates an attribute with the name. Takes ownership of neither.
Definition IR.cpp:1312
MLIR_CAPI_EXPORTED MlirStringRef mlirIdentifierStr(MlirIdentifier ident)
Gets the string value of the identifier.
Definition IR.cpp:1333
MLIR_CAPI_EXPORTED MlirContext mlirTypeGetContext(MlirType type)
Gets the context that a type was created with.
Definition IR.cpp:1250
MLIR_CAPI_EXPORTED bool mlirTypeEqual(MlirType t1, MlirType t2)
Checks if two types are equal.
Definition IR.cpp:1262
MLIR_CAPI_EXPORTED MlirIdentifier mlirIdentifierGet(MlirContext context, MlirStringRef str)
Gets an identifier with the given string value.
Definition IR.cpp:1321
nb::object denseIntOrFPElementsAttributeCaster(PyAttribute &pyAttribute)
nb::object symbolRefOrFlatSymbolRefAttributeCaster(PyAttribute &pyAttribute)
nb::object integerOrBoolAttributeCaster(PyAttribute &pyAttribute)
MlirStringRef toMlirStringRef(const std::string &s)
Definition IRCore.h:1342
static T pyTryCast(nanobind::handle object)
nb::object denseArrayAttributeCaster(PyAttribute &pyAttribute)
MLIR_PYTHON_API_EXPORTED void populateIRAttributes(nanobind::module_ &m)
Include the generated interface declarations.
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:75
const char * data
Pointer to the first symbol.
Definition Support.h:76
size_t length
Length of the fragment.
Definition Support.h:77
Custom exception that allows access to error diagnostic information.
Definition IRCore.h:1330
RAII object that captures any error diagnostics emitted to the provided context.
Definition IRCore.h:435
std::vector< PyDiagnostic::DiagnosticInfo > take()
Definition IRCore.h:445
nb_buffer_info(void *ptr, ssize_t itemsize, const char *format, ssize_t ndim, SmallVector< ssize_t, 4 > shape_in, SmallVector< ssize_t, 4 > strides_in, bool readonly=false, std::unique_ptr< Py_buffer, void(*)(Py_buffer *)> owned_view_in=std::unique_ptr< Py_buffer, void(*)(Py_buffer *)>(nullptr, nullptr))