# `Beaver.MLIR.Dialect.Ptr`

Operations and construction helpers for MLIR's upstream Ptr dialect.

Ptr values model native pointers in IR. They are distinct from
`Beaver.Native.OpaquePtr` and other BEAM resources, which own or reference
host-side native data outside MLIR.

Use `type/1` with the generic memory space at high-level ABI boundaries such
as ENIF calls. Use an explicit LLVM address space when Ptr operations remain
in an `llvm.func` until LLVM IR translation:

    Ptr.type()
    Ptr.type(memory_space: {:llvm, 3})

`null/1` and `address/2` return typed attributes suitable for
`ptr.constant`.

# `memory_space`

```elixir
@type memory_space() ::
  :generic
  | non_neg_integer()
  | {:llvm, non_neg_integer()}
  | Beaver.Deferred.attribute()
```

# `address`

```elixir
@spec address(
  non_neg_integer(),
  keyword()
) :: Beaver.Deferred.attribute()
```

Return a typed `#ptr.address` attribute for `ptr.constant`.

# `constant`

Return op name `ptr.constant` as a bitstring.

# `constant`

`ptr.constant` - Pointer constant operation

This op has support for result type inference.

## Attributes
- `value` - Single, `TypedAttrInterface`, TypedAttr instance

## Results
- `result` - Single, `Ptr_PtrType`, pointer type
## Description
The `constant` operation produces a pointer constant. The attribute must be
a typed attribute of pointer type.

Example:

```mlir
// Create a null pointer
%null = ptr.constant #ptr.null : !ptr.ptr<#ptr.generic_space>
```

# `from_ptr`

Return op name `ptr.from_ptr` as a bitstring.

# `from_ptr`

`ptr.from_ptr` - Casts a `!ptr.ptr` value to a ptr-like value.

## Operands
- `ptr` - Single, `Ptr_PtrType`, pointer type
- `metadata` - Optional, `Ptr_PtrMetadata`, Pointer metadata type

## Results
- `result` - Single, `PtrLikeTypeInterface`, PtrLikeTypeInterface instance
## Description
The `from_ptr` operation casts a `ptr` value to a ptr-like object. It's
important to note that:
- The ptr-like object cannot be a `!ptr.ptr`.
- The memory-space of both the `ptr` and ptr-like object must match.
- The cast is Pure (no UB and side-effect free).

The optional `metadata` operand exists to provide any ptr-like metadata
that might be required to perform the cast.

Example:

```mlir
%typed_ptr = ptr.from_ptr %ptr : !ptr.ptr<#ptr.generic_space> -> !my.ptr<f32, #ptr.generic_space>
%memref = ptr.from_ptr %ptr metadata %md : !ptr.ptr<#ptr.generic_space> -> memref<f32, #ptr.generic_space>

// Cast the `%ptr` to a memref without utilizing metadata.
%memref = ptr.from_ptr %ptr : !ptr.ptr<#ptr.generic_space> -> memref<f32, #ptr.generic_space>
```

# `gather`

Return op name `ptr.gather` as a bitstring.

# `gather`

`ptr.gather` - Gather operation

This op has support for result type inference.

## Operands
- `ptrs` - Single, `Ptr_Ptr1DType`, A shaped type with value semantics and rank. of pointer type values
- `mask` - Single, `Ptr_Mask1DType`, A shaped type with value semantics and rank. of 1-bit signless integer values
- `passthrough` - Single, `Ptr_Any1DType`, A shaped type with value semantics and rank. of any non-token type values

## Results
- `result` - Single, `Ptr_Any1DType`, A shaped type with value semantics and rank. of any non-token type values
## Description
The `gather` operation performs conditional loads from multiple memory
locations specified by `ptrs` based on a mask `mask`. Elements of the
result corresponding to masked-off lanes are taken from the passthrough
operand.

The mask operand is a shaped type of `i1` elements that must have the same
shape as the result type.

Examples:
```mlir
// Gather values from multiple memory locations
%result = ptr.gather %ptrs, %mask, %passthrough :
  vector<4x!ptr.ptr<#ptr.generic_space>> -> vector<4xf32>

// Gather with alignment
%result = ptr.gather %ptrs, %mask, %passthrough alignment = 8 :
  vector<4x!ptr.ptr<#ptr.generic_space>> -> vector<4xf32>
```

