Buffer/View Model¶
IRx defines one canonical low-level memory/container substrate: a buffer owner handle plus a buffer view descriptor. This is not a user-facing scientific array API. It does not define NumPy semantics, broadcasting, slicing syntax, reductions, tensor algebra, or high-level dtype policy.
The model exists so Arx can lower scientific data structures into stable plain ABI data without baking array-library behavior into IRx.
Canonical Representation¶
The canonical view descriptor is the identified struct irx_buffer_view with
this stable field order:
| Index | Field | Meaning |
|---|---|---|
| 0 | data |
Opaque data pointer. |
| 1 | owner |
Opaque owner handle or null. |
| 2 | dtype |
Opaque dtype handle or stable token. |
| 3 | ndim |
Rank as i32. |
| 4 | shape |
Pointer to i64 shape metadata. |
| 5 | strides |
Pointer to i64 stride metadata. |
| 6 | offset_bytes |
Byte offset from data. |
| 7 | flags |
Ownership, mutability, layout, and interop flags. |
The lowered LLVM shape is:
%"irx_buffer_view" = type {i8*, i8*, i8*, i32, i64*, i64*, i64, i32}
There are no hidden headers or backend-only object layouts. IRx lowers the descriptor as a plain struct value, consistent with the project struct ABI foundation.
Built-In Primitive Dtype Tokens¶
When a producer does not need an out-of-band dtype handle, it may use these
stable low-level primitive dtype tokens in the dtype field:
| Token | Name |
|---|---|
| 1 | bool |
| 2 | int8 |
| 3 | int16 |
| 4 | int32 |
| 5 | int64 |
| 6 | uint8 |
| 7 | uint16 |
| 8 | uint32 |
| 9 | uint64 |
| 10 | float32 |
| 11 | float64 |
These tokens are a low-level interop convenience, not a full dtype system. Producers may still use opaque dtype handles where that is a better fit.
Ownership¶
Ownership is explicit in the descriptor flags and is never inferred from unrelated fields.
- Borrowed views set the borrowed flag, use a null owner handle, and do not free memory.
- Owned views set the owned flag and use a non-null owner handle managed by runtime/native helpers.
- External-owner views set the external-owner flag and use a non-null owner handle representing imported storage or host-managed lifetime.
- Exactly one ownership flag must be set.
- Copying a descriptor copies metadata only.
- Descriptor copies are shallow.
- Deep copy is explicit and is not performed by assignment, argument passing, or generic lowering.
- Retain and release are explicit runtime/native operations, not hidden generic lowering behavior.
- Retain and release require an owned or external-owner view when the ownership state is statically known; borrowed views are not lifetime-managed by IRx.
The current buffer runtime feature provides opaque owner retain/release
helpers and view retain/release helpers. The owner handle remains opaque in LLVM
IR.
Mutability¶
Mutability is attached to the view.
- Readonly views set the readonly flag.
- Writable views set the writable flag.
- Exactly one mutability flag must be set.
- Writes through statically readonly views are rejected during semantic analysis.
- Mutable borrowed views are allowed when the producer's storage contract makes that safe.
This deliberately separates "may write through this view" from "who owns the underlying allocation."
Interop Sidecars¶
The buffer/view substrate may advertise extra producer-side metadata through generic interop flags.
IRX_BUFFER_FLAG_VALIDITY_BITMAPmeans the producer has separate validity metadata for the same logical elements.- The flag does not make generic buffer indexing null-aware.
- A consumer that cares about validity semantics must use the producer-specific API that created the view.
- The Arrow runtime uses this flag when projecting nullable fixed-width arrays
into
irx_buffer_view.
Shape And Strides¶
Shape and strides describe logical indexing, not ownership.
ndimmust be non-negative.- Shape length must match
ndim. - Stride length must match
ndim. - Shape dimensions must be non-negative.
offset_bytesmust be non-negative.- Null data with nonzero static extent is rejected.
- Contiguity is represented as explicit or derivable metadata; rank alone does not imply contiguity.
The descriptor supports contiguous and non-contiguous views. IRx does not add high-level slicing or broadcasting semantics in this layer.
Raw Byte Writes¶
BufferViewWrite is a narrow raw byte write helper used by lowering tests and
future compiler-generated substrate operations. It writes one 8-bit integer
through a view at offset_bytes + byte_offset.
It is not a generic typed element store, not a slicing operation, and not an array mutation API. Typed element stores, dtype-aware indexing, and higher-level container mutations belong in future Arx-facing layers.
Runtime And Native Boundaries¶
IRx-internal lowering may pass buffer views as plain struct values where that is consistent with the existing struct-lowering rules. Runtime/native boundaries use explicit helper calls and pointer-to-descriptor conventions for lifetime operations.
The buffer runtime feature is activated only when a buffer helper symbol is
requested, such as irx_buffer_view_retain or irx_buffer_view_release. Plain
descriptor lowering does not drag in native runtime artifacts.
The runtime boundary is intentionally conservative:
- owner handles are opaque at the IR level
- retain/release are explicit calls for owned or external-owner views
- ownership transfer is a helper-level concern
- descriptor copies remain shallow metadata copies
- raw byte writes remain a narrow substrate primitive
- no particular high-level array library is assumed
The IRx-owned Python AST helper nodes for descriptors, raw byte writes, and runtime helper calls are internal compiler substrate nodes. They are not intended as a source-level buffer programming model.