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