# `generic_space`

```elixir
@spec generic_space(keyword()) :: Beaver.Deferred.attribute()
```

Return the upstream Ptr generic-memory-space attribute.

# `get_metadata`

Return op name `ptr.get_metadata` as a bitstring.

# `get_metadata`

`ptr.get_metadata` - SSA value representing pointer metadata.

This op has support for result type inference.

## Operands
- `ptr` - Single, `PtrLikeTypeInterface`, PtrLikeTypeInterface instance

## Results
- `result` - Single, `Ptr_PtrMetadata`, Pointer metadata type
## Description
The `get_metadata` operation produces an opaque value that encodes the
metadata of the ptr-like type.

Example:

```mlir
%metadata = ptr.get_metadata %memref : memref<?x?xf32>
```

# `llvm_address_space`

```elixir
@spec llvm_address_space(
  non_neg_integer(),
  keyword()
) :: Beaver.Deferred.attribute()
```

Return an LLVM address-space attribute for a non-negative address-space number.

# `load`

Return op name `ptr.load` as a bitstring.

# `load`

`ptr.load`

## Attributes
- `syncscope` - Optional, `StrAttr`, string attribute

## Operands
- `ptr` - Single, `Ptr_PtrType`, pointer type

## Results
- `value` - Single, `AnyType`, any non-token type
## Description
The `load` operation is used to read from memory. A load may be marked as
atomic, volatile, and/or nontemporal.

An atomic load only supports a limited set of value types, and requires
an explicit alignment.

Examples:
```mlir
// A volatile load of a float variable.
%0 = ptr.load volatile %ptr : !ptr.ptr -> f32

// A nontemporal load of a float variable.
%0 = ptr.load %ptr nontemporal : !ptr.ptr -> f32

// An atomic load of an integer variable.
%0 = ptr.load %ptr atomic monotonic alignment = 8 : !ptr.ptr -> i64
```

See the following link for more details on the meaning of `alignment`,
`volatile_`, `nontemporal`, `invariant`, `invariant_group`, `ordering`,
and `syncscope`:
https://llvm.org/docs/LangRef.html#load-instruction

# `masked_load`

Return op name `ptr.masked_load` as a bitstring.

# `masked_load`

`ptr.masked_load` - Masked load operation

This op has support for result type inference.

## Operands
- `ptr` - Single, `Ptr_PtrType`, pointer type
- `mask` - Single, `Ptr_Mask1DType`, A shaped type with value semantics and rank. of 1-bit signless integer values
- `passthrough` - Single, `Ptr_Any1DType`, A shaped type with value semantics and rank. of any non-token type values

## Results
- `result` - Single, `Ptr_Any1DType`, A shaped type with value semantics and rank. of any non-token type values
## Description
The `masked_load` operation performs a conditional load from memory based
on  a mask. Elements of the result corresponding to masked-off lanes are
taken from the passthrough operand.

The mask operand is a shaped type of `i1` elements that must have the same
shape as the result type.

Examples:
```mlir
// Masked load with passthrough on vectors
%result = ptr.masked_load %ptr, %mask, %passthrough :
  !ptr.ptr<#ptr.generic_space> -> vector<4xf32>

// Masked load with passthrough on tensors
%result = ptr.masked_load %ptr, %mask, %passthrough :
  !ptr.ptr<#ptr.generic_space> -> tensor<4xf32>
```

# `masked_store`

Return op name `ptr.masked_store` as a bitstring.

# `masked_store`

`ptr.masked_store` - Masked store operation

## Operands
- `value` - Single, `Ptr_Any1DType`, A shaped type with value semantics and rank. of any non-token type values
- `ptr` - Single, `Ptr_PtrType`, pointer type
- `mask` - Single, `Ptr_Mask1DType`, A shaped type with value semantics and rank. of 1-bit signless integer values
## Description
The `masked_store` operation performs a conditional store to memory based
on  a mask. Only elements corresponding to set bits in the mask are written
to memory.

