[Mlir-commits] [mlir] [mlir][python] Support Arbitrary Precision Integers in MLIR C API and Python Bindings (PR #177733)

Ryan Kim llvmlistbot at llvm.org
Sat Jan 24 16:41:22 PST 2026


================
@@ -343,8 +343,50 @@ void PyFloatAttribute::bindDerived(ClassTy &c) {
 void PyIntegerAttribute::bindDerived(ClassTy &c) {
   c.def_static(
       "get",
-      [](PyType &type, int64_t value) {
-        MlirAttribute attr = mlirIntegerAttrGet(type, value);
+      [](PyType &type, nb::object value) {
+        // Handle IndexType - it doesn't have a bit width or signedness.
+        if (mlirTypeIsAIndex(type)) {
+          int64_t intValue = nb::cast<int64_t>(value);
+          MlirAttribute attr = mlirIntegerAttrGet(type, intValue);
+          return PyIntegerAttribute(type.getContext(), attr);
+        }
+
+        // Get the bit width of the integer type.
+        unsigned bitWidth = mlirIntegerTypeGetWidth(type);
+
+        // Try to use the fast path for small integers.
+        if (bitWidth <= 64) {
+          int64_t intValue = nb::cast<int64_t>(value);
+          MlirAttribute attr = mlirIntegerAttrGet(type, intValue);
+          return PyIntegerAttribute(type.getContext(), attr);
+        }
+
+        // For larger integers, convert Python int to array of 64-bit words.
+        unsigned numWords = (bitWidth + 63) / 64;
+        std::vector<uint64_t> words(numWords, 0);
+
+        // Extract words from Python integer (little-endian order).
+        nb::object mask = nb::int_(0xFFFFFFFFFFFFFFFFULL);
+        nb::object shift = nb::int_(64);
+        nb::object current = value;
+
+        // Handle negative numbers for signed types by converting to two's
+        // complement representation.
+        if (mlirIntegerTypeIsSigned(type)) {
+          nb::object zero = nb::int_(0);
+          if (nb::cast<bool>(current < zero)) {
+            nb::object twoToTheBitWidth = nb::int_(1) << nb::int_(bitWidth);
+            current = current + twoToTheBitWidth;
----------------
chokobole wrote:

`mlirIntegerAttrGetFromWords` expects an array of unsigned 64-bit words. However, Python represents negative numbers directly (e.g., `-5`), not in two's complement form.

For example, to store `-1` in a 256-bit signed integer type:

- Python value: `-1`
- Required MLIR representation: `2^256 - 1` (all bits set to 1)

So what I am doing right here is to make it two's complement form

```c++
if (mlirIntegerTypeIsSigned(type)) {
  nb::object zero = nb::int_(0);
  if (nb::cast<bool>(current < zero)) {  // Check if negative
    // Convert to two's complement by adding 2^bitWidth
    nb::object twoToTheBitWidth = nb::int_(1) << nb::int_(bitWidth);
    current = current + twoToTheBitWidth;
  }
}
```

https://github.com/llvm/llvm-project/pull/177733


More information about the Mlir-commits mailing list