# gizlang:native

Native code a library did not compile itself: a dynamic library's symbols and calls through them (a GPU driver), raw memory, a generated CPU kernel run on every core, and a native resource a Gizlang value owns. A `Native` comes only from a `System`, so only code main handed its authority loads native code.

```gizlang
import * as Native from "gizlang:native";
```

## Types

### `Native`

```gizlang
type Native
```

The authority to load and call native code.

Opaque: create and use it through this module's functions.

### `Library`

```gizlang
type Library
```

A loaded dynamic library.

Opaque: create and use it through this module's functions.

### `Owned`

```gizlang
type Owned
```

A native resource held by a value: `get` gives the resource (a pointer or
handle); when the last copy is dropped its release runs.

Opaque: create and use it through this module's functions.

### `Release`

```gizlang
type Release = { release: u64; a: u64; b: u64; }
```

A release that a native library queued: the function and its two arguments.

- `release`: `u64`
- `a`: `u64`
- `b`: `u64`

### `Callback`

```gizlang
type Callback = { target: u64; first: u64; size: i64; result: i64; tag: i64; records: u64; }
```

What a C callback (Native.callback) does when a library calls it as `int f(void *user, void *arg)`: forward `arg`
to `target(first, arg)` (when target is not 0) and answer `result` if that gives 0, else 0; with no target, answer
`result`. With `size` > 0 it also records the `size` bytes at `arg` (none when arg is null) with `tag` on
`records` (Native.records).

- `target`: `u64`
- `first`: `u64`
- `size`: `i64`
- `result`: `i64`
- `tag`: `i64`
- `records`: `u64`

### `Record`

```gizlang
type Record = { tag: i64; data: bytes; }
```

A record a callback made: its tag and the bytes it was given.

- `tag`: `i64`
- `data`: `bytes`

## Functions

### `native`

```gizlang
function native(sys: System): Native
```

The authority to load native libraries and use native memory, given by the System.

## Methods

### `Owned.get`

```gizlang
function Owned.get(self: Owned): u64
```

The resource that this value holds (a pointer or handle).

### `Owned.past`

```gizlang
function Owned.past(self: Owned, offset: u64): Owned
```

The address `offset` bytes past this one's, keeping this one alive.

### `Native.open`

```gizlang
function Native.open(self: Native, path: string): Option<Library>
```

The library at `path` as the dynamic loader finds it ("libcuda.so.1").

Effects: fail, io.

### `Native.libc`

```gizlang
function Native.libc(self: Native): Option<Library>
```

The C library of this platform: Linux's libc.so.6, macOS's libSystem or Windows' ucrtbase.dll; none where none
loads. Code that calls libc opens it here, never by one platform's name.

Effects: fail, io.

### `Library.symbol`

```gizlang
function Library.symbol(self: Library, name: string): Option<u64>
```

A symbol's address, or none.

Effects: fail, io.

### `Native.call`

```gizlang
function Native.call(self: Native, target: u64, arguments: Vec<u64>): u64
```

Calls the C function at `target` with integer-class arguments (at most
20: pointers, sizes, handles), giving its integer result (0 for void).

Effects: fail, io.

### `Native.allocate`

```gizlang
function Native.allocate(self: Native, size: i64): u64
```

A new 64-byte-aligned block of `size` bytes, not zeroed; `free` it, or `own` it.

Effects: fail, io.

### `Native.free`

```gizlang
function Native.free(self: Native, address: u64): void
```

Frees the native memory at ADDRESS.

Effects: fail, io.

### `Native.read`

```gizlang
function Native.read(self: Native, address: u64, length: i64): bytes
```

`length` bytes at `address`, copied.

Effects: fail, io.

### `Native.write`

```gizlang
function Native.write(self: Native, address: u64, data: bytes): void
```

`data` copied to `address`.

Effects: fail, io.

### `Native.copy`

```gizlang
function Native.copy(self: Native, target: u64, source: u64, length: i64): void
```

Copies LENGTH bytes from SOURCE to TARGET in native memory.

Effects: fail, io.

### `Native.flush`

```gizlang
function Native.flush(self: Native, address: u64, length: i64): void
```

Writes the CPU cache lines of `length` bytes at `address` back to memory and drops them: for memory a device reads or
writes without snooping the caches (an NPU's buffers). No step on targets other than x86 and Arm.

Effects: fail, io.

### `Native.readInto`

```gizlang
function Native.readInto(self: Native, address: u64, into: mut bytes, length: i64): void
```

LENGTH bytes at `address` copied into the start of `into`, with no allocation (a queue loop that reuses one buffer).
A LENGTH beyond `into` is a fault.

Effects: fail.

### `Native.writePrefix`

```gizlang
function Native.writePrefix(self: Native, address: u64, data: bytes, length: i64): void
```

The first LENGTH bytes of `data` copied to `address`, with no allocation. A LENGTH beyond `data` is a fault.

Effects: fail.

### `Native.writeF32`

```gizlang
function Native.writeF32(self: Native, target: u64, data: Vec<f32>): void
```

The items of `data` written at `target`, and `count` f32 items at `address` as
a new Vec: device buffers filled and read without a bytes value between.

Effects: fail, io.

### `Native.readF32`

```gizlang
function Native.readF32(self: Native, address: u64, count: i64): Vec<f32>
```

COUNT 32-bit floats at ADDRESS, copied.

Effects: fail, io.

### `Native.now`

```gizlang
function Native.now(self: Native): i64
```

Nanoseconds of a monotonic clock.

Effects: fail, io.

### `Native.parallel`

```gizlang
function Native.parallel(self: Native, kernel: u64, arguments: u64, count: i64, grain: i64): void
```

Runs `void kernel(const u64 *arguments, i64 begin, i64 end)` over
[0, count) in chunks of `grain` on every core (Task.parallel's pool).

Effects: fail, io.

### `Native.own`

```gizlang
function Native.own(self: Native, value: u64, release: u64, a: u64, b: u64, queue: u64): Owned
```

`value` owned by the returned function value: once its last copy is
dropped, `release(a, b)` runs (a C function), or with a `queue` it is put
there for `drain`.

Effects: fail, io.

### `Native.queue`

```gizlang
function Native.queue(self: Native): u64
```

A queue of releases (Native.own) for a library to run when it is safe.

Effects: fail, io.

### `Native.drain`

```gizlang
function Native.drain(self: Native, queue: u64): Vec<Release>
```

The releases queued so far, oldest first, taken off the queue.

Effects: fail, io.

### `Native.callback`

```gizlang
function Native.callback(self: Native, c: Callback): Option<u64>
```

A C function pointer that does `c` (one of 64; undefined when all are taken), for a library that calls back on the
caller's thread, such as NVDEC's parser. Free it with uncallback.

Effects: fail, io.

### `Native.uncallback`

```gizlang
function Native.uncallback(self: Native, address: u64): void
```

Frees a callback that `callback` made. The address must not be called after this.

Effects: fail, io.

### `Native.records`

```gizlang
function Native.records(self: Native): u64
```

A list for callbacks' records: it keeps the order of the calls of every callback that shares it.

Effects: fail, io.

### `Native.recorded`

```gizlang
function Native.recorded(self: Native, records: u64): Vec<Record>
```

The records so far, oldest first, taken off the list.

Effects: fail, io.

### `Native.unrecord`

```gizlang
function Native.unrecord(self: Native, records: u64): void
```

Frees a list of records and what it still holds.

Effects: fail, io.