The mask operand is a shaped type of `i1` elements that must have the same
shape as the value being stored.

Examples:
```mlir
// Masked store
ptr.masked_store %value, %ptr, %mask :
  vector<4xf32>, !ptr.ptr<#ptr.generic_space>

// Masked store with alignment
ptr.masked_store %value, %ptr, %mask alignment = 8 :
  vector<4xf32>, !ptr.ptr<#ptr.generic_space>
```

# `null`

```elixir
@spec null(keyword()) :: Beaver.Deferred.attribute()
```

Return a typed `#ptr.null` attribute for `ptr.constant`.

# `ptr_add`

Return op name `ptr.ptr_add` as a bitstring.

# `ptr_add`

`ptr.ptr_add` - Pointer add operation

This op has support for result type inference.

## Operands
- `base` - Single, `Ptr_PtrLikeType`, A shaped type with value semantics and rank. of pointer type values or pointer type
- `offset` - Single, `Ptr_IntLikeType`, A shaped type with value semantics and rank. of signless integer or index values or signless integer or index

## Results
- `result` - Single, `Ptr_PtrLikeType`, A shaped type with value semantics and rank. of pointer type values or pointer type
## Description
The `ptr_add` operation adds an int-like offset to one or more pointers to produce one or more new pointers.

The operation supports both scalar and shaped types with value semantics:
- When both base and offset are scalar: produces a single new pointer
- When base is shaped and offset is scalar: adds the same offset to each
pointer in the base
- When base is scalar and offset is shaped: adds the single pointer to each
offset in the shaped value
- When both are shaped: performs element-wise addition (shapes must be
compatible)

Example:

```mlir
// Scalar base and offset
%x_off  = ptr.ptr_add %x, %off : !ptr.ptr<#ptr.generic_space>, i32
%x_off0 = ptr.ptr_add nusw %x, %off : !ptr.ptr<#ptr.generic_space>, i32

// Shaped base with scalar offset
%ptrs_off = ptr.ptr_add %ptrs, %off : vector<4x!ptr.ptr<#ptr.generic_space>>, i32

// Scalar base with shaped offset
%x_offs = ptr.ptr_add %x, %offs : !ptr.ptr<#ptr.generic_space>, vector<4xi32>

// Both base and offset are shaped
%ptrs_offs = ptr.ptr_add %ptrs, %offs : vector<4x!ptr.ptr<#ptr.generic_space>>, vector<4xi32>
```

# `ptr_diff`

Return op name `ptr.ptr_diff` as a bitstring.

# `ptr_diff`

`ptr.ptr_diff` - Pointer difference operation

## Operands
- `lhs` - Single, `Ptr_PtrLikeType`, A shaped type with value semantics and rank. of pointer type values or pointer type
- `rhs` - Single, `Ptr_PtrLikeType`, A shaped type with value semantics and rank. of pointer type values or pointer type

## Results
- `result` - Single, `Ptr_IntLikeType`, A shaped type with value semantics and rank. of signless integer or index values or signless integer or index
## Description
The `ptr_diff` operation computes the difference between two pointers,
returning an integer or index value representing the number of bytes
between them.

The operation supports both scalar and shaped types with value semantics:
- When both operands are scalar: produces a single difference value
- When both are shaped: performs element-wise subtraction,
  shapes must be the same

The operation also supports the following flags:
- `none`: No flags are set.
- `nuw`: No Unsigned Wrap, if the subtraction causes an unsigned overflow
  (that is: the result would be negative), the result is a poison value.
- `nsw`: No Signed Wrap, if the subtraction causes a signed overflow, the
  result is a poison value.

NOTE: The pointer difference is calculated using an integer type specified
by the data layout. The final result will be sign-extended or truncated to
fit the result type as necessary.

Example:

```mlir
// Scalar pointers
%diff = ptr.ptr_diff %p1, %p2 : !ptr.ptr<#ptr.generic_space> -> i64

// Shaped pointers
%diffs = ptr.ptr_diff nsw %ptrs1, %ptrs2 :
  vector<4x!ptr.ptr<#ptr.generic_space>> -> vector<4xi64>
```

# `scatter`

