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