Skip to content

Commit 1e7c4d5

Browse files
authored
flambda-backend: Document arrays of unboxed numbers (ocaml-flambda#2672)
* Document arrays of unboxed numbers: * Maybe fix markdown * Notes from review * Fix HTML anchors * Try again to fix HTML anchor
1 parent ba2d0d7 commit 1e7c4d5

File tree

1 file changed

+61
-2
lines changed
  • jane/doc/extensions/unboxed-types

1 file changed

+61
-2
lines changed

jane/doc/extensions/unboxed-types/index.md

+61-2
Original file line numberDiff line numberDiff line change
@@ -217,14 +217,17 @@ Here by defining module type `S` with layout `any` and using `with` constraints,
217217
reason about modules with similar shapes but that operate on different layouts. This removes code
218218
duplication and can aid ppxs in supporting unboxed types.
219219

220+
<!-- This heading is referred to by name in a link to an HTML anchor below.
221+
If you rename it, please also update that link.
222+
-->
220223
# `[@layout_poly]` attribute
221224

222225
The attribute enables support for **limited layout polymorphism on external
223226
`%`-primitives**. This is possible because these primitives are always inlined at every
224227
use site. We can thus specialize the function implementation based on the layout
225228
information at each site.
226229

227-
With a `[@layout-poly]` external declaration like this:
230+
With a `[@layout_poly]` external declaration like this:
228231

229232
```ocaml
230233
external[@layout_poly] opaque_identity : ('a : any). 'a -> 'a = "%opaque"
@@ -270,7 +273,7 @@ let f2 : float# -> float# = magic;; (* ok *)
270273
let f3 : float# -> int32# = magic;; (* error *)
271274
```
272275

273-
This feature is conceptually similar to `[@local_opt]` for modes and would be useful for
276+
This feature is conceptually similar to `[@local_opt]` for modes and is useful for
274277
array access primitives.
275278

276279
Here's the list of primitives that currently support `[@layout_poly]`:
@@ -285,17 +288,73 @@ Here's the list of primitives that currently support `[@layout_poly]`:
285288
* `%array_safe_set`
286289
* `%array_unsafe_get`
287290
* `%array_unsafe_set`
291+
* `%array_size`
292+
293+
# Arrays of unboxed elements
294+
295+
Arrays can store elements of any layout. You can think of `array` as having been declared as:
296+
297+
```ocaml
298+
type ('a : any) array = (* ... *)
299+
```
300+
301+
Array elements are packed according to their width. For example, arrays of
302+
elements whose layout is `bits32` store two elements per word.
303+
304+
You can use normal array syntax for constructing such an array:
305+
306+
```ocaml
307+
let array = [| #2l |]
308+
```
309+
310+
Array primitives must be declared with `[@layout_poly]` to be usable with arrays of unboxed elements.
311+
312+
```ocaml
313+
module Array = struct
314+
external[@layout_poly] get : ('a : any). 'a array -> int -> 'a = "%array_safe_get"
315+
end
316+
317+
let first_elem () = array.(0)
318+
```
319+
320+
(The above relies on the fact that array projection syntax desugars to a call to whatever `Array.get` is in scope.)
321+
322+
A limited set of primitives may be bound as `[@layout_poly]`;
323+
[see the earlier section](#layout_poly-attribute) for more information.
324+
325+
## Runtime representation
326+
327+
| Array | Tag | Layout of data |
328+
|----------------------------------|--------------------|-------------------------------------------------------------|
329+
| `float# array` | `Double_array_tag` | 64 bits per element |
330+
| `int64# array` | `Custom_tag` | reserved custom block word, followed by 64 bits per element |
331+
| `float32# array`, `int32# array` | `Custom_tag` | reserved custom block word, followed by 32 bits per element |
332+
333+
The above table is written about concrete types like `float#` and `int64#`, but
334+
actually holds for all types of the relevant layout.
335+
336+
The reserved custom block word is the standard custom block field that stores a
337+
pointer to the record of custom operations, like polymorphic equality and
338+
comparison. For unboxed 32-bit element types, like `int32#` and `float32#`, the
339+
custom operations pointer is different for odd-length arrays and even-length
340+
arrays.
341+
342+
Odd-length arrays of 32-bit element type have 32 bits of padding at the end.
343+
The contents of this padding is unspecified, and it is not guaranteed that
344+
the padding value will be preserved by the generated code or the runtime.
288345

289346
# Using unboxed types in structures
290347

291348
Unboxed types can usually be put in structures, though there are some restrictions.
292349

293350
These structures may contain unboxed types, but have some restrictions on field
294351
orders:
352+
295353
* Records
296354
* Constructors
297355

298356
Unboxed numbers can't be put in these structures:
357+
299358
* Constructors with inline record fields
300359
* Exceptions
301360
* Extensible variant constructors

0 commit comments

Comments
 (0)