Return op name `ptr.scatter` as a bitstring.

# `scatter`

`ptr.scatter` - Scatter operation

## Operands
- `value` - Single, `Ptr_Any1DType`, A shaped type with value semantics and rank. of any non-token type values
- `ptrs` - Single, `Ptr_Ptr1DType`, A shaped type with value semantics and rank. of pointer type values
- `mask` - Single, `Ptr_Mask1DType`, A shaped type with value semantics and rank. of 1-bit signless integer values
## Description
The `scatter` operation performs a conditional store of a value `value` to
multiple memory locations specified by `ptrs` based on a mask `mask`.

Only elements corresponding to set bits in the mask are written to memory.
The mask operand is a shaped type of `i1` elements that must have the same
shape as the value being stored.

Examples:
```mlir
// Scatter values to multiple memory locations
ptr.scatter %value, %ptrs, %mask :
  vector<4xf32>, vector<4x!ptr.ptr<#ptr.generic_space>>

// Scatter with alignment
ptr.scatter %value, %ptrs, %mask alignment = 8 :
  vector<4xf32>, vector<4x!ptr.ptr<#ptr.generic_space>>
```

# `store`

Return op name `ptr.store` as a bitstring.

# `store`

`ptr.store`

## Attributes
- `syncscope` - Optional, `StrAttr`, string attribute

## Operands
- `value` - Single, `AnyType`, any non-token type
- `ptr` - Single, `Ptr_PtrType`, pointer type
## Description
The `store` operation is used to write to memory. A store may be marked as
atomic, volatile, and/or nontemporal.

An atomic store only supports a limited set of value types, and requires
an explicit alignment.

Examples:
```mlir
// A volatile store of a float variable.
ptr.store volatile %val, %ptr : f32, !ptr.ptr

// A nontemporal store of a float variable.
ptr.store %val, %ptr nontemporal : f32, !ptr.ptr

// An atomic store of an integer variable.
ptr.store %val, %ptr atomic monotonic alignment = 8: i64, !ptr.ptr
```

See the following link for more details on the meaning of `alignment`,
`volatile_`, `nontemporal`, `invariant_group`, `ordering`, and `syncscope`:
https://llvm.org/docs/LangRef.html#store-instruction

# `to_ptr`

Return op name `ptr.to_ptr` as a bitstring.

# `to_ptr`

`ptr.to_ptr` - Casts a ptr-like value to a `!ptr.ptr` value.

## Operands
- `ptr` - Single, `PtrLikeTypeInterface`, PtrLikeTypeInterface instance

## Results
- `result` - Single, `Ptr_PtrType`, pointer type
## Description
The `to_ptr` operation casts a ptr-like object to a `!ptr.ptr`. It's
important to note that:
- The ptr-like object cannot be a `!ptr.ptr`.
- The memory-space of both the `ptr` and ptr-like object must match.
- The cast is side-effect free.

Example:

```mlir
%ptr0 = ptr.to_ptr %my_ptr : !my.ptr<f32, #ptr.generic_space> -> !ptr.ptr<#ptr.generic_space>
%ptr1 = ptr.to_ptr %memref : memref<f32, #ptr.generic_space> -> !ptr.ptr<#ptr.generic_space>
```

# `type`

```elixir
@spec type(keyword()) :: Beaver.Deferred.type()
```

Return a `!ptr.ptr` type.

The default is `#ptr.generic_space`. Pass either an address-space number or
`{:llvm, address_space}` to make the LLVM address space explicit.

# `type_offset`

Return op name `ptr.type_offset` as a bitstring.

# `type_offset`

`ptr.type_offset` - Type offset operation

## Attributes
- `elementType` - Single, `TypeAttr`, any type attribute

## Results
- `result` - Single, `AnySignlessIntegerOrIndex`, signless integer or index
## Description
The `type_offset` operation produces an int or index-typed SSA value
equal to a target-specific constant representing the offset of a single
element of the given type.

Example:

```mlir
// Return the offset between two f32 stored in memory
%0 = ptr.type_offset f32 : index
// Return the offset between two memref descriptors stored in memory
%1 = ptr.type_offset memref<12 x f64> : i32
```

