The C code can then recover the exception identifier using `caml_named_value` and pass it as first argument to the functions `raise, `raise_with_argv`, and `raise_with_string` (described in section 22.4.7) to actually raise the exception. For example, here is a C function that raises the `Error` exception with the given argument:

```c
void raise_error(char * msg)
{
    camlóg_raise_with_string(*caml_named_value("test exception"), msg);
}
```

### 22.7.4 Main program in C

In normal operation, a mixed OCaml/C program starts by executing the OCaml initialization code, which then may proceed to call C functions. We say that the main program is the OCaml code. In some applications, it is desirable that the C code plays the role of the main program, calling OCaml functions when needed. This can be achieved as follows:

* The C part of the program must provide a `main` function, which will override the default `main` function provided by the OCaml runtime system. Execution will start in the user-defined `main` function just like for a regular C program.

* At some point, the C code must call `caml_main(argv)` to initialize the OCaml code. The `argv` argument is a C array of strings (type `char **`), terminated with a `NULL` pointer, which represents the command-line arguments, as passed as second argument to `main`. The OCaml array `Sys.argv` will be initialized from this parameter. For the bytecode compiler, `argv[0]` and `argv[1]` are also consulted to find the file containing the bytecode.

* The call to `caml_main` initializes the OCaml runtime system, loads the bytecode (in the case of the bytecode compiler), and executes the initialization code of the OCaml program. Typically, this initialization code registers callback functions using `Callback.register`. Once the OCaml initialization code is complete, control returns to the C code that called `caml_main`.

* The C code can then invoke OCaml functions using the callback mechanism (see section 22.7.1).

### 22.7.5 Embedding the OCaml code in the C code

The bytecode compiler in custom runtime mode (`ocamlc -custom`) normally appends the bytecode to the executable file containing the custom runtime. This has two consequences. First, the final linking step must be performed by `ocamlc`. Second, the OCaml runtime library must be able to find the name of the executable file from the command-line arguments. When using `caml_main(argv)` as in section 22.7.4, this means that `argv[0]` or `argv[1]` must contain the executable file name.

An alternative is to embed the bytecode in the C code. The `-output-obj` and `-output-complete-obj` options to `ocamlc` are provided for this purpose. They cause the `ocamlc` compiler to output a C object file (`.o` file, `.obj` under Windows) containing the bytecode for the OCaml part of the program, as well as a `caml_startup` function. The C object file produced by `ocamlc -output-complete-obj` also contains the runtime and autolink libraries. The C object file produced by `ocamlc -output-obj` or `ocamlc -output-complete-obj` can then be linked with C code using the standard C compiler, or stored in a C library.
### 22.3.1 Atomic types

<table><thead><tr><td>OCaml type</td><td>Encoding</td></tr></thead><tbody><tr><td>int</td><td>Unboxed integer values.</td></tr><tr><td>char</td><td>Unboxed integer values (ASCII code).</td></tr><tr><td>float</td><td>Blocks with tag Double_tag.</td></tr><tr><td>bytes</td><td>Blocks with tag String_tag.</td></tr><tr><td>string</td><td>Blocks with tag String_tag.</td></tr><tr><td>int32</td><td>Blocks with tag Custom_tag.</td></tr><tr><td>int64</td><td>Blocks with tag Custom_tag.</td></tr><tr><td>nativeint</td><td>Blocks with tag Custom_tag.</td></tr></tbody></table>

### 22.3.2 Tuples and records

Tuples are represented by pointers to blocks, with tag 0.

Records are also represented by zero-tagged blocks. The ordering of labels in the record type declaration determines the layout of the record fields: the value associated to the label declared first is stored in field 0 of the block, the value associated to the second label goes in field 1, and so on.

As an optimization, records whose fields all have static type `float` are represented as arrays of floating-point numbers, with tag `Double_array_tag`. (See the section below on arrays.)

As another optimization, unboxed record types are represented specially; unboxed record types are the immutable record types that have only one field. An unboxed type will be represented in one of two ways: boxed or unboxed. Boxed record types are represented as described above (by a block with tag 0 or `Double_array_tag`). An unboxed record type is represented directly by the value of its field (i.e. there is no block to represent the record itself).

The representation is chosen according to the following, in decreasing order of priority:

* An attribute (`[@@boxed]` or `[@@unboxed]`) on the type declaration.

* A compiler option (`-unboxed-types` or `-no-unboxed-types`).

* The default representation. In the present version of OCaml, the default is the boxed representation.

### 22.3.3 Arrays

Arrays of integers and pointers are represented like tuples and records, that is, as pointers to blocks tagged 0. They are accessed with the `Field` macro for reading and the `caml_modify` function for writing.

Values of type `floatarray` (as manipulated by the `Float Array` module), as well as records whose declaration contains only float fields, use an efficient unboxed representation: blocks with tag `Double_array_tag` whose content consist of raw double values, which are not themselves valid OCaml values. They should be accessed using the `Double_flat_field` and `Store_double_flat_field` macros.

Finally, arrays of type `float array` may use either the boxed or the unboxed representation depending on the how the compiler is configured. They currently use the unboxed representation by default, but can be made to use the boxed representation by passing the `--disable-flat-float-array`
The `caml_startup` function must be called from the main C program in order to initialize the OCaml runtime and execute the OCaml initialization code. Just like `caml_main`, it takes one `argv` parameter containing the command-line parameters. Unlike `caml_main`, this `argv` parameter is used only to initialize `Sys.argv`, but not for finding the name of the executable file.

The `caml_startup` function calls the uncaught exception handler (or enters the debugger, if running under ocamldebug) if an exception escapes from a top-level module initialiser. Such exceptions may be caught in the C code by instead using the `caml_startup_exn` function and testing the result using `Is_exception_result` (followed by `Extract_exception` if appropriate).

The `-output-obj` and `-output-complete-obj` options can also be used to obtain the C source file. More interestingly, these options can also produce directly a shared library (`.so` file, `.dll` under Windows) that contains the OCaml code, the OCaml runtime system and any other static C code given to `ocamlc` (`.o`, `.a`, respectively, `.obj`, `.lib`). This use of `-output-obj` and `-output-complete-obj` is very similar to a normal linking step, but instead of producing a main program that automatically runs the OCaml code, it produces a shared library that can run the OCaml code on demand. The three possible behaviors of `-output-obj` and `-output-complete-obj` (to produce a C source code `.c`, a C object file `.o`, a shared library `.so`), are selected according to the extension of the resulting file (given with `-o`).

The native-code compiler `ocamlopt` also supports the `-output-obj` and `-output-complete-obj` options, causing it to output a C object file or a shared library containing the native code for all OCaml modules on the command-line, as well as the OCaml startup code. Initialization is performed by calling `caml_startup` (or `caml_startup_exn`) as in the case of the bytecode compiler. The file produced by `ocamlopt -output-complete-obj` also contains the runtime and autolink libraries.

For the final linking phase, in addition to the object file produced by `-output-obj`, you will have to provide the OCaml runtime library (`libcamlrun.a` for bytecode, `libasmrun.a` for native-code), as well as all C libraries that are required by the OCaml libraries used. For instance, assume the OCaml part of your program uses the Unix library. With `ocamlc`, you should do:

```
ocamlc -output-obj -o camlcode.o unix.cma other .cmo and .cma files
cc -o myprog C objects and libraries \
    camlcode.o -L'ocamlc -where' -lunix -lcamlrun
```

With `ocamlopt`, you should do:

```
ocamlopt -output-obj -o camlcode.o unix.cmxa other .cmx and .cmxa files
cc -o myprog C objects and libraries \
    camlcode.o -L'ocamlc -where' -lunix -lasmrun
```

For the final linking phase, in addition to the object file produced by `-output-complete-obj`, you will have only to provide the C libraries required by the OCaml runtime.

For instance, assume the OCaml part of your program uses the Unix library. With `ocamlc`, you should do:

```
ocamlc -output-complete-obj -o camlcode.o unix.cma other .cmo and .cma files
cc -o myprog C objects and libraries \
    camlcode.o C libraries required by the runtime, eg -lm -ldl -lcurses -lpthread
```

With `ocamlopt`, you should do:
flag to the 'configure' script. They should be accessed using the `Double_array_field` and `Store_double_array_field` macros, which will work correctly under both modes.

### 22.3.4 Concrete data types

Constructed terms are represented either by unboxed integers (for constant constructors) or by blocks whose tag encode the constructor (for non-constant constructors). The constant constructors and the non-constant constructors for a given concrete type are numbered separately, starting from 0, in the order in which they appear in the concrete type declaration. A constant constructor is represented by the unboxed integer equal to its constructor number. A non-constant constructor declared with *n* arguments is represented by a block of size *n*, tagged with the constructor number; the *n* fields contain its arguments. Example:

<table><thead><tr><td>Constructed term</td><td>Representation</td></tr></thead><tbody><tr><td>()</td><td>Val_int(0)</td></tr><tr><td>false</td><td>Val_int(0)</td></tr><tr><td>true</td><td>Val_int(1)</td></tr><tr><td>[]</td><td>Val_int(0)</td></tr><tr><td>h::t</td><td>Block with size = 2 and tag = 0; first field contains h, second field t.</td></tr></tbody></table>

As a convenience, `caml/mlvalues.h` defines the macros `Val_unit`, `Val_false`, `Val_true` and `Val_emptylist` to refer to `()`, `false`, `true` and `[]`.

The following example illustrates the assignment of integers and block tags to constructors:

```c
type t =
  | A          (* First constant constructor -> integer "Val_int(0)" *)
  | B of string (* First non-constant constructor -> block with tag 0 *)
  | C          (* Second constant constructor -> integer "Val_int(1)" *)
  | D of bool   (* Second non-constant constructor -> block with tag 1 *)
  | E of t * t  (* Third non-constant constructor -> block with tag 2 *)
```

As an optimization, unboxed concrete data types are represented specially; a concrete data type is unboxed if it has exactly one constructor and this constructor has exactly one argument. Unboxed concrete data types are represented in the same ways as unboxed record types: see the description in section 22.3.2.

### 22.3.5 Objects

Objects are represented as blocks with tag `Object_tag`. The first field of the block refers to the object's class and associated method suite, in a format that cannot easily be exploited from C. The second field contains a unique object ID, used for comparisons. The remaining fields of the object contain the values of the instance variables of the object. It is unsafe to access directly instance variables, as the type system provides no guarantee about the instance variables contained by an object.

One may extract a public method from an object using the C function `caml_get_public_method` (declared in `<caml/mlvalues.h>`) . Since public method tags are hashed in the same way as variant
ocamlopt -output-complete-obj -o camlcode.o unix.cmxa other .cmx and .cmxa files

cc -o myprog C objects and libraries \
camlcode.o C libraries required by the runtime, eg -lm -ldl

**Warning:** On some ports, special options are required on the final linking phase that links
together the object file produced by the -output-obj and -output-complete-obj options and the
remainder of the program. Those options are shown in the configuration file Makefile.config
generated during compilation of OCaml, as the variable OC_LDFLAGS.

* Windows with the MSVC compiler: the object file produced by OCaml have been compiled with the /MD flag, and therefore all other object files linked with it should also be compiled with /MD.

* other systems: you may have to add one or both of -lm and -ldl, depending on your OS and C compiler.

**Stack backtraces.** When OCaml bytecode produced by ocamlc -g is embedded in a C program, no debugging information is included, and therefore it is impossible to print stack backtraces on uncaught exceptions. This is not the case when native code produced by ocamlopt -g is embedded in a C program: stack backtrace information is available, but the backtrace mechanism needs to be turned on programmatically. This can be achieved from the OCaml side by calling Printexc.record_backtrace true in the initialization of one of the OCaml modules. This can also be achieved from the C side by calling caml_record_backtraces(1); in the OCaml-C glue code. (caml_record_backtraces is declared in backtrace.h)

**Unloading the runtime.**

In case the shared library produced with -output-obj is to be loaded and unloaded repeatedly
by a single process, care must be taken to unload the OCaml runtime explicitly, in order to avoid
various system resource leaks.

Since 4.05, caml_shutdown function can be used to shut the runtime down gracefully, which
equals the following:

* Running the functions that were registered with Stdlib.at_exit.

* Triggering finalization of allocated custom blocks (see section 22.9). For example, Stdlib.in_channel and Stdlib.out_channel are represented by custom blocks that enclose file descriptors, which are to be released.

* Unloading the dependent shared libraries that were loaded by the runtime, including dynlink plugins.

* Freeing the memory blocks that were allocated by the runtime with malloc. Inside C primitives, it is advised to use caml_stat_* functions from memory.h for managing static (that is, non-moving) blocks of heap memory, as all the blocks allocated with these functions are automatically freed by caml_shutdown. For ensuring compatibility with legacy C stubs that have used caml_stat_* incorrectly, this behaviour is only enabled if the runtime is started with a specialized caml_startup_pooled function.
tags, and methods are functions taking self as first argument, if you want to do the method call `foo#bar` from the C side, you should call:

```c
callback(caml_get_public_method(foo, caml_hash("bar")), foo);
```

### 22.3.6 Polymorphic variants

Like constructed terms, polymorphic variant values are represented either as integers (for polymorphic variants without argument), or as blocks (for polymorphic variants with an argument). Unlike constructed terms, variant constructors are not numbered starting from 0, but identified by a hash value (an OCaml integer), as computed by the C function `caml_hashVariant` (declared in `<caml/mlvalues.h>`): the hash value for a variant constructor named, say, `VConstr` is `caml_hashpong`("VConstr").

The variant value `VConstr` is represented by `caml_hash`_variant("VConstr"). The variant value `VConstr(v)` is represented by a block of size 2 and tag 0, with field number 0 containing `caml_hash`_variant("VConstr") and field number 1 containing `v`.

Unlike constructed values, polymorphic variant values taking several arguments are not flattened. That is, `VConstr(v, w)` is represented by a block of size 2, whose field number 1 contains the representation of the pair `(v, w)`, rather than a block of size 3 containing `v` and `w` in fields 1 and 2.

## 22.4 Operations on values

### 22.4.1 Kind tests

* `Is_long(v)` is true if value `v` is an immediate integer, false otherwise

* `Is_block(v)` is true if value `v` is a pointer to a block, and false if it is an immediate integer.

* `Is_none(v)` is true if value `v` is `None`.

* `Is_some(v)` is true if value `v` (assumed to be of option type) corresponds to the Some constructor.

### 22.4.2 Operations on integers

The header `<caml/config.h>` defines a C integer type `intnat` of signed 64-bit integers (32-bit integers on 32-bit architectures). This type is used to represent the integer encoded by a value corresponding to an unboxed integer without truncation.

* `Val_long(n)` returns the value encoding the `intnat` `n`.

* `Long_val(v)` returns the `intnat` encoded in value `v`.

* `Val_int(i)` returns the value encoding the `int` `i`.

* `Int_val(v)` returns the `int` encoded in value `v`. Note that this operation may result in a truncated value since `int` is 32-bit wide on 64-bit architectures.

* `Val_bool(x)` returns the OCaml boolean representing the truth value of the C integer `x`.
As a shared library may have several clients simultaneously, it is made for convenience that `caml_startup` (and `caml_startup_pooled`) may be called multiple times, given that each such call is paired with a corresponding call to `caml_shutdown` (in a nested fashion). The runtime will be unloaded once there are no outstanding calls to `caml_startup`.

Once a runtime is unloaded, it cannot be started up again without reloading the shared library and reinitializing its static data. Therefore, at the moment, the facility is only useful for building reloadable shared libraries.

**Unix signal handling.** Depending on the target platform and operating system, the native-code runtime system may install signal handlers for one or several of the `SIGSEGV`, `SIGTRAP` and `SIGFPE` signals when `caml_startup` is called, and reset these signals to their default behaviors when `caml_shutdown` is called. The main program written in C should not try to handle these signals itself.

## 22.8 Advanced example with callbacks

This section illustrates the callback facilities described in section 22.7. We are going to package some OCaml functions in such a way that they can be linked with C code and called from C just like any C functions. The OCaml functions are defined in the following `mod.ml` OCaml source:

```c
(* File mod.ml -- some "useful" OCaml functions *)

let rec fib n = if n < 2 then 1 else fib(n-1) + fib(n-2)

let format_result n = Printf.sprintf "Result is: %d\n" n

(* Export those two functions to C *)

let _ = Callback.register "fib" fib
let _ = Callback.register "format_result" format_result
```

Here is the C stub code for calling these functions from C:

```c
/* File modwrap.c -- wrappers around the OCaml functions */

#include <stdio.h>
#include <string.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>

int fib(int n)
{
    static const value * fib_closure = NULL;
    if (fib_closure == NULL) fib_closure = caml_named_value("fib");
    return Int_val(caml_callback(*fib_closure, Val_int(n)));
```
* `Bool_val(v)` returns 0 if `v` is the OCaml boolean `false`, 1 if `v` is `true`.

* `Val_true`, `Val_false` represent the OCaml booleans `true` and `false`.

* `Val_emptylist` represents the empty list.

* `Val_none` represents the OCaml value `None`.

### 22.4.3 Accessing blocks

* `Wosize_val(v)` returns the size of the block `v`, in words, excluding the header.

* `Tag_val(v)` returns the tag of the block `v`.

* `Field(v, n)` returns the value contained in the `n` field of the structured block `v`. Fields are numbered from 0 to `Wosize_val(v) - 1`.

* `Store_field(b, n, v)` stores the value `v` in the field number `n` of value `b`, which must be a structured block.

* `Code_val(v)` returns the code part of the closure `v`.

* `caml_string_length(v)` returns the length (number of bytes) of the string or byte sequence `v`.

* `Byte(v, n)` returns the `n` byte of the string or byte sequence `v`, with type `char`. Bytes are numbered from 0 to `string_length(v) - 1`.

* `Byte_u(v, n)` returns the `n` byte of the string or byte sequence `v`, with type `unsigned char`. Bytes are numbered from 0 to `string_length(v) - 1`.

* `String_val(v)` returns a pointer to the first byte of the string `v`, with type `const char *`. This pointer is a valid C string: there is a null byte after the last byte in the string. However, OCaml strings can contain embedded null bytes, which will confuse the usual C functions over strings. The function `caml_string_is_c_safe(v)` returns `true` if the OCaml string `v` does not contain any embedded null bytes.

* `Bytes_val(v)` returns a pointer to the first byte of the byte sequence `v`, with type `unsigned char *`.

* `Double_val(v)` returns the floating-point number contained in value `v`, with type `double`.

* `Double_array_field(v, n)` returns the `n` element of a `float` array `v`.

* `Store_double_array_field(v, n, d)` stores the double precision floating-point number `d` in the `n` element of a `float` array `v`.

* `Double_flat_field(v, n)` returns the `n` element of a `floatarray` or a record of floats `v` (an unboxed block tagged `Double_array_tag`).

* `Store_double_flat_field(v, n, d)` stores the double precision floating-point number `d` in the `n` element of a `floatarray` or a record of floats `v`.
```c
}

char * format_result(int n)
{
    static const value * format_result_closed = NULL;
    if (format_result_closed == NULL)
        format_result_closed = caml_named_value("format_result");
    return strsup(String_val(caml_callback(*format_result_closed, Val_int(n))));
    /* We copy the C string returned by String_val to the C heap
     * so that it remains valid after garbage collection. */
}
```

We now compile the OCaml code to a C object file and put it in a C library along with the stub code in `modwrap.c` and the OCaml runtime system:

```
ocamlc -custom -output-obj -o modcaml.o mod.ml
ocamlc -c modwrap.c
cp `ocamlc -where`/libcamlrun.a mod.a && chmod +w mod.a
ar r mod.a modcaml.o modwrap.o
```

(One can also use `ocamlopt -output-obj` instead of `ocamlc -custom -output-obj`. In this case, replace `libcamlrun.a` (the bytecode runtime library) by `libasmrun.a` (the native-code runtime library).)

Now, we can use the two functions `fib` and `format_result` in any C program, just like regular C functions. Just remember to call `caml_startup` (or `caml_startup_exn`) once before.

```c
/* File main.c -- a sample client for the OCaml functions */

#include <stdio.h>
#include <caml/callback.h>

extern int fib(int n);
extern char * format_result(int n);

int main(int argc, char ** argv)
{
    int result;

    /* Initialize OCaml code */
    caml_startup(argv);
    /* Do some computation */
    result = fib(10);
    printf("fib(10) = %s\n", format_result(result));
    return 0;
}
```

To build the whole program, just invoke the C compiler as follows:
* `Data_custom_val(v)` returns a pointer to the data part of the custom block `v`. This pointer has type `void *` and must be cast to the type of the data contained in the custom block.

* `Int32_val(v)` returns the 32-bit integer contained in the `int32 v`.

* `Int64_val(v)` returns the 64-bit integer contained in the `int64 v`.

* `Nativeint_val(v)` returns the long integer contained in the `nativeint v`.

* `caml_field_unboxed(v)` returns the value of the field of a value `v` of any unboxed type (record or concrete data type).

* `caml_field_boxed(v)` returns the value of the field of a value `v` of any boxed type (record or concrete data type).

* `caml_field_unboxed(v)` calls either `caml_field_unboxed` or `caml_field_boxed` according to the default representation of unboxed types in the current version of OCaml.

* `Some_val(v)` returns the argument `x` of a value `v` of the form `Some(x)`.

The expressions `Field(v, n)`, `Byte(v, n)` and `Byte_u(v, n)` are valid l-values. Hence, they can be assigned to, resulting in an in-place modification of value `v`. Assigning directly to `Field(v, n)` must be done with care to avoid confusing the garbage collector (see below).

### 22.4.4 Allocating blocks

### 22.4.5 Simple interface

* `Atom(t)` returns an "atom" (zero-sized block) with tag `t`. Zero-sized blocks are preallocated outside of the heap. It is incorrect to try and allocate a zero-sized block using the functions below. For instance, `Atom(0)` represents the empty array.

* `caml_alloc(n, t)` returns a fresh block of size `n` with tag `t`. If `t` is less than `No_scan_tag`, then the fields of the block are initialized with a valid value in order to satisfy the GC constraints.

* `caml_alloc_tuple(n)` returns a fresh block of size `n` words, with tag 0.

* `caml_alloc_string(n)` returns a byte sequence (or string) value of length `n` bytes. The sequence initially contains uninitialized bytes.

* `caml_alloc_initialize_string(n, p)` returns a byte sequence (or string) value of length `n` bytes. The value is initialized from the `n` bytes starting at address `p`.

* `caml_copy_string(s)` returns a string or byte sequence value containing a copy of the null-terminated C string `s` (a `char *`).

* `caml_copy_double(d)` returns a floating-point value initialized with the double `d`.

* `caml_copy_int32(i)`, `caml_copy_int64(i)` and `caml_copy_nativeint(i)` return a value of OCaml type `int32`, `int64` and `nativeint`, respectively, initialized with the integer `i`.
cc -o prog -I `ocamlc -where` main.c mod.a -lcurses

(On some machines, you may need to put `-ltermcap` or `-lcurses -ltermcap` instead of `-lcurses`.)

## 22.9 Advanced topic: custom blocks

Blocks with tag `Custom_tag` contain both arbitrary user data and a pointer to a C struct, with type `struct custom_operations`, that associates user-provided finalization, comparison, hashing, serialization and deserialization functions to this block.

### 22.9.1 The struct custom_operations

The `struct custom_operations` is defined in `<caml/custom.h>` and contains the following fields:

* `char *identifier`

A zero-terminated character string serving as an identifier for serialization and deserialization operations.

* `void (*finalize)(value v)`

The `finalize` field contains a pointer to a C function that is called when the block becomes unreachable and is about to be reclaimed. The block is passed as first argument to the function.

The `finalize` field can also be `custom_finalize_default` to indicate that no finalization function is associated with the block.

* `int (*compare)(value v1, value v2)`

The `compare` field contains a pointer to a C function that is called whenever two custom blocks are compared using OCaml's generic comparison operators (`=`, `<>`, `<=`, `>=`, `<`, `>`, and `compare`).

The C function should return 0 if the data contained in the two blocks are structurally equal, a negative integer if the data from the first block is less than the data from the second block, and a positive integer if the data from the first block is greater than the data from the second block.

The `compare` field can be set to `custom_compare_default`; this default comparison function simply raises `Failure`.

* `int (*compare_ext)(value v1, value v2)`

(Since 3.12.1) The `compare_ext` field contains a pointer to a C function that is called whenever one custom block and one unboxed integer are compared using OCaml's generic comparison operators (`=`, `<>`, `<=`, `>=`, `<`, `>`, and `compare`). As in the case of the `compare` field, the C function should return 0 if the two arguments are structurally equal, a negative integer if the first argument compares less than the second argument, and a positive integer if the first argument compares greater than the second argument.

The `compare_ext` field can be set to `custom_compare_ext_default`; this default comparison function simply raises `Failure`.

* `intnat (*hash)(value v)`

The `hash` field contains a pointer to a C function that is called whenever OCaml's generic
* `caml_alloc_array(f, a)` allocates an array of values, calling function `f` over each element of the input array `a` to transform it into a value. The array `a` is an array of pointers terminated by the null pointer. The function `f` receives each pointer as argument, and returns a value. The zero-tagged block returned by `alloc_array(f, a)` is filled with the values returned by the successive calls to `f`. (This function must not be used to build an array of floating-point numbers.)

* `caml_copy_string_array(p)` allocates an array of strings or byte sequences, copied from the pointer to a string array `p` (a `char **`). `p` must be NULL-terminated.

* `caml_alloc_float_array(n)` allocates an array of floating point numbers of size `n`. The array initially contains uninitialized values.

* `caml_alloc_unboxed(v)` returns the value (of any unboxed type) whose field is the value `v`.

* `caml_alloc_boxed(v)` allocates and returns a value (of any boxed type) whose field is the value `v`.

* `caml_alloc_unboxable(v)` calls either `caml_alloc_unboxed` or `caml_alloc_boxed` according to the default representation of unboxable types in the current version of OCaml.

* `caml_alloc_some(v)` allocates a block representing `Some(v)`.

### 22.4.6 Low-level interface

The following functions are slightly more efficient than `caml_alloc`, but also much more difficult to use.

From the standpoint of the allocation functions, blocks are divided according to their size as zero-sized blocks, small blocks (with size less than or equal to `Max_young_wosize`), and large blocks (with size greater than `Max_young_wosize`). The constant `Max_young_wosize` is declared in the include file `mlvalues.h`. It is guaranteed to be at least 64 (words), so that any block with constant size less than or equal to 64 can be assumed to be small. For blocks whose size is computed at run-time, the size must be compared against `Max_young_wosize` to determine the correct allocation procedure.

* `caml_alloc_small(n, t)` returns a fresh small block of size $n \le \text{Max\_young\_wosize}$ words, with tag `t`. If this block is a structured block (i.e. if $t < \text{No\_scan\_tag}$), then the fields of the block (initially containing garbage) must be initialized with legal values (using direct assignment to the fields of the block) before the next allocation.

* `caml_alloc_shr(n, t)` returns a fresh block of size `n`, with tag `t`. The size of the block can be greater than `Max_young_wosize`. (It can also be smaller, but in this case it is more efficient to call `caml_alloc_small` instead of `caml_alloc_shr`.) If this block is a structured block (i.e. if $t < \text{No\_scan\_tag}$), then the fields of the block (initially containing garbage) must be initialized with legal values (using the `caml_initialize` function described below) before the next allocation.
hash operator (see module `Hashtbl` [28.24]) is applied to a custom block. The C function can return an arbitrary integer representing the hash value of the data contained in the given custom block. The hash value must be compatible with the `compare` function, in the sense that two structurally equal data (that is, two custom blocks for which `compare` returns 0) must have the same hash value.

The `hash` field can be set to `custom_hash_default`, in which case the custom block is ignored during hash computation.

* `void (*submit)(value v, uintnat *bsize_32, uintnat *bsize_64)`

The `submit` field contains a pointer to a C function that is called whenever the custom block needs to be serialized (marshaled) using the OCaml functions `output_value` or ` Marshal.to_...`. For a custom block, those functions first write the identifier of the block (as given by the `identifier` field) to the output stream, then call the user-provided `submit` function. That function is responsible for writing the data contained in the custom block, using the `submit`... functions defined in `<caml/intext.h>` and listed below. The user-provided `submit` function must then store in its `bsize_32` and `bsize_64` parameters the sizes in bytes of the data part of the custom block on a 32-bit architecture and on a 64-bit architecture, respectively.

The `submit` field can be set to `customsubmit_default`, in which case the `Failure` exception is raised when attempting to submit the custom block.

* `uintnat (*deserializeto)(void *dst)`

The `deserializeto` field contains a pointer to a C function that is called whenever a custom block with identifier `identifier` needs to be deserialized (un-marshaled) using the OCaml functions `input_value` or ` Marshal.from_...`. This user-provided function is responsible for reading back the data written by the `submit` operation, using the `deserializeto`... functions defined in `<caml/intext.h>` and listed below. It must then rebuild the data part of the custom block and store it at the pointer given as the `dst` argument. Finally, it returns the size in bytes of the data part of the custom block. This size must be identical to the `wsize_32` result of the `submit` operation if the architecture is 32 bits, or `wsize_64` if the architecture is 64 bits.

The `deserializeto` field can be set to `customsubmit_default` to indicate that deserial-ization is not supported. In this case, do not register the `struct custom_operations` with the deserializer using `register_custom_operations` (see below).

* `const struct customécritures* fixed_length`

(Since 4.08.0) Normally, space in the serialized output is reserved to write the `bsize_32` and `bsize_64` fields returned by `submit`. However, for very short custom blocks, this space can be larger than the data itself! As a space optimisation, if `submit` always returns the same values for `bsize_32` and `bsize_64`, then these values may be specified in the `fixed_length` structure, and do not consume space in the serialized output.

Note: the `finalize`, `compare`, `hash`, `submit`, and `submit` functions attached to custom block descriptors must never access the OCaml runtime. Within these functions, do not call any of the OCaml allocation functions, and do not perform a callback into OCaml code. Do not use
### 22.4.7 Raising exceptions

Two functions are provided to raise two standard exceptions:

* `caml_failwith(s)`, where `s` is a null-terminated C string (with type `char *`), raises exception `Failure` with argument `s`.

* `caml_valid argument(s)`, where `s` is a null-terminated C string (with type `char *`), raises exception `Invalid_argument` with argument `s`.

Raising arbitrary exceptions from C is more delicate: the exception constructor is dynamically allocated by the OCaml program, and therefore must be communicated to the C function using the registration facility described below in section 22.7.4. Once the exception constructor is recovered in C, the following functions actually raise the exception:

* `caml_raiseConstant(id)` raises the exception `id` with no argument;

* `caml_raise_with_arg(id, v)` raises the exception `id` with the OCaml value `v` as argument;

* `caml_raise_with_args(id, n, v)` raises the exception `id` with the OCaml values `v[0]`, ..., `v[n-1]` as arguments;

* `caml_raise_with_string(id, s)`, where `s` is a null-terminated C string, raises the exception `id` with a copy of the C string `s` as argument.

Sometimes, it is necessary to clean-up state and release resources before actually raising the exception back into OCaml. To this end, alternative functions that return the exception instead of raising it directly (`caml_exception_failure`, `caml_exception_valid argument`, etc.) are provided. The type `caml_result` represents either an OCaml value or an exception; see section 22.7.2.

## 22.5 Living in harmony with the garbage collector

Unused blocks in the heap are automatically reclaimed by the garbage collector. This requires some cooperation from C code that manipulates heap-allocated blocks.

### 22.5.1 Simple interface

All the macros described in this section are declared in the `memory.h` header file.

**Rule 1** A function that has parameters or local variables of type value must begin with a call to one of the `CAMLparam` macros and return with `CAMLreturn`, `CAMLreturn0`, or `CAMLreturnT`.

There are six `CAMLparam` macros: `CAMLparam0` to `CAMLparam5`, which take zero to five arguments respectively. If your function has no more than 5 parameters of type `value`, use the corresponding macros with these parameters as arguments. If your function has more than 5 parameters of type `value`, use `CAMLparam5` with five of these parameters, and use one or more calls to the `CAMLxparam` macros for the remaining parameters (`CAMLxparam1` to `CAMLxparam5`). If the function has an argument `x` which is an array of values of length `n`, use `CAMLparamN(x, n)` to declare it (or `CAMLxparamN(x, n)` if you already have a call to `CAMLparam` for some other arguments).
`CAMLparam` to register the parameters to these functions, and do not use `CAMLreturn` to return the result. Do not raise exceptions, do not remove global roots, etc.

### 22.9.2 Allocating custom blocks

Custom blocks must be allocated via `caml_alloc_custom` or `caml_alloc_custom_mem`:

`caml_alloc_custom ops size used max`

returns a fresh custom block, with room for `size` bytes of user data, and whose associated operations are given by `ops` (a pointer to a `struct custom_operations`, usually statically allocated as a C global variable).

The two parameters `used` and `max` are used to control the speed of garbage collection when the finalized object contains pointers to out-of-heap resources. Generally speaking, the OCaml incremental major collector adjusts its speed relative to the allocation rate of the program. The faster the program allocates, the harder the GC works in order to reclaim quickly unreachable blocks and avoid having large amount of “floating garbage” (unreferenced objects that the GC has not yet collected).

Normally, the allocation rate is measured by counting the in-heap size of allocated blocks. However, it often happens that finalized objects contain pointers to out-of-heap memory blocks and other resources (such as file descriptors, X Windows bitmaps, etc.). For those blocks, the in-heap size of blocks is not a good measure of the quantity of resources allocated by the program.

The two arguments `used` and `max` give the GC an idea of how much out-of-heap resources are consumed by the finalized block being allocated: you give the amount of resources allocated to this object as parameter `used`, and the maximum amount that you want to see in floating garbage as parameter `max`. The units are arbitrary: the GC cares only about the ratio `used/max`.

For instance, if you are allocating a finalized block holding an X Windows bitmap of `w` by `h` pixels, and you'd rather not have more than 1 mega-pixels of unreclaimed bitmaps, specify `used = w * h` and `max = 1000000`.

Another way to describe the effect of the `used` and `max` parameters is in terms of full GC cycles. If you allocate many custom blocks with `used/max = 1/N`, the GC will then do one full cycle (examining every object in the heap and calling finalization functions on those that are unreachable) every `N` allocations. For instance, if `used = 1` and `max = 1000`, the GC will do one full cycle at least every 1000 allocations of custom blocks.

If your finalized blocks contain no pointers to out-of-heap resources, or if the previous discussion made little sense to you, just take `used = 0` and `max = 1`. But if you later find that the finalization functions are not called “often enough”, consider increasing the `used/max` ratio.

`caml_alloc_custom_mem ops size used`

Use this function when your custom block holds only out-of-heap memory (memory allocated with `malloc` or `caml_stat_alloc`) and no other resources. `used` should be the number of bytes of out-of-heap memory that are held by your custom block. This function works like `caml_alloc_custom` except that the `max` parameter is under the control of the user (via the `custom_major_ratio`, `custom_minor_ratio`, and `custom_minor_max_size` parameters) and proportional to the heap sizes. It has been available since OCaml 4.08.0.
The macros `CAMLreturn`, `CAMLreturn0`, and `CAMLreturnT` are used to replace the C keyword `return`; any function using a `CAMLparam` macro on entry should use `CAMLreturn` on all exit points. C functions exported as OCaml externals must return a `value`, and they should use `CAMLreturn` (`x`) instead of `return x`. Some helper functions may manipulate OCaml values yet return `void` or another datatype. `void`-returning procedures should explicitly use `CAMLreturn0`, and not have any implicit return. Helper functions returning C data of some type `t` should use `CAMLreturnT` (`t`, `x`) instead of `return x`.

**Note:** Some C compilers give bogus warnings about unused variables `caml_ dummy_ xxx` at each use of `CAMLparam` and `CAMLlocal`. You should ignore them.

Examples:

```c
CAMLprim value my_external (value v1, value v2, value v3)
{
    CAMLparam3 (v1, v2, v3);
    ...
    CAMLreturn (Val_unit);
}
```

```c
static void helper_procedure (value v1, value v2)
{
    CAMLparam2 (v1, v2);
    ...
    CAMLreturn0;
}
```

```c
static int helper_function (value v1, value v2)
{
    CAMLparam2 (v1, v2);
    ...
    CAMLreturnT (int, 0);
}
```

**Note:** If your function is a primitive with more than 5 arguments for use with the byte-code runtime, its arguments are not *values* and must not be declared (they have types `value *` and `int`).

**Warning:** `CAMLreturn0` should only be used for internal procedures that return `void`. `CAMLreturn (Val_unit)` should be used for functions that return an OCaml `unit` value. Primitives (C functions that can be called from OCaml) should never return `void`.

**Rule 2** *Local variables of type value must be declared with one of the CAMLlocal macros. Arrays of values are declared with CAMLlocalN. These macros must be used at the beginning of the function, not in a nested block. Temporaries are equivalent to local variables, but they cannot be registered*
### 22.9.3 Accessing custom blocks

The data part of a custom block *v* can be accessed via the pointer `Data_custom_val(v)`. This pointer has type `void *` and should be cast to the actual type of the data stored in the custom block.

The contents of custom blocks are not scanned by the garbage collector, and must therefore not contain any pointer inside the OCaml heap. In other terms, never store an OCaml `value` in a custom block, and do not use `Field`, `Store_field` nor `caml_modify` to access the data part of a custom block. Conversely, any C data structure (not containing heap pointers) can be stored in a custom block.

### 22.9.4 Writing custom serialization and deserialization functions

The following functions, defined in `<caml/intext.h>`, are provided to write and read back the contents of custom blocks in a portable way. Those functions handle endianness conversions when e.g. data is written on a little-endian machine and read back on a big-endian machine.

<table><thead><tr><td>Function</td><td>Action</td></tr></thead><tbody><tr><td>caml_serialize_int_1</td><td>Write a 1-byte integer</td></tr><tr><td>caml_serialize_int_2</td><td>Write a 2-byte integer</td></tr><tr><td>caml_serialize_int_4</td><td>Write a 4-byte integer</td></tr><tr><td>caml_serialize_int_8</td><td>Write a 8-byte integer</td></tr><tr><td>caml_serialize_float_4</td><td>Write a 4-byte float</td></tr><tr><td>caml_serialize_float_8</td><td>Write a 8-byte float</td></tr><tr><td>caml_serialize_block_1</td><td>Write an array of 1-byte quantities</td></tr><tr><td>caml_serialize_block_2</td><td>Write an array of 2-byte quantities</td></tr><tr><td>caml_serialize_block_4</td><td>Write an array of 4-byte quantities</td></tr><tr><td>caml_serialize_block_8</td><td>Write an array of 8-byte quantities</td></tr><tr><td>caml_des工業ize_uint_1</td><td>Read an unsigned 1-byte integer</td></tr><tr><td>caml_des工业ize_sint_1</td><td>Read a signed 1-byte integer</td></tr><tr><td>caml_des工业ize_uint_2</td><td>Read an unsigned 2-byte integer</td></tr><tr><td>caml_des工业ize_sint_2</td><td>Read a signed 2-byte integer</td></tr><tr><td>caml_des工业ize_uint_4</td><td>Read an unsigned 4-byte integer</td></tr><tr><td>caml_des工业ize_sint_4</td><td>Read a signed 4-byte integer</td></tr><tr><td>caml_des工业ize_uint_8</td><td>Read an unsigned 8-byte integer</td></tr><tr><td>caml_des工业ize_sint_8</td><td>Read a signed 8-byte integer</td></tr><tr><td>caml_des工业ize_float_4</td><td>Read a 4-byte float</td></tr><tr><td>caml_des工业ize_float_8</td><td>Read an 8-byte float</td></tr><tr><td>caml_des工业ize_block_1</td><td>Read an array of 1-byte quantities</td></tr><tr><td>caml_des工业ize_block_2</td><td>Read an array of 2-byte quantities</td></tr><tr><td>caml_des工业ize_block_4</td><td>Read an array of 4-byte quantities</td></tr><tr><td>caml_des工业ize_block_8</td><td>Read an array of 8-byte quantities</td></tr><tr><td>caml_des工业ize_error</td><td>Signal an error during deserialization; input_value or Marshal.from... raise a Failure exception after cleaning up their internal data structures</td></tr></tbody></table>
with the garbage collector, so a temporary of type **value** must not be live when a garbage collection may occur.

The macros `CAMLlocal1` to `CAMLlocal5` declare and initialize one to five local variables of type **value**. The variable names are given as arguments to the macros. `CAMLlocalN(x, n)` declares and initializes a local variable of type **value** `[n]`. You can use several calls to these macros if you have more than 5 local variables.

Example:

```c
CAMLprim value bar (value v1, value v2, value v3)
{
    CAMLparam3 (v1, v2, v3);
    CAMLlocal1 (result);
    result = caml_alloc (3, 0);
    ...
    CAMLreturn (result);
}
```

**Warning:** `CAMLlocal` (and `CAMLxparam`) can only be called after `CAMLparam`. If a function declares local values but takes no value argument, it should start with `CAMLparam0 ()`.

```c
static value foo (int n)
{
    CAMLparam0 ();;
    CAMLlocal (result);
    ...
    CAMLreturn (result);
}
```

**Rule 3** Assignments to the fields of structured blocks must be done with the `Store_field` macro (for normal blocks), `Store_double_array_field` macro (for float array values) or `Store_double_flat_field` (for floatarray values and records of floating-point numbers). Other assignments must not use `Store_field`, `Store_double_array_field` nor `Store_double_flat_field`.

`Store_field` (*b*, *n*, *v*) stores the value *v* in the field number *n* of value *b*, which must be a block (i.e. `Is_block`(*b*) must be true).

Example:

```c
CAMLprim value bar (value v1, value v2, value v3)
{
    CAMLparam3 (v1, v2, v3);
    CAMLlocal1 (result);
    result = caml_alloc (3, 0);
    Store_field (result, 0, v1);
    Store_field (result, 1, v2);
```
Serialized functions are attached to the custom blocks to which they apply. Obviously, deserialization functions cannot be attached this way, since the custom block does not exist yet when deserialization begins! Thus, the `struct custom_operations` that contain deserialization functions must be registered with the deserializer in advance, using the `register_custom_operations` function declared in `<caml/custom.h>`. Deserialization proceeds by reading the identifier off the input stream, allocating a custom block of the size specified in the input stream, searching the registered `struct custom_operations` blocks for one with the same identifier, and calling its `deserializes` function to fill the data part of the custom block.

### 22.9.5 Choosing identifiers

Identifiers in `struct custom_operations` must be chosen carefully, since they must identify uniquely the data structure for serialization and deserialization operations. In particular, consider including a version number in the identifier; this way, the format of the data can be changed later, yet backward-compatible deserialization functions can be provided.

Identifiers starting with `_` (an underscore character) are reserved for the OCaml runtime system; do not use them for your custom data. We recommend to use a URL (`http://mymachine.mydomain.com/mylibrary/version-number`) or a Java-style package name (`com.mydomain.mymachine.mylibrary.version-number`) as identifiers, to minimize the risk of identifier collision.

### 22.9.6 Finalized blocks

Custom blocks generalize the finalized blocks that were present in OCaml prior to version 3.00. For backwards compatibility, the format of custom blocks is compatible with that of finalized blocks, and the `caml_alloc_final` function is still available to allocate a custom block with a given finalization function, but default comparison, hashing and serialization functions. (In particular, the finalization function must not access the OCaml runtime.)

`caml_alloc_final(n, f, used, max)` returns a fresh custom block of size *n*+1 words, with finalization function *f*. The first word is reserved for storing the custom operations; the other *n* words are available for your data. The two parameters `used` and `max` are used to control the speed of garbage collection, as described for `caml_alloc_custom`.

## 22.10 Advanced topic: Bigarrays and the OCaml-C interface

This section explains how C stub code that interfaces C or Fortran code with OCaml code can use Bigarrays.

### 22.10.1 Include file

The include file `<caml/bigarray.h>` must be included in the C stub file. It declares the functions, constants and macros discussed below.
```c
Store_field (result, 2, v3);
CAMLreturn (result);
}
```

**Warning:** The first argument of `Store_field` and `Store_double_field` must be a variable declared by `CAMLparam*` or a parameter declared by `CAMLlocal*` to ensure that a garbage collection triggered by the evaluation of the other arguments will not invalidate the first argument after it is computed.

**Use with CAMLlocalN:** Arrays of values declared using `CAMLlocalN` must not be written to using `Store_field`. Use the normal C array syntax instead.

**Rule 4** Global variables containing values must be registered with the garbage collector using the `caml_register_global_root` function, save that global variables and locations that will only ever contain OCaml integers (and never pointers) do not have to be registered.

The same is true for any memory location outside the OCaml heap that contains a value and is not guaranteed to be reachable—for as long as it contains such value—from either another registered global variable or location, local variable declared with `CAMLlocal` or function parameter declared with `CAMLparam`.

Registration of a global variable `v` is achieved by calling `caml_register_global_root(&v)` just before or just after a valid value is stored in `v` for the first time; likewise, registration of an arbitrary location `p` is achieved by calling `caml_register_global_root(p)`.

You must not call any of the OCaml runtime functions or macros between registering and storing the value. Neither must you store anything in the variable `v` (likewise, the location `p`) that is not a valid value.

The registration causes the contents of the variable or memory location to be updated by the garbage collector whenever the value in such variable or location is moved within the OCaml heap. In the presence of threads care must be taken to ensure appropriate synchronisation with the OCaml runtime to avoid a race condition against the garbage collector when reading or writing the value. (See section 22.12.2.)

A registered global variable `v` can be un-registered by calling `caml_remove_global_root(&v)`.

If the contents of the global variable `v` are seldom modified after registration, better performance can be achieved by calling `caml_register_generational_global_root(&v)` to register `v` (after its initialization with a valid value, but before any allocation or call to the GC functions), and `caml_remove_generational_global_root(&v)` to un-register it. In this case, you must not modify the value of `v` directly, but you must use `caml_modify_generational_global_root(&v,x)` to set it to `x`. The garbage collector takes advantage of the guarantee that `v` is not modified between calls to `caml_modify_generational_global_root` to scan it less often. This improves performance if the modifications of `v` happen less often than minor collections.

**Note:** The CAML macros use identifiers (local variables, type identifiers, structure tags) that start with `caml_`. Do not use any identifier starting with `caml_` in your programs.
### 22.10.2 Accessing an OCaml bigarray from C or Fortran

If `v` is a OCaml value representing a Bigarray, the expression `Caml_ba_data_val(v)` returns a pointer to the data part of the array. This pointer is of type `void *` and can be cast to the appropriate C type for the array (e.g. `double []`, `char []` [10], etc).

Various characteristics of the OCaml Bigarray can be consulted from C as follows:

<table><thead><tr><td>C expression</td><td>Returns</td></tr></thead><tbody><tr><td>Caml_ba_array_val(v)->num_dim</td><td>number of dimensions</td></tr><tr><td>Caml_ba_array_val(v)->dim[]</td><td>i-th dimension</td></tr><tr><td>Caml_ba_array_val(v)->flags &amp; BIGARRAY KIND_MASK</td><td>kind of array elements</td></tr></tbody></table>

The kind of array elements is one of the following constants:

<table><thead><tr><td>Constant</td><td>Element kind</td></tr></thead><tbody><tr><td>CAML_BA_FLOAT32</td><td>32-bit single-precision floats</td></tr><tr><td>CAML_BA_FLOAT64</td><td>64-bit double-precision floats</td></tr><tr><td>CAML_BA_SINT8</td><td>8-bit signed integers</td></tr><tr><td>CAML_BA_UUID8</td><td>8-bit unsigned integers</td></tr><tr><td>CAML_BA_SINT16</td><td>16-bit signed integers</td></tr><tr><td>CAML_BA_UUID16</td><td>16-bit unsigned integers</td></tr><tr><td>CAML_BA_INT32</td><td>32-bit signed integers</td></tr><tr><td>CAML_BA_INT64</td><td>64-bit signed integers</td></tr><tr><td>CAML_BA_CAML_INT</td><td>31- or 63-bit signed integers</td></tr><tr><td>CAML_BA_NATIVE_INT</td><td>32- or 64-bit (platform-native) integers</td></tr><tr><td>CAML_BA_COMPLEX32</td><td>32-bit single-precision complex numbers</td></tr><tr><td>CAML_BA_COMPLEX64</td><td>64-bit double-precision complex numbers</td></tr><tr><td>CAML_BA_CHAR</td><td>8-bit characters</td></tr></tbody></table>

**Warning:** `Caml_ba_array_val(v)` must always be dereferenced immediately and not stored anywhere, including local variables. It resolves to a derived pointer: it is not a valid OCaml value but points to a memory region managed by the GC. For this reason this value must not be stored in any memory location that could be live cross a GC.

The following example shows the passing of a two-dimensional Bigarray to a C function and a Fortran function.

```c
extern void my_c_function(double * data, int dimx, int dimy);
extern void my_fortran_function_(double * data, int * dimx, int * dimy);

CAMLprim value camlstub(value bigarray)
{
    int dimx = Caml_ba_array_val(bigarray)->dim[0];
    int dimy = Caml_ba_array_val(bigarray)->dim[1];

    /* C passes scalar parameters by value */
    my_c_function(Caml_ba_data_val(bigarray), dimx, dimy);

    /* Fortran passes all parameters by reference */
    my_fortran_function_(Caml_ba_data_val(bigarray), &dimx, &dimy);
```
### 22.5.2 Low-level interface

We now give the GC rules corresponding to the low-level allocation functions `caml_alloc_small` and `caml_alloc_shr`. You can ignore those rules if you stick to the simplified allocation function `caml_alloc`.

**Rule 5** After a structured block (a block with tag less than `No_scan_tag`) is allocated with the low-level functions, all fields of this block must be filled with well-formed values before the next allocation operation. If the block has been allocated with `caml_alloc_small`, filling is performed by direct assignment to the fields of the block:

```
Field(v, n) = v_n;
```

If the block has been allocated with `caml_alloc_shr`, filling is performed through the `caml_initialize` function:

```
caml_initialize(&Field(v, n), v_n);
```

The next allocation can trigger a garbage collection. The garbage collector assumes that all structured blocks contain well-formed values. Newly created blocks contain random data, which generally do not represent well-formed values.

If you really need to allocate before the fields can receive their final value, first initialize with a constant value (e.g. `Val_unit`), then allocate, then modify the fields with the correct value (see rule 6).

**Rule 6** Direct assignment to a field of a block, as in

```
Field(v, n) = w;
```

is safe only if `v` is a block newly allocated by `caml_alloc_small`; that is, if no allocation took place between the allocation of `v` and the assignment to the field. In all other cases, never assign directly. If the block has just been allocated by `caml_alloc_shr`, use `caml_initialize` to assign a value to a field for the first time:

```
caml_initialize(&Field(v, n), w);
```

Otherwise, you are updating a field that previously contained a well-formed value; then, call the `caml_modify` function:

```
caml_modify(&Field(v, n), w);
```

To illustrate the rules above, here is a C function that builds and returns a list containing the two integers given as parameters. First, we write it using the simplified allocation functions:

```c
value alloc_list_int(int i1, int i2)
{
    CAMLparam0 ();
    CAMLlocal2 (result, r);

    r = caml_alloc(2, 0);          /* Allocate a cons cell */
```
```c
return Val_unit;
}
```

### 22.10.3 Wrapping a C or Fortran array as an OCaml Bigarray

A pointer `p` to an already-allocated C or Fortran array can be wrapped and returned to OCaml as a Bigarray using the `caml_ba_alloc` or `caml_ba_alloc_dirs` functions.

* `caml_ba_alloc(kind | layout, numdimsm, p, dims)`

Return an OCaml Bigarray wrapping the data pointed to by `p`. `kind` is the kind of array elements (one of the `CAML_BA_` kind constants above). `layout` is `CAML_BA_C_LAYOUT` for an array with C layout and `CAML_BA_FORTRAN_LAYOUT` for an array with Fortran layout. `numdimsm` is the number of dimensions in the array. `dims` is an array of `numdimsm` long integers, giving the sizes of the array in each dimension.

* `caml_ba_alloc_dirs(kind | layout, numdimsm, p, (long)dim₁, (long)dim₂, ..., (long)dimnumdimsm)`

Same as `caml_ba_alloc`, but the sizes of the array in each dimension are listed as extra arguments in the function call, rather than being passed as an array.

The following example illustrates how statically-allocated C and Fortran arrays can be made available to OCaml.

```c
extern long my_c_array[100][200];
extern float my_fortran_array_[300][400];

CAMLprim value caml_get_c_array(value unit)
{
    long dims[2];
    dims[0] = 100; dims[1] = 200;
    return caml_ba_alloc(CAML_BA_NATIVE_INT | CAML_BA_C_LAYOUT,
                          2, my_c_array, dims);
}

CAMLprim value caml_get_fortran_array(value unit)
{
    return caml_ba_alloc_dirs(CAML_BA_FLOAT32 | CAML_BA_FORTRAN_LAYOUT,
                                 2, my_fortran_array_, 300L, 400L);
}
```

## 22.11 Advanced topic: cheaper C call

This section describe how to make calling C functions cheaper.

**Note:** This only applies to the native compiler. So whenever you use any of these methods, you have to provide an alternative byte-code stub that ignores all the special annotations.
```c
Store_field(r, 0, Val_int(i2));      /* car = the integer i2 */
Store_field(r, 1, Val_emptylist);    /* cdr = the empty list [] */
result = caml_alloc(2, 0);          /* Allocate the other cons cell */
Store_field(result, 0, Val_int(i1));  /* car = the integer i1 */
Store_field(result, 1, r);           /* cdr = the first cons cell */
CAMLreturn (result);
}
```

Here, the registering of `result` is not strictly needed, because no allocation takes place after it gets its value, but it's easier and safer to simply register all the local variables that have type `value`.

Here is the same function written using the low-level allocation functions. We notice that the `cons cells` are small blocks and can be allocated with `caml_alloc_small`, and filled by direct assignments on their fields.

```c
value alloc_list_int(int i1, int i2)
{
    CAMLparam0 ();
    CAMLlocal2 (result, r);

    r = caml_alloc_small(2, 0);      /* Allocate a cons cell */
    Field(r, 0) = Val_int(i2);        /* car = the integer i2 */
    Field(r, 1) = Val_emptylist;     /* cdr = the empty list [] */
    result = caml_alloc_small(2, 0);  /* Allocate the other cons cell */
    Field(result, 0) = Val_int(i1);    /* car = the integer i1 */
    Field(result, 1) = r;            /* cdr = the first cons cell */
    CAMLreturn (result);
}
```

In the two examples above, the list is built bottom-up. Here is an alternate way, that proceeds top-down. It is less efficient, but illustrates the use of `caml_modify`.

```c
value alloc_list_int(int i1, int i2)
{
    CAMLparam0 ();
    CAMLlocal2 (tail, r);

    r = caml_alloc_small(2, 0);      /* Allocate a cons cell */
    Field(r, 0) = Val_int(i1);        /* car = the integer i1 */
    Field(r, 1) = Val_int(0);         /* A dummy value */
    tail = caml_alloc_small(2, 0);   /* Allocate the other cons cell */
    Field(tail, 0) = Val_int(i2);     /* car = the integer i2 */
    Field(tail, 1) = Val_emptylist;  /* cdr = the empty list [] */
    caml_modify(&Field(r, 1), tail); /* cdr of the result = tail */
    CAMLreturn (r);
}
```

It would be incorrect to perform `Field(r, 1) = tail` directly, because the allocation of `tail` has taken place since `r` was allocated.
### 22.11.1 Passing unboxed values

We said earlier that all OCaml objects are represented by the C type `value`, and one has to use macros such as `Int_val` to decode data from the `value` type. It is however possible to tell the OCaml native-code compiler to do this for us and pass arguments unboxed to the C function. Similarly it is possible to tell OCaml to expect the result unboxed and box it for us.

The motivation is that, by letting `ocamlopt` deal with boxing, it can often decide to suppress it entirely.

For instance let's consider this example:

```c
external foo : float -> float -> float = "foo"

let f a b =
    let len = Array.length a in
    assert (Array.length b = len);
    let res = Array.make len 0. in
    for i = 0 to len - 1 do
        res.(i) <- foo a.(i) b.(i)
    done
```

Float arrays are unboxed in OCaml, however the C function `foo` expect its arguments as boxed floats and returns a boxed float. Hence the OCaml compiler has no choice but to box `a.(i)` and `b.(i)` and unbox the result of `foo`. This results in the allocation of `3 * len` temporary float values.

Now if we annotate the arguments and result with `@unboxed]`, the native-code compiler will be able to avoid all these allocations:

```c
external foo
    : (float @unboxed])
-> (float @unboxed])
-> (float @unboxed])
= "foo_bytes" "foo"
```

In this case the C functions must look like:

```c
CAMLprim double foo(double a, double b)
{
    ...
}

CAMLprim value foo_bytes(value a, value b)
{
    return caml_copy_double(foo(Double_val(a), Double_val(b)))
}
```

For convenience, when all arguments and the result are annotated with `@unboxed]`, it is possible to put the attribute only once on the declaration itself. So we can also write instead:
### 22.5.3 Pending actions and asynchronous exceptions

Since 4.10, allocation functions are guaranteed not to run any OCaml code, including finalisers, signal handlers and other threads running on the same domain. Instead, their execution is delayed to a later safe point.

The function `caml_process_pendingActions` from `<caml/signals.h>` executes any pending signal handlers and finalisers, Memprof callbacks, preemptive sylthread switching, and requested minor and major garbage collections. In particular, it can raise asynchronous exceptions and cause mutations on the OCaml heap from the same domain. It is recommended to call it regularly at safe points inside long-running non-blocking C code.

The function `caml_process_pendingActions_res` returns the exception instead of raising it directly into OCaml code. This is represented by a different C type, `caml_result` rather than `value`. The result can be tested using `caml_result_is_exception`, followed by some cleanup logic, and finally `caml_get_value_or Rais e` which returns the value (here just a unit value, ignored) or raises the exception.

```c
CAMLlocalresult(res);
...
res = caml_process_pendingActions_res();
if (caml_result_is_exception(res)) {
    ...cleanup...
    (void)caml_get_value_or Rais e(res);
}
```

For more details on `caml_result`, see section 22.7.2.

## 22.6 A complete example

This section outlines how the functions from the Unix `curses` library can be made available to OCaml programs. First of all, here is the interface `curses.ml` that declares the `curses` primitives and data types:

```c
(* File curses.ml -- declaration of primitives and data types *)
type window              (* The type "window" remains abstract *)
external initscr: unit -> window = "caml_curses_initscr"
external endwin: unit -> unit = "caml_curses_endwin"
external refresh: unit -> unit = "caml_curses_refresh"
external wrefresh : window -> unit = "caml_curses_wrefresh"
external newwin: int -> int -> int -> int -> window = "caml_curses_newwin"
external addch: char -> unit = "caml_curses_addch"
external mvwaddch: window -> int -> int -> char -> unit = "caml_curses_mvwaddch"
external addstr: string -> unit = "caml_curses_addstr"
external mvwaddstr: window -> int -> int -> string -> unit
    = "caml_curses_mvwaddstr"
(* lots more omitted *)
```

To compile this interface:
external foo : float -> float -> float = "foo_byte" "foo" [@@unboxed]

The following table summarize what OCaml types can be unboxed, and what C types should be used in correspondence:

<table><thead><tr><td>OCaml type</td><td>C type</td></tr></thead><tbody><tr><td>float</td><td>double</td></tr><tr><td>int32</td><td>int32_t</td></tr><tr><td>int64</td><td>int64_t</td></tr><tr><td>nativeint</td><td>intnat</td></tr></tbody></table>

Similarly, it is possible to pass untagged OCaml integers between OCaml and C. This is done by annotating the arguments and/or result with `@@untagged`:

external f : string -> (int [@@untagged]) = "f_byte" "f"

The corresponding C type must be `intnat`.

**Note:** Do not use the C `int` type in correspondence with `(int [@@untagged])`. This is because they often differ in size.

### 22.11.2 Direct C call

In order to be able to run the garbage collector in the middle of a C function, the OCaml native-code compiler generates some bookkeeping code around C calls. Technically it wraps every C call with the C function `caml_c_call` which is part of the OCaml runtime.

For small functions that are called repeatedly, this indirection can have a big impact on performances. However this is not needed if we know that the C function doesn't allocate, doesn't raise exceptions, and doesn't release the domain lock (see section 22.12.2). We can instruct the OCaml native-code compiler of this fact by annotating the external declaration with the attribute `@@noalloc`:

external bar : int -> int -> int = "foo" [@@noalloc]

In this case calling `bar` from OCaml is as cheap as calling any other OCaml function, except for the fact that the OCaml compiler can't inline C functions...

### 22.11.3 Example: calling C library functions without indirection

Using these attributes, it is possible to call C library functions with no indirection. For instance many math functions are defined this way in the OCaml standard library:

external sqrt : float -> float = "caml sqrt float" "sqrt" [@@unboxed] [@@noalloc] (** Square root. *)

external exp : float -> float = "caml_exp float" "exp" [@@unboxed] [@@noalloc] (** Exponential. *)

external log : float -> float = "caml_log float" "log" [@@unboxed] [@@noalloc] (** Natural logarithm. *)
ocamlc -c curses.ml

To implement these functions, we just have to provide the stub code; the core functions are already
implemented in the curses library. The stub code file, curses_stubs.c, looks like this:

/* File curses_stubs.c -- stub code for curses */
#include <curses.h>
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/alloc.h>
#include <caml/custom.h>

/* Encapsulation of opaque window handles (of type WINDOW *)
as OCaml custom blocks. */

static struct custom_operations curses_windows = {
    "fr.inria.caml.curses_windows",
    custom_finalize_default,
    custom_compare_default,
    custom_hash_default,
    custom_serialize_default,
    custom_des工業ize_default,
    custom_compare_ext_default,
    custom_fixed_length_default
};

/* Accessing the WINDOW * part of an OCaml custom block */
#define Window_val(v) (*((WINDOW **) Data_custom_val(v)))

/* Allocating an OCaml custom block to hold the given WINDOW * */
static value alloc_windows(WINDOW * w)

{
    value v = caml_alloc_custom(&curses_windows_ops, sizeof(WINDOW *), 0, 1);
    Window_val(v) = w;
    return v;
}

CAMLprim value caml_curses_initscr(value unit)

{
    CAMLparam1 (unit);
    CAMLreturn (alloc_windows(initscr));
}

CAMLprim value caml_curses_endwin(value unit)

{
    CAMLparam1 (unit);
## 22.12 Advanced topic: multithreading

Using multiple threads (shared-memory concurrency) in a mixed OCaml/C application requires special precautions, which are described in this section.

### 22.12.1 Registering threads created from C

Callbacks from C to OCaml are possible only if the calling thread is known to the OCaml run-time system. Threads created from OCaml (through the `Thread.create` function of the system threads library) are automatically known to the run-time system. If the application creates additional threads from C and wishes to callback into OCaml code from these threads, it must first register them with the run-time system. The following functions are declared in the include file <caml/threads.h>.

* `caml_c_thread_register()` registers the calling thread with the OCaml run-time system. Returns 1 on success, 0 on error. Registering an already-registered thread does nothing and returns 0.

* `caml_c_thread unregister()` must be called before the thread terminates, to unregister it from the OCaml run-time system. Returns 1 on success, 0 on error. If the calling thread was not previously registered, does nothing and returns 0.

### 22.12.2 Parallel execution of long-running C code with systhreads

Domains are the unit of parallelism for OCaml programs. When using the systhreads library, multiple threads might be attached to the same domain. However, at any time, at most one of those thread can be executing OCaml code or C code that uses the OCaml run-time system by domain. Technically, this is enforced by a “domain lock” that any thread must hold while executing such code within a domain.

When OCaml calls the C code implementing a primitive, the domain lock is held, therefore the C code has full access to the facilities of the run-time system. However, no other thread in the same domain can execute OCaml code concurrently with the C code of the primitive. See also chapter 9.6 for the behaviour with multiple domains.

If a C primitive runs for a long time or performs potentially blocking input-output operations, it can explicitly release the domain lock, enabling other OCaml threads in the same domain to run concurrently with its operations. The C code must re-acquire the domain lock before returning to OCaml. This is achieved with the following functions, declared in the include file <caml/threads.h>.

* `caml_release_runtime_system()` The calling thread releases the domain lock and other OCaml resources, enabling other threads to run OCaml code in parallel with the execution of the calling thread.

* `caml_acquire_runtime_system()` The calling thread re-acquires the domain lock and other OCaml resources. It may block until no other thread in the same domain uses the OCaml run-time system.

These functions poll for pending signals by calling asynchronous callbacks (section 22.5.3) before releasing and after acquiring the lock. They can therefore execute arbitrary OCaml code including raising an asynchronous exception.
endwin();
CAMLreturn (Val_unit);
}

CAMLprim value caml_curses_refresh(value unit)
{
    CAMLparam1 (unit);
    refresh();
    CAMLreturn (Val_unit);
}

CAMLprim value caml_curses_wrefresh(value win)
{
    CAMLparam1 (win);
    wrefresh，请问 win 是什么类型？
    CAMLreturn (Val_unit);
}

CAMLprim value caml_curses_newwin(value nlines, value ncols, value x0, value y0)
{
    CAMLparam4 (nlines, ncols, x0, y0);
    CAMLreturn (alloc_windows(newwin(Int_val(nlines), Int_val.ncols),
                             Int_val(x0), Int_val(y0)));
}

CAMLprim value caml_curses_addch(value c)
{
    CAMLparam1 (c);
    addch(Int_val(c)); /* Characters are encoded like integers */
    CAMLreturn (Val_unit);
}

CAMLprim value caml_curses_mvwaddch(value win, value x, value y, value c)
{
    CAMLparam4 (win, x, y, c);
    mvwaddch，请问 win, x, y, c 是什么类型？
    CAMLreturn (Val_unit);
}

CAMLprim value caml_curses_addstr(value s)
{
    CAMLparam1 (s);
    addstr(String_val(s));
    CAMLreturn (Val_unit);
}
After `caml_release_runtime_system()` was called and until `caml_acquire_runtime_system()` is called, the C code must not access any OCaml data, nor call any function of the run-time system, nor call back into OCaml code. Consequently, arguments provided by OCaml to the C primitive must be copied into C data structures before calling `caml_release_runtime_system()`, and results to be returned to OCaml must be encoded as OCaml values after `caml_acquire_runtime_system()` returns.

Example: the following C primitive invokes `gethostbyname` to find the IP address of a host name. The `gethostbyname` function can block for a long time, so we choose to release the OCaml run-time system while it is running.

```c
CAMLprim stub_gethostbyname(value vname)
{
    CAMLparam1 (vname);
    CAMLlocal1 (vres);
    struct hostent *h;
    char *name;

    /* Copy the string argument to a C string, allocated outside the
     OCaml heap. */
    name = caml_stat_strdup(String_val(vname));
    /* Release the OCaml run-time system */
    caml_release_runtime_system();
    /* Resolve the name */
    h = gethostbyname(name);
    /* Free the copy of the string, which we might as well do before
     acquiring the runtime system to benefit from parallelism. */
    caml_stat_free(name);
    /* Re-acquire the OCaml run-time system */
    caml_acquire_runtime_system();
    /* Encode the relevant fields of h as the OCaml value vres */
    ... /* Omitted */
    /* Return to OCaml */
    CAMLreturn (vres);
}
```

The macro `Caml_state` evaluates to the domain state variable, and checks in debug mode that the domain lock is held. Such a check is also placed in normal mode at key entry points of the C API; this is why calling some of the runtime functions and macros without correctly owning the domain lock can result in a fatal error: `no domain lock held`. The variant `Caml_state_opt` does not perform any check but evaluates to `NULL` when the domain lock is not held. This lets you determine whether a thread belonging to a domain currently holds its domain lock, for various purposes.

Callbacks from C to OCaml must be performed while holding the domain lock to the OCaml run-time system. This is naturally the case if the callback is performed by a C primitive that did not release the run-time system. If the C primitive released the run-time system previously, or the callback is performed from other C code that was not invoked from OCaml (e.g. an event loop in a
```c
CAMLprim value caml_curses_mvwaddstr(value win, value x, value y, value s)
{
    CAMLparam4 (win, x, y, s);
    mvwaddstr，请 window_val win, int val(x), int val(y), string val(s));
    CAMLreturn (Val_unit);
}
```

```c
/* This goes on for pages. */
```

The file `curses_stubs.c` can be compiled with:

```bash
cc -c -I`ocamlc -where` curses_stubs.c
```

or, even simpler,

```bash
ocamlc -c curses_stubs.c
```

(When passed a `.c` file, the `ocamlc` command simply calls the C compiler on that file, with the right `-I` option.)

Now, here is a sample OCaml program `prog.ml` that uses the `curses` module:

```ml
(* File prog.ml -- main program using curses *)
open Curses;;
let main_windows = initscr () in
let small_windows = newwin 10 5 20 10 in
    mvwaddstr main_windows 10 2 "Hello";
    mvwaddstr small_windows 4 3 "world";
    refresh();
    Unix.sleep 5;
endwin()
```

To compile and link this program, run:

```bash
ocamlc -custom -o prog unix.cma curses.cmo prog.ml curses_stubs.o -cclib -lcurses
```

(On some machines, you may need to put `-cclib -lcurses -cclib -ltermcap` or `-cclib -ltermcap` instead of `-cclib -lcurses`.)

## 22.7 Advanced topic: callbacks from C to OCaml

So far, we have described how to call C functions from OCaml. In this section, we show how C functions can call OCaml functions, either as callbacks (OCaml calls C which calls OCaml), or with the main program written in C.
GUI application), the run-time system must be acquired before the callback and released after:

```c
 caml_acquire_runtime_system();
 /* Resolve OCaml function vfun to be invoked */
 /* Build OCaml argument varg to the callback */
 vres = callback(vfun, varg);
 /* Copy relevant parts of result vres to C data structures */
 caml_release_runtime_system();
```

Note: the `acquire` and `release` functions described above were introduced in OCaml 3.12. Older code uses the following historical names, declared in `<caml/signals.h>`:

* `caml_enter_blocking Brewster` as an alias for `caml_release_runtime_system`

* `camlLeave blocking Brewster` as an alias for `caml_acquire_runtime_system`

Intuition: a “blocking section” is a piece of C code that does not use the OCaml run-time system, typically a blocking input/output operation.

## 22.13 Advanced topic: interfacing with Windows Unicode APIs

This section contains some general guidelines for writing C stubs that use Windows Unicode APIs. The OCaml system under Windows can be configured at build time in one of two modes:

* **legacy mode:** All path names, environment variables, command line arguments, etc. on the OCaml side are assumed to be encoded using the current 8-bit code page of the system.

* **Unicode mode:** All path names, environment variables, command line arguments, etc. on the OCaml side are assumed to be encoded using UTF-8.

In what follows, we say that a string has the *OCaml encoding* if it is encoded in UTF-8 when in Unicode mode, in the current code page in legacy mode, or is an arbitrary string under Unix. A string has the *platform encoding* if it is encoded in UTF-16 under Windows or is an arbitrary string under Unix.

From the point of view of the writer of C stubs, the challenges of interacting with Windows Unicode APIs are twofold:

* The Windows API uses the UTF-16 encoding to support Unicode. The runtime system performs the necessary conversions so that the OCaml programmer only needs to deal with the OCaml encoding. C stubs that call Windows Unicode APIs need to use specific runtime functions to perform the necessary conversions in a compatible way.

* When writing stubs that need to be compiled under both Windows and Unix, the stubs need to be written in a way that allow the necessary conversions under Windows but that also work under Unix, where typically nothing particular needs to be done to support Unicode.
### 22.7.1 Applying OCaml closures from C

C functions can apply OCaml function values (closures) to OCaml values. The following functions are provided to perform the applications:

* `caml_callback(f, a)` applies the functional value `f` to the value `a` and returns the value returned by `f`.

* `caml_callback2(f, a, b)` applies the functional value `f` (which is assumed to be a curried OCaml function with two arguments) to `a` and `b`.

* `caml_callback3(f, a, b, c)` applies the functional value `f` (a curried OCaml function with three arguments) to `a`, `b` and `c`.

* `caml_callbackN(f, n, args)` applies the functional value `f` to the `n` arguments contained in the C array of values `args`.

If the function `f` does not return, but raises an exception that escapes the scope of the application, then this exception is propagated to the next enclosing OCaml code, skipping over the C code. That is, if an OCaml function `f` calls a C function `g` that calls back an OCaml function `h` that raises a stray exception, then the execution of `g` is interrupted and the exception is propagated back into `f`.

### 22.7.2 `caml_result`: resource cleanup on OCaml exceptions

If the OCaml function called with `caml_callback` (or `caml_process_pendingActions` as mentioned in Section 22.5.3) raises an exception, the C caller will be interrupted immediately to return to the closest OCaml exception handler. This is often the wrong behavior if the C caller needs to run some resource cleanup logic to terminate safely.

The OCaml FFI provides an alternative API to call OCaml code from C that returns a value of type `caml_result` instead of `value`. A C value of type `caml_result` is either an OCaml value returned correctly by the OCaml function, or an OCaml exception raised by the OCaml function. The C caller can run any cleanup logic before re-raising the exception (if any) or continuing the computation.

`caml_result` values can be manipulated using the following functions and macros:

* `value caml_get_value_or Rais e (caml_result res)` (in `fail.h`) returns the value contained in `res` or reraises the exception it contains. In particular, `(void)caml_get_value_or Rais e(res)` can be used to ignore an OCaml result of type `unit`, yet propagate exceptions to the caller.

* `Result_value(value v)` (in `mlvalues.h`) is the result that represents returning the value `v`.

* `Result_exception(value exn)` (in `mlvalues.h`) is the result that represents raising the exception `exn`.

* `int caml_result_is_exception(caml_result res)` (in `mlvalues.h`) is true if `res` represents an exception.
The native C character type under Windows is `WCHAR`, two bytes wide, while under Unix it is `char`, one byte wide. A type `char_os` is defined in `<caml/misc.h>` that stands for the concrete C character type of each platform. Strings in the platform encoding are of type `char_os *`.

The following functions are exposed to help write compatible C stubs. To use them, you need to include both `<caml/misc.h>` and `<caml/osdeps.h>`.

* `char_os* caml_stat_strdup_to_os(const char *)` copies the argument while translating from OCaml encoding to the platform encoding. This function is typically used to convert the `char *` underlying an OCaml string before passing it to an operating system API that takes a Unicode argument. Under Unix, it is equivalent to `caml_stat_strdup`.

**Note:** For maximum backwards compatibility in Unicode mode, if the argument is not a valid UTF-8 string, this function will fall back to assuming that it is encoded in the current code page.

* `char* caml_stat_strdup_of_os(const char_os *)` copies the argument while translating from the platform encoding to the OCaml encoding. It is the inverse of `caml_stat_strdup_to_os`. This function is typically used to convert a string obtained from the operating system before passing it on to OCaml code. Under Unix, it is equivalent to `caml_stat_strdup`.

* `value caml_copy_string_of_os(char_os *)` allocates an OCaml string with contents equal to the argument string converted to the OCaml encoding. This function is essentially equivalent to `caml_stat_strdup_of_os` followed by `caml_copy_string`, except that it avoids the allocation of the intermediate string returned by `caml_stat_strdup_of_os`. Under Unix, it is equivalent to `caml_copy_string`.

**Note:** The strings returned by `caml_stat_strdup_to_os` and `caml_stat_strdup_of_os` are allocated using `caml_stat_alloc`, so they need to be deallocated using `caml_stat_free` when they are no longer needed.

**Example** We want to bind the function `getenv` in a way that works both under Unix and Windows. Under Unix this function has the prototype:

```c
char *getenv(const char *);
```

While the Unicode version under Windows has the prototype:

```c
WCHAR *wgetenv(const WCHAR *);
```

In terms of `char_os`, both functions take an argument of type `char_os *` and return a result of the same type. We begin by choosing the right implementation of the function to bind:

```c
#ifdef _WIN32
#define getenv_os _wgetenv
#else
#define getenv_os getenv
#endif
```
* The macro `CAMLlocalresult(foo)` (in `memory.h`) is the `caml_result` counterpart of `CAMLlocal1`: it declares a local variable of type `caml_result`, whose content is tracked by the OCaml GC. Just like `CAMLlocal1`, it can only be used between a `CAMLparam` macro and `CAMLreturn` or `CAMLreturnT` macros. There is no equivalent of `CAMLlocal2`, `CAMLlocal3`, etc., but the macro can be used several times.

For convenience, `Result_unit` is defined as `Result_value(Val_unit)`.

By convention, result-returning C functions have their name suffixed with `_res`, for example `caml_callback2_res` and `caml_process_pending_actions_res`.

Some examples:

```c
#include <caml/mlvalues.h> // for the caml_result type, caml_result_is_exception
#include <caml/memory.h>  // CAMLlocalresult
#include <caml/callback.h> // caml_callback_res
#include <caml/fail.h>    // caml_get_value_or RaisE
#include <caml/alloc.h>  // caml_alloc_2
```

```c
/* This function calls an OCaml callback,
   and returns the value or reraises the exception. */
value logging_callback(value f, value arg) {
    CAMLparam2(f, arg);
    CAMLlocalresult(res);
    printf("Start callback.\n");
    res = caml_callback_res(f, arg);
    printf("End callback.\n");
    CAMLreturn (caml_get_value_or RaisE(res));
}
```

```c
/* This function assumes that the callback returns
   a 'unit' value and ignores it -- or reraises
   its exception. It must be called by C, as it
   does not return a value, but the caller cannot
   handle exceptions as they are raised directly. */
void logging_unit_callback(value f, value arg) {
    CAMLparam2(f, arg);
    CAMLlocalresult(res);
    printf("Start unit callback.\n");
    res = caml_callback_res(f, arg);
    printf("End callback.\n");
    (void)caml_get_value_or RaisE(res);
    CAMLreturn0;
}
```

```c
/* This function calls a callback on two arguments in turn,
   and returns the pair of values;
   it does not reraise exceptions, but returns a caml_result instead, letting
```
The rest of the binding is the same for both platforms:

#include <caml/mlvalues.h>

#include <caml/misc.h>

#include <caml/alloc.h>

#include <caml/fail.h>

#include <caml/osdeps.h>

#include <stdlib.h>

CAMLprim value stub_getenv(value var_name)

{

CAMLparam1(var_name);

CAMLlocal1(var_value);

char_os *var_name_os, *var_value_os;

var_name_os = caml_stat_strdup_to_os(String_val(var_name));

var_value_os = getenv_os(var_name_os);

caml_stat_free(var_name_os);

if (var_value_os == NULL)

camlOMPNOT_FOUND();

var_value = caml_copy_string_of_os(var_value_os);

CAMLreturn(var_value);

22.14 Building mixed C/OCaml libraries: ocamlmklib

The ocamlmklib command facilitates the construction of libraries containing both OCaml code and C code, and usable both in static linking and dynamic linking modes. This command is available under Windows since Objective Caml 3.11 and under other operating systems since Objective Caml 3.03.

The ocamlmklib command takes three kinds of arguments:

• OCaml source files and object files ( .cmo , .cmx , .ml ) comprising the OCaml part of the library;

• C object files ( .o , .a , respectively, .obj , .lib ) comprising the C part of the library;

• Support libraries for the C part ( -lib ).

It generates the following outputs:

• An OCaml bytecode library .cma incorporating the .cmo and .ml OCaml files given as arguments, and automatically referencing the C library generated with the C object files.
```c
        its own C caller perform its own cleanup. */
caml_result two_callback_res(value f, value arg1, value arg2) {
    CAMLparam3(f, arg1, arg2);
    CAMLlocalresult(res);
    CAMLlocal3(v1, v2, pair);

    res = caml_callback_res(f, arg1);
    // early exit on exception
    if (caml_result_is_exception(res))
        CAMLreturnT(caml_result, res);
    v1 = caml_get_value_or Rraise(res);

    res = caml_callback_res(f, arg2);
    if (caml_result_is_exception(res))
        CAMLreturnT(caml_result, res);
    v2 = caml_get_value_or Rraise(res);

    // build the pair of values, and
    // wrap it in a caml_result
    pair = caml_alloc_2(0, v1, v2);
    res = Result_value(pair);
    CAMLreturnT(caml_result, res);
}
```

**Compatibility:** The `caml_result` type is available since OCaml 5.3. Older versions of OCaml use an unsafe concept of encoded exceptions (suffix _exn, operations `Is_exception_result` and `Extract_exception`) which are of type `value` but are not valid OCaml values and can crash the GC if they are not extracted immediately by the caller. We strongly recommend using `caml_result` instead, to have a clear separation between valid values and reified exceptions at distinct C types, but the older approach remains available for backwards-compatibility.

### 22.7.3 Obtaining or registering OCaml closures for use in C functions

There are two ways to obtain OCaml function values (closures) to be passed to the `callback` functions described above. One way is to pass the OCaml function as an argument to a primitive function. For example, if the OCaml code contains the declaration

```c
external apply : ('a -> 'b) -> 'a -> 'b = "caml_apply"
```

the corresponding C stub can be written as follows:

```c
CAMLprim value caml_apply(value vf, value vx)
{
    CAMLparam2(vf, vx);
    CAMLlocal1(vy);
    vy = caml_callback(vf, vx);
```
* An OCaml native-code library `.cmxa` incorporating the `.cmx` and `.ml` OCaml files given as arguments, and automatically referencing the C library generated with the C object files.

* If dynamic linking is supported on the target platform, a `.so` (respectively, `.dll`) shared library built from the C object files given as arguments, and automatically referencing the support libraries.

* A C static library `.a` (respectively, `.lib`) built from the C object files.

In addition, the following options are recognized:

**-cclib, -ccopt, -I, -linkall**

These options are passed as is to `ocamlc` or `ocamlopt`. See the documentation of these commands.

**-rpath, -R, -Wl, -rpath, -Wl, -R**

These options are passed as is to the C compiler. Refer to the documentation of the C compiler.

**-custom**

Force the construction of a statically linked library only, even if dynamic linking is supported.

**-failsafe**

Fall back to building a statically linked library if a problem occurs while building the shared library (e.g. some of the support libraries are not available as shared libraries).

**-Ldir**

Add `dir` to the search path for support libraries (`-llib`).

**-ocamlc cmd**

Use `cmd` instead of `ocamlc` to call the bytecode compiler.

**-ocamlopt cmd**

Use `cmd` instead of `ocamlopt` to call the native-code compiler.

**-o output**

Set the name of the generated OCaml library. `ocamlmklib` will generate `output.cma` and/or `output.cmxa`. If not specified, defaults to `a`.

**-oc outputc**

Set the name of the generated C library. `ocamlmklib` will generate `liboutputc.so` (if shared libraries are supported) and `liboutputc.a`. If not specified, defaults to the output name given with `-o`.

On native Windows, the following environment variable is also consulted:

**OCAML_FLEXLINK**

Alternative executable to use instead of the configured value. Primarily used for bootstrapping.
```c
CAMLreturn(vy);
}
```

Another possibility is to use the registration mechanism provided by OCaml. This registration mechanism enables OCaml code to register OCaml functions under some global name, and C code to retrieve the corresponding closure by this global name.

On the OCaml side, registration is performed by evaluating `Callback.register n v`. Here, *n* is the global name (an arbitrary string) and *v* the OCaml value. For instance:

```c
let f x = print_string "f is applied to "; print_int x; print_newline()
let _ = Callback.register "test function" f
```

On the C side, a pointer to the value registered under name *n* is obtained by calling `caml_named_value(n)`. The returned pointer must then be dereferenced to recover the actual OCaml value. If no value is registered under the name *n*, the null pointer is returned. For example, here is a C wrapper that calls the OCaml function *f* above:

```c
void call_caml_f(int arg)
{
    caml_callback(*caml_named_value("test function"), Val_int(arg));
}
```

The pointer returned by `caml_named_value` is constant and can safely be cached in a C variable to avoid repeated name lookups. The value pointed to cannot be changed from C. However, it might change during garbage collection, so must always be recomputed at the point of use. Here is a more efficient variant of `call_caml_f` above that calls `caml_named_value` only once:

```c
void call_caml_f(int arg)
{
    static const value * closure_f = NULL;
    if (closure_f == NULL) {
        /* First time around, look up by name */
        closure_f = caml_named_value("test function");
    }
    caml_callback(*closure_f, Val_int(arg));
}
```

### 22.7.4 Registering OCaml exceptions for use in C functions

The registration mechanism described above can also be used to communicate exception constructors from OCaml to C. The OCaml code registers the exception constructor by evaluating `Callback.register_exception n exn`, where *n* is an arbitrary name and *exn* is an exception value with the exception constructor to register. For example:

```c
exception Error of string
let _ = Callback.register_exception "test exception" (Error "any string")
```
**Example** Consider an OCaml interface to the standard libz C library for reading and writing compressed files. Assume this library resides in `/usr/local/zlib`. This interface is composed of an OCaml part `zip.cmo/zip.cmx` and a C part `zipstubs.o` containing the stub code around the libz entry points. The following command builds the OCaml libraries `zip.cma` and `zip.cmxa`, as well as the companion C libraries `dllzip.so` and `libzip.a`:

```
ocamlmklib -o zip zip.cmo zip.cmx zipstubs.o -lz -L/usr/local/zlib
```

If shared libraries are supported, this performs the following commands:

```
ocamlc -a -o zip.cma zip.cmo -dllib -lzip \
       -cclib -lzip -cclib -lz -ccopt -L/usr/local/zlib
ocamlopt -a -o zip.cmxa zip.cmx -cclib -lzip \
           -cclib -lzip -cclib -lz -ccopt -L/usr/local/zlib
gcc -shared -o dllzip.so zipstubs.o -lz -L/usr/local/zlib
ar rc libzip.a zipstubs.o
```

Note: This example is on a Unix system. The exact command lines may be different on other systems.

If shared libraries are not supported, the following commands are performed instead:

```
ocamlc -a -custom -o zip.cma zip.cmo -cclib -lzip \
       -cclib -lz -ccopt -L/usr/local/zlib
ocamlopt -a -o zip.cmxa zip.cmx -lzip \
           -cclib -lz -ccopt -L/usr/local/zlib
ar rc libzip.a zipstubs.o
```

Instead of building simultaneously the bytecode library, the native-code library and the C libraries, `ocamlmklib` can be called three times to build each separately. Thus,

```
ocamlmklib -o zip zip.cmo -lz -L/usr/local/zlib
```

builds the bytecode library `zip.cma`, and

```
ocamlmklib -o zip zip.cmx -lz -L/usr/local/zlib
```

builds the native-code library `zip.cmxa`, and

```
ocamlmklib -o zip zipstubs.o -lz -L/usr/local/zlib
```

builds the C libraries `dllzip.so` and `libzip.a`. Notice that the support libraries (`-lz`) and the corresponding options (`-L/usr/local/zlib`) must be given on all three invocations of `ocamlmklib`, because they are needed at different times depending on whether shared libraries are supported.

## 22.15 Cautionary words: the internal runtime API

Not all headers available in the `caml/` directory were described in previous sections. All those unmentioned headers are part of the internal runtime API, for which there is no stability guarantee. If you really need access to this internal runtime API, this section provides some guidelines that may help you to write code that might not break on every new version of OCaml.
The C code can then recover the exception constructor using `caml_named_value` and pass it as first argument to the functions `raise, `raise_with_argv`, and `raise_with_string` (described in section 22.4.7) to actually raise the exception. For example, here is a C function that raises the `Error` exception with the given argument:

```c
void raise_error(char * msg)
{
    camlóg_raise_with_string(&caml_named_value("test exception"), msg);
}
```

### 22.7.5 Main program in C

In normal operation, a mixed OCaml/C program starts by executing the OCaml initialization code, which then may proceed to call C functions. We say that the main program is the OCaml code. In some applications, it is desirable that the C code plays the role of the main program, calling OCaml functions when needed. This can be achieved as follows:

* The C part of the program must provide a `main` function, which will override the default `main` function provided by the OCaml runtime system. Execution will start in the user-defined `main` function just like for a regular C program.

* At some point, the C code must call `caml_main(argv)` to initialize the OCaml code. The `argv` argument is a C array of strings (type `char **`), terminated with a `NULL` pointer, which represents the command-line arguments, as passed as second argument to `main`. The OCaml array `Sys.argv` will be initialized from this parameter. For the bytecode compiler, `argv[0]` and `argv[1]` are also consulted to find the file containing the bytecode.

* The call to `caml_main` initializes the OCaml runtime system, loads the bytecode (in the case of the bytecode compiler), and executes the initialization code of the OCaml program. Typically, this initialization code registers callback functions using `Callback.register`. Once the OCaml initialization code is complete, control returns to the C code that called `caml_main`.

* The C code can then invoke OCaml functions using the callback mechanism (see section 22.7.1).

### 22.7.6 Embedding the OCaml code in the C code

The bytecode compiler in custom runtime mode (`ocamlc -custom`) normally appends the bytecode to the executable file containing the custom runtime. This has two consequences. First, the final linking step must be performed by `ocamlc`. Second, the OCaml runtime library must be able to find the name of the executable file from the command-line arguments. When using `caml_main(argv)` as in section 22.7.5, this means that `argv[0]` or `argv[1]` must contain the executable file name.

An alternative is to embed the bytecode in the C code. The `-output-obj` and `-output-complete-obj` options to `ocamlc` are provided for this purpose. They cause the `ocamlc` compiler to output a C object file (`.o` file, `.obj` under Windows) containing the bytecode for the OCaml part of the program, as well as a `caml_startup` function. The C object file produced by `ocamlc -output-complete-obj` also contains the runtime and autolink libraries. The C object file produced by `ocamlc -output-obj` or `ocamlc -output-complete-obj` can then be linked with C code using the standard C compiler, or stored in a C library.
**Note** Programmers which come to rely on the internal API for a use-case which they find realistic and useful are encouraged to open a request for improvement on the bug tracker.

## 22.15.1 Internal variables and CAML_INTERALS

Since OCaml 4.04, it is possible to get access to every part of the internal runtime API by defining the `CAML_INTERALS` macro before loading caml header files. If this macro is not defined, parts of the internal runtime API are hidden.

If you are using internal C variables, do not redefine them by hand. You should import those variables by including the corresponding header files. The representation of those variables has already changed once in OCaml 4.10, and is still under evolution. If your code relies on such internal and brittle properties, it will be broken at some point in time.

For instance, rather than redefining `caml_young_limit`:

```c
extern int caml_young_limit;
```

which breaks in OCaml ≥ 4.10, you should include the `minor_gc` header:

```c
#include <caml/minor_gc.h>
```

## 22.15.2 OCaml version macros

Finally, if including the right headers is not enough, or if you need to support version older than OCaml 4.04, the header file `caml/version.h` should help you to define your own compatibility layer. This file provides few macros defining the current OCaml version. In particular, the `OCAML_VERSION` macro describes the current version, its format is `MmmPP`. For example, if you need some specific handling for versions older than 4.10.0, you could write

```c
#include <caml/version.h>
#if OCAML_VERSION >= 41000
...
#else
...
#endif
```
The `caml_startup` function must be called from the main C program in order to initialize the OCaml runtime and execute the OCaml initialization code. Just like `caml_main`, it takes one `argv` parameter containing the command-line parameters. Unlike `caml_main`, this `argv` parameter is used only to initialize `Sys.argv`, but not for finding the name of the executable file.

The `caml_startup` function calls the uncaught exception handler (or enters the debugger, if running under ocamldebug) if an exception escapes from a top-level module initialiser. Such exceptions may be caught in the C code by instead using the `caml_startup_exn` function and testing the result using `Is_exception_result` (followed by `Extract_exception` if appropriate).

The `-output-obj` and `-output-complete-obj` options can also be used to obtain the C source file. More interestingly, these options can also produce directly a shared library (`.so` file, `.dll` under Windows) that contains the OCaml code, the OCaml runtime system and any other static C code given to `ocamlc` (`.o`, `.a`, respectively, `.obj`, `.lib`). This use of `-output-obj` and `-output-complete-obj` is very similar to a normal linking step, but instead of producing a main program that automatically runs the OCaml code, it produces a shared library that can run the OCaml code on demand. The three possible behaviors of `-output-obj` and `-output-complete-obj` (to produce a C source code `.c`, a C object file `.o`, a shared library `.so`), are selected according to the extension of the resulting file (given with `-o`).

The native-code compiler `ocamlopt` also supports the `-output-obj` and `-output-complete-obj` options, causing it to output a C object file or a shared library containing the native code for all OCaml modules on the command-line, as well as the OCaml startup code. Initialization is performed by calling `caml_startup` (or `caml_startup_exn`) as in the case of the bytecode compiler. The file produced by `ocamlopt -output-complete-obj` also contains the runtime and autolink libraries.

For the final linking phase, in addition to the object file produced by `-output-obj`, you will have to provide the OCaml runtime library (`libcamlrun.a` for bytecode, `libasmrun.a` for native-code), as well as all C libraries that are required by the OCaml libraries used. For instance, assume the OCaml part of your program uses the Unix library. With `ocamlc`, you should do:

```
ocamlc -output-obj -o camlcode.o unix.cma other .cmo and .cma files
cc -o myprog C objects and libraries \
camlcode.o -L`ocamlc -where` -lunix -lcamlrun
```

With `ocamlopt`, you should do:

```
ocamlopt -output-obj -o camlcode.o unix.cmxa other .cmx and .cmxa files
cc -o myprog C objects and libraries \
camlcode.o -L`ocamlc -where` -lunix -lasmrun
```

For the final linking phase, in addition to the object file produced by `-output-complete-obj`, you will have only to provide the C libraries required by the OCaml runtime.

For instance, assume the OCaml part of your program uses the Unix library. With `ocamlc`, you should do:

```
ocamlc -output-complete-obj -o camlcode.o unix.cma other .cmo and .cma files
cc -o myprog C objects and libraries \
camlcode.o C libraries required by the runtime, eg -lm -ldl -lcurses -lpthread
```

With `ocamlopt`, you should do:
ocamlopt -output-complete-obj -o camlcode.o unix.cmxa other .cmx and .cmxa files

cc -o myprog C objects and libraries \
camlcode.o C libraries required by the runtime, eg -lm -ldl

**Warning:** On some ports, special options are required on the final linking phase that links together the object file produced by the `-output-obj` and `-output-complete-obj` options and the remainder of the program. Those options are shown in the configuration file `Makefile.config` generated during compilation of OCaml, as the variable `OC_LDFLAGS`.

* Windows with the MSVC compiler: the object file produced by OCaml have been compiled with the `/MD` flag, and therefore all other object files linked with it should also be compiled with `/MD`.

* other systems: you may have to add one or both of `-lm` and `-ldl`, depending on your OS and C compiler.

**Stack backtraces.** When OCaml bytecode produced by `ocamlc -g` is embedded in a C program, no debugging information is included, and therefore it is impossible to print stack backtraces on uncaught exceptions. This is not the case when native code produced by `ocamlopt -g` is embedded in a C program: stack backtrace information is available, but the backtrace mechanism needs to be turned on programmatically. This can be achieved from the OCaml side by calling `Printexc.record_backtrace true` in the initialization of one of the OCaml modules. This can also be achieved from the C side by calling `caml_record_backtraces(1);` in the OCaml-C glue code. (`caml_record_backtraces` is declared in `backtrace.h`)

**Unloading the runtime.**

In case the shared library produced with `-output-obj` is to be loaded and unloaded repeatedly by a single process, care must be taken to unload the OCaml runtime explicitly, in order to avoid various system resource leaks.

Since 4.05, `caml_shutdown` function can be used to shut the runtime down gracefully, which equals the following:

* Running the functions that were registered with `Stdlib.at_exit`.

* Triggering finalization of allocated custom blocks (see section 22.9). For example, `Stdlib.in_channel` and `Stdlib.out_channel` are represented by custom blocks that enclose file descriptors, which are to be released.

* Unloading the dependent shared libraries that were loaded by the runtime, including `dynlink` plugins.

* Freeing the memory blocks that were allocated by the runtime with `malloc`. Inside C primitives, it is advised to use `caml_stat_*` functions from `memory.h` for managing static (that is, non-moving) blocks of heap memory, as all the blocks allocated with these functions are automatically freed by `caml_shutdown`. For ensuring compatibility with legacy C stubs that have used `caml_stat_*` incorrectly, this behaviour is only enabled if the runtime is started with a specialized `caml_startup_pooled` function.
# Chapter 23

## Optimisation with Flambda

### 23.1 Overview

Flambda is the term used to describe a series of optimisation passes provided by the native code compilers as of OCaml 4.03.

Flambda aims to make it easier to write idiomatic OCaml code without incurring performance penalties.

To use the Flambda optimisers it is necessary to pass the `-flambda` option to the OCaml `configure` script. (There is no support for a single compiler that can operate in both Flambda and non-Flambda modes.) Code compiled with Flambda cannot be linked into the same program as code compiled without Flambda. Attempting to do this will result in a compiler error.

Whether or not a particular `ocamlopt` uses Flambda may be determined by invoking it with the `-config` option and looking for any line starting with "`flambda:`". If such a line is present and says "`true`", then Flambda is supported, otherwise it is not.

Flambda provides full optimisation across different compilation units, so long as the `.cmx` files for the dependencies of the unit currently being compiled are available. (A compilation unit corresponds to a single `.ml` source file.) However it does not yet act entirely as a whole-program compiler: for example, elimination of dead code across a complete set of compilation units is not supported.

Optimisation with Flambda is not currently supported when generating bytecode.

Flambda should not in general affect the semantics of existing programs. Two exceptions to this rule are: possible elimination of pure code that is being benchmarked (see section 23.14) and changes in behaviour of code using unsafe operations (see section 23.15).

Flambda does not yet optimise array or string bounds checks. Neither does it take hints for optimisation from any assertions written by the user in the code.

Consult the *Glossary* at the end of this chapter for definitions of technical terms used below.

### 23.2 Command-line flags

The Flambda optimisers provide a variety of command-line flags that may be used to control their behaviour. Detailed descriptions of each flag are given in the referenced sections. Those sections also describe any arguments which the particular flags take.

Commonly-used options:
As a shared library may have several clients simultaneously, it is made for convenience that `caml_startup` (and `caml_startup_pooled`) may be called multiple times, given that each such call is paired with a corresponding call to `caml_shutdown` (in a nested fashion). The runtime will be unloaded once there are no outstanding calls to `caml_startup`.

Once a runtime is unloaded, it cannot be started up again without reloading the shared library and reinitializing its static data. Therefore, at the moment, the facility is only useful for building reloadable shared libraries.

**Unix signal handling.** Depending on the target platform and operating system, the native-code runtime system may install signal handlers for one or several of the `SIGSEGV`, `SIGTRAP` and `SIGFPE` signals when `caml_startup` is called, and reset these signals to their default behaviors when `caml_shutdown` is called. The main program written in C should not try to handle these signals itself.

## 22.8 Advanced example with callbacks

This section illustrates the callback facilities described in section 22.7. We are going to package some OCaml functions in such a way that they can be linked with C code and called from C just like any C functions. The OCaml functions are defined in the following `mod.ml` OCaml source:

```c
(* File mod.ml -- some "useful" OCaml functions *)

let rec fib n = if n < 2 then n else fib(n-1) + fib(n-2)

let format_result n = Printf.sprintf "Result is: %d\n" n

(* Export those two functions to C *)

let _ = Callback.register "fib" fib
let _ = Callback.register "format_result" format_result
```

Here is the C stub code for calling these functions from C:

```c
/* File modwrap.c -- wrappers around the OCaml functions */

#include <stdio.h>
#include <string.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>

int fib(int n)
{
    static const value * fib_closure = NULL;
    if (fib_closure == NULL) fib_closure = caml_named_value("fib");
    return Int_val.caml_callback(*fib_closure, Val_int(n));
```
-02 Perform more optimisation than usual. Compilation times may be lengthened. (This flag is an abbreviation for a certain set of parameters described in section 23.5.)

-03 Perform even more optimisation than usual, possibly including unrolling of recursive functions. Compilation times may be significantly lengthened.

**-Oclassic**

Make inlining decisions at the point of definition of a function rather than at the call site(s). This mirrors the behaviour of OCaml compilers not using Flambda. Compared to compilation using the new Flambda inlining heuristics (for example at -02) it produces smaller .cmx files, shorter compilation times and code that probably runs rather slower. When using -Oclassic, only the following options described in this section are relevant: -inlining-report and -inline. If any other of the options described in this section are used, the behaviour is undefined and may cause an error in future versions of the compiler.

**-inlining-report**

Emit .inlining files (one per round of optimisation) showing all of the inliner's decisions.

Less commonly-used options:

**-remove-unused-arguments**

Remove unused function arguments even when the argument is not specialised. This may have a small performance penalty. See section 23.10.3.

**-unbox-closures**

Pass free variables via specialised arguments rather than closures (an optimisation for reducing allocation). See section 23.9.3. This may have a small performance penalty.

Advanced options, only needed for detailed tuning:

**-inline**

The behaviour depends on whether -Oclassic is used.

* When not in -Oclassic mode, -inline limits the total size of functions considered for inlining during any speculative inlining search. (See section 23.3.10.) Note that this parameter does not control the assessment as to whether any particular function may be inlined. Raising it to excessive amounts will not necessarily cause more functions to be inlined.

* When in -Oclassic mode, -inline behaves as in previous versions of the compiler: it is the maximum size of function to be considered for inlining. See section 23.3.2.

**-inline-tLEVEL**

The equivalent of -inline but used when speculative inlining starts at toplevel. See section 23.3.10. Not used in -Oclassic mode.

**-inline-branch-factor**

Controls how the inliner assesses whether a code path is likely to be hot or cold. See section 23.3.9.
```c
}

char * format_result(int n)
{
    static const value * format_result_closed = NULL;
    if (format_result_closed == NULL)
        format_result_closed = caml_named_value("format_result");
    return strdup(String_val(caml_callback(*format_result_closed, Val_int(n))));
    /* We copy the C string returned by String_val to the C heap
     * so that it remains valid after garbage collection. */
}
```

We now compile the OCaml code to a C object file and put it in a C library along with the stub code in `modwrap.c` and the OCaml runtime system:

```
ocamlc -custom -output-obj -o modcaml.o mod.ml
ocamlc -c modwrap.c
cp `ocamlc -where `/libcamlrun.a mod.a && chmod +w mod.a
ar r mod.a modcaml.o modwrap.o
```

(One can also use `ocamlopt -output-obj` instead of `ocamlc -custom -output-obj`. In this case, replace `libcamlrun.a` (the bytecode runtime library) by `libasmrun.a` (the native-code runtime library).)

Now, we can use the two functions `fib` and `format_result` in any C program, just like regular C functions. Just remember to call `caml_startup` (or `caml_startup_exn`) once before.

```c
/* File main.c -- a sample client for the OCaml functions */

#include <stdio.h>
#include <caml/callback.h>

extern int fib(int n);
extern char * format_result(int n);

int main(int argc, char ** argv)
{
    int result;

    /* Initialize OCaml code */
    caml_startup(argv);
    /* Do some computation */
    result = fib(10);
    printf("fib(10) = %s\n", format_result(result));
    return 0;
}
```

To build the whole program, just invoke the C compiler as follows:
- *inline-alloc-cost*, *inline-branch-cost*, *inline-call-cost*

Controls how the inliner assesses the runtime performance penalties associated with various operations. See section 23.3.9.

- *inline-indirect-cost*, *inline-prim-cost*

Likewise.

- *inline-lifting-benefit*

Controls inlining of functors at toplevel. See section 23.3.9.

- *inline-max-depth*

The maximum depth of any speculative inlining search. See section 23.3.10.

- *inline-max-unroll*

The maximum depth of any unrolling of recursive functions during any speculative inlining search. See section 23.3.10.

- *no-unbox-free-vars-of-closures*

Do not unbox closure variables. See section 23.9.1.

- *no-unbox-specialised-args*

Do not unbox arguments to which functions have been specialised. See section 23.9.2.

- *rounds*

How many rounds of optimisation to perform. See section 23.2.1.

- *unbox-closures-factor*

Scaling factor for benefit calculation when using *unbox-closures*. See section 23.9.3.

## Notes

* The set of command line flags relating to optimisation should typically be specified to be the same across an entire project. Flambda does not currently record the requested flags in the `.cmx` files. As such, inlining of functions from previously-compiled units will subject their code to the optimisation parameters of the unit currently being compiled, rather than those specified when they were previously compiled. It is hoped to rectify this deficiency in the future.

* Flambda-specific flags do not affect linking with the exception of affecting the optimisation of code in the startup file (containing generated functions such as currying helpers). Typically such optimisation will not be significant, so eliding such flags at link time might be reasonable.

* Flambda-specific flags are silently accepted even when the `-flambda` option was not provided to the `configure` script. (There is no means provided to change this behaviour.) This is intended to make it more straightforward to run benchmarks with and without the Flambda optimisers in effect.

* Some of the Flambda flags may be subject to change in future releases.
cc -o prog -I `ocamlc -where` main.c mod.a -lcurses

(On some machines, you may need to put -ltermcap or -lcurses -ltermcap instead of -lcurses.)

## 22.9 Advanced topic: custom blocks

Blocks with tag `Custom_tag` start with a pointer to a C struct with type `struct custom_operations` that associates user-provided finalization, comparison, hashing, serialization and deserialization functions for this block.

After this pointer to custom operations, there can be arbitrary data of zero, one or more words whose semantics is defined by the user (for example this can be just a pointer to a C struct or a C struct itself). Use `Data_custom_val` on the block value to get a pointer on the start of this arbitrary data.

### 22.9.1 The struct custom_operations

The `struct custom_operations` is defined in `<caml/custom.h>` and contains the following fields:

* `char *identifier`

A zero-terminated character string serving as an identifier for serialization and deserialization operations.

* `void (*finalize)(value v)`

The `finalize` field contains a pointer to a C function that is called when the block becomes unreachable and is about to be reclaimed. The block is passed as first argument to the function. The `finalize` field can also be `custom_finalize_default` to indicate that no finalization function is associated with the block. Note the caution below: there are many restrictions on the behaviour of these custom block finalizers. For more powerful and flexible finalization, use `Gcopp` (see Gc[29.25]).

* `int (*compare)(value v1, value v2)`

The `compare` field contains a pointer to a C function that is called whenever two custom blocks are compared using OCaml's generic comparison operators (`=`, `<>`, `<=`, `>=`, `<`, `>`, and `compare`). The C function should return 0 if the data contained in the two blocks are structurally equal, a negative integer if the data from the first block is less than the data from the second block, and a positive integer if the data from the first block is greater than the data from the second block.

The `compare` field can be set to `custom_compare_default`; this default comparison function simply raises `Failure`.

* `int (*compare_ext)(value v1, value v2)`

(Since 3.12.1) The `compare_ext` field contains a pointer to a C function that is called whenever one custom block and one unboxed integer are compared using OCaml's generic comparison operators (`=`, `<>`, `<=`, `>=`, `<`, `>`, and `compare`). As in the case of the `compare` field, the C function should return 0 if the two arguments are structurally equal, a negative integer if the first argument compares less than the second argument, and a positive integer if the first argument compares greater than the second argument.
### 23.2.1 Specification of optimisation parameters by round

Lambda operates in *rounds*: one round consists of a certain sequence of transformations that may then be repeated in order to achieve more satisfactory results. The number of rounds can be set manually using the `-rounds` parameter (although this is not necessary when using predefined optimisation levels such as with `-O2` and `-O3`). For high optimisation the number of rounds might be set at 3 or 4.

Command-line flags that may apply per round, for example those with `-cost` in the name, accept arguments of the form:

$$n | round=n[,...]$$

* If the first form is used, with a single integer specified, the value will apply to all rounds.

* If the second form is used, zero-based *round* integers specify values which are to be used only for those rounds.

The flags `-Oclassic`, `-O2` and `-O3` are applied before all other flags, meaning that certain parameters may be overridden without having to specify every parameter usually invoked by the given optimisation level.

## 23.3 Inlining

Inlining refers to the copying of the code of a function to a place where the function is called. The code of the function will be surrounded by bindings of its parameters to the corresponding arguments.

The aims of inlining are:

* to reduce the runtime overhead caused by function calls (including setting up for such calls and returning afterwards);

* to reduce instruction cache misses by expressing frequently-taken paths through the program using fewer machine instructions; and

* to reduce the amount of allocation (especially of closures).

These goals are often reached not just by inlining itself but also by other optimisations that the compiler is able to perform as a result of inlining.

When a recursive call to a function (within the definition of that function or another in the same mutually-recursive group) is inlined, the procedure is also known as *unrolling*. This is somewhat akin to loop peeling. For example, given the following code:

```h
let rec fact x =
    if x == 0 then
        1
    else
        x * fact (x - 1)
```

```h
let n = fact 4
```
The `compare_ext` field can be set to `custom_compare_ext_default`; this default comparison function simply raises `Failure`.

* `intnat` (*hash)(value v)

The `hash` field contains a pointer to a C function that is called whenever OCaml's generic hash operator (see module `Hashtbl[29.26]`) is applied to a custom block. The C function can return an arbitrary integer representing the hash value of the data contained in the given custom block. The hash value must be compatible with the `compare` function, in the sense that two structurally equal data (that is, two custom blocks for which `compare` returns 0) must have the same hash value.

The `hash` field can be set to `custom_hash_default`, in which case the custom block is ignored during hash computation.

* `void` (*` serialize`)(value v, uintnat * bsize_32, uintnat * bsize_64)

The ` serialize` field contains a pointer to a C function that is called whenever the custom block needs to be serialized (marshaled) using the OCaml functions `output_value` or ` Marshal.to_...`. For a custom block, those functions first write the identifier of the block (as given by the `identifier` field) to the output stream, then call the user-provided ` serialize` function. That function is responsible for writing the data contained in the custom block, using the ` serialize_...` functions defined in `<caml/intext.h>` and listed in section 22.9.4. The user-provided ` serialize` function must then store in its `bsize_32` and `bsize_64` parameters the sizes in bytes of the data part of the custom block on a 32-bit architecture and on a 64-bit architecture, respectively.

The ` serialize` field can be set to `custom_serialize_default`, in which case the `Failure` exception is raised when attempting to serialize the custom block.

* `uintnat` (*`deserialze`)(void * dst)

The ` deserialze ` field contains a pointer to a C function that is called whenever a custom block with identifier ` identifier ` needs to be deserialized (un-marshaled) using the OCaml functions ` input_value ` or ` Marshal.from_...`. This user-provided function is responsible for reading back the data written by the ` serialize ` operation, using the ` deserialze_... ` functions defined in `<caml/intext.h>` and listed in section 22.9.4. It must then rebuild the data part of the custom block and store it at the pointer given as the ` dst ` argument. Finally, it returns the size in bytes of the data part of the custom block. This size must be identical to the ` bsize_32 ` result of the ` serialize ` operation if the architecture is 32 bits, or ` bsize_64 ` if the architecture is 64 bits.

The ` deserialze ` field can be set to ` custom_deserialize_default ` to indicate that deserial-
ization is not supported. In this case, do not register the ` struct custom_operations ` with
the deserializer using ` register_custom_operations ` (see below).

* `const struct custom_fixed_length* fixed_length`

(Since 4.08.0) Normally, space in the serialized output is reserved to write the `bsize_32` and `bsize_64` fields returned by ` serialize`. However, for very short custom blocks, this space can be larger than the data itself! As a space optimisation, if ` serialize` always returns the same values for `bsize_32` and `bsize_64`, then these values may be specified in the `fixed_length` structure, and do not consume space in the serialized output.
unrolling once at the call site fact 4 produces (with the body of fact unchanged):

```hml
let n =
  if 4 = 0 then
    1
  else
    4 * fact (4 - 1)
```

This simplifies to:

```hml
let n = 4 * fact 3
```

Flambda provides significantly enhanced inlining capabilities relative to previous versions of the compiler.

### 23.3.1 Aside: when inlining is performed

Inlining is performed together with all of the other Flambda optimisation passes, that is to say, after closure conversion. This has three particular advantages over a potentially more straightforward implementation prior to closure conversion:

* It permits higher-order inlining, for example when a non-inlinable function always returns the same function yet with different environments of definition. Not all such cases are supported yet, but it is intended that such support will be improved in future.

* It is easier to integrate with cross-module optimisation, since imported information about other modules is already in the correct intermediate language.

* It becomes more straightforward to optimise closure allocations since the layout of closures does not have to be estimated in any way: it is known. Similarly, it becomes more straightforward to control which variables end up in which closures, helping to avoid closure bloat.

### 23.3.2 Classic inlining heuristic

In `-Oclassic` mode the behaviour of the Flambda inliner mimics previous versions of the compiler. (Code may still be subject to further optimisations not performed by previous versions of the compiler: functors may be inlined, constants are lifted and unused code is eliminated all as described elsewhere in this chapter. See sections 23.3.5, 23.8.1 and 23.10. At the definition site of a function, the body of the function is measured. It will then be marked as eligible for inlining (and hence inlined at every direct call site) if:

* the measured size (in unspecified units) is smaller than that of a function call plus the argument of the `-inline` command-line flag; and

* the function is not recursive.

Non-Lambda versions of the compiler cannot inline functions that contain a definition of another function. However `-Oclassic` does permit this. Further, non-Lambda versions also cannot inline functions that are only themselves exposed as a result of a previous pass of inlining, but again this is permitted by `-Oclassic`. For example:
**Caution:** the `finalize`, `compare`, `hash`, ` serialize`, and `desHIPeR` functions attached to custom block descriptors are allowed only limited interactions with the OCaml runtime. Within these functions, do not call any of the OCaml allocation functions, and do not perform any callback into OCaml code or allow it to be called (for example, do not call `caml_release_runtime_system()`). Do not use `CAMLparam` to register the parameters to these functions, do not use `CAMLlocal` to register their local variables, and do not use `CAMLreturn` to return the result. Do not raise exceptions. To signal an error during deserialization, use `caml_des工業ize_error`, and ` serialize` and `desHIPeR` functions may freely use the functions from section 22.9.4. There are especially stringent restrictions on the behavior of custom block finalizers. In addition to the restrictions above, finalizers must not access the OCaml heap, or mutate the OCaml heap or any memory reachable from OCaml GC roots. However, note that `finalize` functions may freely use `caml_remove_global_root` and `caml_remove_generational_global_root`. In short, if a custom block finalizer does anything with the `value` it receives other than call `Data_custom_val` on it, then it is probably unsafe. When in doubt, err on the side of caution.

## 22.9.2 Allocating custom blocks

Custom blocks must be allocated via `caml_alloc_custom` or `caml_alloc_custom_mem`:

```
caml_alloc_custom(ops, size, used, max)
```

returns a fresh custom block, with room for `size` bytes of user data, and whose associated operations are given by `ops` (a pointer to a `struct custom_operations`, usually statically allocated as a C global variable).

The two parameters `used` and `max` are used to control the speed of garbage collection when the finalized object contains pointers to out-of-heap resources. Generally speaking, the OCaml incremental major collector adjusts its speed relative to the allocation rate of the program. The faster the program allocates, the harder the GC works in order to reclaim quickly unreachable blocks and avoid having large amount of “floating garbage” (unreferenced objects that the GC has not yet collected).

Normally, the allocation rate is measured by counting the in-heap size of allocated blocks. However, it often happens that finalized objects contain pointers to out-of-heap memory blocks and other resources (such as file descriptors, X Windows bitmaps, etc.). For those blocks, the in-heap size of blocks is not a good measure of the quantity of resources allocated by the program.

The two arguments `used` and `max` give the GC an idea of how much out-of-heap resources are consumed by the finalized block being allocated: you give the amount of resources allocated to this object as parameter `used`, and the maximum amount that you want to see in floating garbage as parameter `max`. The units are arbitrary: the GC cares only about the ratio `used/max`.

For instance, if you are allocating a finalized block holding an X Windows bitmap of `w` by `h` pixels, and you'd rather not have more than 1 mega-pixels of unreclaimed bitmaps, specify `used = w * h` and `max = 1000000`.

Another way to describe the effect of the `used` and `max` parameters is in terms of full GC cycles. If you allocate many custom blocks with `used/max = 1/N`, the GC will then do one full cycle (examining every object in the heap and calling finalization functions on those that are unreachable) every `N` allocations. For instance, if `used = 1` and `max = 1000`, the GC will do one full cycle at least every 1000 allocations of custom blocks.
module M : sig
  val i : int
end = struct
  let f x =
    let g y = x + y in
    g
  let h = f 3
  let i = h 4 (* h is correctly discovered to be g and inlined *)
end

All of this contrasts with the normal `Lambda` mode, that is to say without `-Oclassic`, where:

* the inlining decision is made at the **call site**; and

* recursive functions can be handled, by *specialisation* (see below).

The `Lambda` mode is described in the next section.

### 23.3.3 Overview of “Lambda” inlining heuristics

The `Lambda` inlining heuristics, used whenever the compiler is configured for `Lambda` and `-Oclassic` was not specified, make inlining decisions at call sites. This helps in situations where the context is important. For example:

let f b x =
  if b then
    x
  else
    ... big expression ...

let g x = f true x

In this case, we would like to inline `f` into `g`, because a conditional jump can be eliminated and the code size should reduce. If the inlining decision has been made after the declaration of `f` without seeing the use, its size would have probably made it ineligible for inlining; but at the call site, its final size can be known. Further, this function should probably not be inlined systematically: if `b` is unknown, or indeed `false`, there is little benefit to trade off against a large increase in code size. In the existing non-`Lambda` inliner this isn't a great problem because chains of inlining were cut off fairly quickly. However it has led to excessive use of overly-large inlining parameters such as `-inline 10000`.

In more detail, at each call site the following procedure is followed:

* Determine whether it is clear that inlining would be beneficial without, for the moment, doing any inlining within the function itself. (The exact assessment of *benefit* is described below.) If so, the function is inlined.

* If inlining the function is not clearly beneficial, then inlining will be performed *speculatively* inside the function itself. The search for speculative inlining possibilities is controlled by two parameters: the *inlining threshold* and the *inlining depth*. (These are described in more detail below.)
If your finalized blocks contain no pointers to out-of-heap resources, or if the previous discussion made little sense to you, just take `used = 0` and `max = 1`. But if you later find that the finalization functions are not called "often enough", consider increasing the `used/max` ratio.

`caml_alloc_custom_mem(ops, size, used)`

Use this function when your custom block holds only out-of-heap memory (memory allocated with `malloc` or `caml_stat_alloc`) and no other resources. `used` should be the number of bytes of out-of-heap memory that are held by your custom block. This function works like `caml_alloc_custom` except that the `max` parameter is under the control of the user (via the `custom_major_ratio`, `custom_minor_ratio`, and `custom_minor_max_size` parameters) and proportional to the heap sizes. It has been available since OCaml 4.08.0.

### 22.9.3 Accessing custom blocks

The data part of a custom block `v` can be accessed via the pointer `Data_custom_val(v)`. This pointer has type `void *` and should be cast to the actual type of the data stored in the custom block.

The contents of custom blocks are not scanned by the garbage collector, and must therefore not contain any pointer inside the OCaml heap. In other terms, never store an OCaml `value` in a custom block, and do not use `Field`, `Store_field` nor `caml_modify` to access the data part of a custom block. Conversely, any C data structure (not containing heap pointers) can be stored in a custom block.

### 22.9.4 Writing custom serialization and deserialization functions

The following functions, defined in `<caml/intext.h>`, are provided to write and read back the contents of custom blocks in a portable way. Those functions handle endianness conversions when e.g. data is written on a little-endian machine and read back on a big-endian machine.
- If such speculation shows that performing some inlining inside the function would be beneficial, then such inlining is performed and the resulting function inlined at the original call site.

- Otherwise, nothing happens.

Inlining within recursive functions of calls to other functions in the same mutually-recursive group is kept in check by an *unrolling depth*, described below. This ensures that functions are not unrolled to excess. (Unrolling is only enabled if `-O3` optimisation level is selected and/or the `-inline-max-unroll` flag is passed with an argument greater than zero.)

### 23.3.4 Handling of specific language constructs

### 23.3.5 Functors

There is nothing particular about functors that inhibits inlining compared to normal functions. To the inliner, these both look the same, except that functors are marked as such.

Applications of functors at toplevel are biased in favour of inlining. (This bias may be adjusted: see the documentation for `-inline-lifting-benefit` below.)

Applications of functors not at toplevel, for example in a local module inside some other expression, are treated by the inliner identically to normal function calls.

### 23.3.6 First-class modules

The inliner will be able to consider inlining a call to a function in a first class module if it knows which particular function is going to be called. The presence of the first-class module record that wraps the set of functions in the module does not per se inhibit inlining.

### 23.3.7 Objects

Method calls to objects are not at present inlined by Flambda.

### 23.3.8 Inlining reports

If the `-inlining-report` option is provided to the compiler then a file will be emitted corresponding to each round of optimisation. For the OCaml source file `basename.ml` the files are named `basename-round.inlining.org`, with `round` a zero-based integer. Inside the files, which are formatted as "org mode", will be found English prose describing the decisions that the inliner took.

### 23.3.9 Assessment of inlining benefit

Inlining typically results in an increase in code size, which if left unchecked, may not only lead to grossly large executables and excessive compilation times but also a decrease in performance due to worse locality. As such, the Flambda inliner trades off the change in code size against the expected runtime performance benefit, with the benefit being computed based on the number of operations that the compiler observes may be removed as a result of inlining.

For example given the following code:
<table><thead><tr><th>Function</th><th>Action</th></tr></thead><tbody><tr><td>caml_serialized_int_1</td><td>Write a 1-byte integer</td></tr><tr><td>caml_serialized_int_2</td><td>Write a 2-byte integer</td></tr><tr><td>caml_serialized_int_4</td><td>Write a 4-byte integer</td></tr><tr><td>caml_serialized_int_8</td><td>Write a 8-byte integer</td></tr><tr><td>caml_serialized_float_4</td><td>Write a 4-byte float</td></tr><tr><td>caml_serialized_float_8</td><td>Write a 8-byte float</td></tr><tr><td>caml_serialized_block_1</td><td>Write an array of 1-byte quantities</td></tr><tr><td>caml_serialized_block_2</td><td>Write an array of 2-byte quantities</td></tr><tr><td>caml_serialized_block_4</td><td>Write an array of 4-byte quantities</td></tr><tr><td>caml_serialized_block_8</td><td>Write an array of 8-byte quantities</td></tr><tr><td>caml_des工業ize_uint_1</td><td>Read an unsigned 1-byte integer</td></tr><tr><td>caml_des工业ize_sint_1</td><td>Read a signed 1-byte integer</td></tr><tr><td>caml_des工业ize_uint_2</td><td>Read an unsigned 2-byte integer</td></tr><tr><td>caml_des工业ize_sint_2</td><td>Read a signed 2-byte integer</td></tr><tr><td>caml_des工业ize_uint_4</td><td>Read an unsigned 4-byte integer</td></tr><tr><td>caml_des工业ize_sint_4</td><td>Read a signed 4-byte integer</td></tr><tr><td>caml_des工业ize_uint_8</td><td>Read an unsigned 8-byte integer</td></tr><tr><td>caml_des工业ize_sint_8</td><td>Read a signed 8-byte integer</td></tr><tr><td>caml_des工业ize_float_4</td><td>Read a 4-byte float</td></tr><tr><td>caml_des工业ize_float_8</td><td>Read an 8-byte float</td></tr><tr><td>caml_des工业ize_block_1</td><td>Read an array of 1-byte quantities</td></tr><tr><td>caml_des工业ize_block_2</td><td>Read an array of 2-byte quantities</td></tr><tr><td>caml_des工业ize_block_4</td><td>Read an array of 4-byte quantities</td></tr><tr><td>caml_des工业ize_block_8</td><td>Read an array of 8-byte quantities</td></tr><tr><td>caml_des工业ize_error</td><td>Signal an error during deserialization; input_value or Marshal.from... raise a Failure exception after cleaning up their internal data structures</td></tr></tbody></table>

Serlization functions are attached to the custom blocks to which they apply. Obviously, deserialization functions cannot be attached this way, since the custom block does not exist yet when deserialization begins! Thus, the struct custom_operations that contain deserialization functions must be registered with the deserializer in advance, using the register_custom_operations function declared in <caml/custom.h>. Deserialization proceeds by reading the identifier off the input stream, allocating a custom block of the size specified in the input stream, searching the registered struct custom_operations blocks for one with the same identifier, and calling its desynchronize function to fill the data part of the custom block.

### 22.9.5 Choosing identifiers

Identifiers in struct custom_operations must be chosen carefully, since they must identify uniquely the data structure for serialization and deserialization operations. In particular, consider including a version number in the identifier; this way, the format of the data can be changed later, yet backward-compatible deserialisation functions can be provided.

Identifiers starting with `_` (an underscore character) are reserved for the OCaml runtime system; do not use them for your custom data. We recommend to use a URL
```hml
let f b x =
  if b then
    x
  else
    ... big expression ...
```

```hml
let g x = f true x
```

it would be observed that inlining of `f` would remove:

* one direct call;

* one conditional branch.

Formally, an estimate of runtime performance benefit is computed by first summing the cost of the operations that are known to be removed as a result of the inlining and subsequent simplification of the inlined body. The individual costs for the various kinds of operations may be adjusted using the various `-inline-...-cost` flags as follows. Costs are specified as integers. All of these flags accept a single argument describing such integers using the conventions detailed in section 23.2.1.

**-inline-alloc-cost**

The cost of an allocation.

**-inline-branch-cost**

The cost of a branch.

**-inline-call-cost**

The cost of a direct function call.

**-inline-indirect-cost**

The cost of an indirect function call.

**-inline-prim-cost**

The cost of a *primitive*. Primitives encompass operations including arithmetic and memory access.

(Default values are described in section 23.5 below.)

The initial benefit value is then scaled by a factor that attempts to compensate for the fact that the current point in the code, if under some number of conditional branches, may be cold. (Lambda does not currently compute hot and cold paths.) The factor—the estimated probability that the inliner really is on a *hot* path—is calculated as $\frac{1}{(1+f)^d}$, where f is set by `-inline-branch-factor` and d is the nesting depth of branches at the current point. As the inliner descends into more deeply-nested branches, the benefit of inlining thus lessens.

The resulting benefit value is known as the *estimated benefit*.

The change in code size is also estimated: morally speaking it should be the change in machine code size, but since that is not available to the inliner, an approximation is used.

If the estimated benefit exceeds the increase in code size then the inlined version of the function will be kept. Otherwise the function will not be inlined.

Applications of functors at toplevel will be given an additional benefit (which may be controlled by the `-inline-lifting-benefit` flag) to bias inlining in such situations towards keeping the inlined version.
(http://mymachine.mydomain.com/mylibrary/version-number) or a Java-style package name (com.mydomain.mymachine.mylibrary.version-number) as identifiers, to minimize the risk of identifier collision.

### 22.9.6 Finalized blocks

Custom blocks generalize the finalized blocks that were present in OCaml prior to version 3.00. For backwards compatibility, the format of custom blocks is compatible with that of finalized blocks, and the `caml_alloc_final` function is still available to allocate a custom block with a given finalization function, but default comparison, hashing and serialization functions. (In particular, the finalization function must not access the OCaml runtime.)

`caml_alloc_final(n, f, used, max)` returns a fresh custom block of size $n+1$ words, with finalization function $f$. The first word is reserved for storing the custom operations; the other $n$ words are available for your data. The two parameters `used` and `max` are used to control the speed of garbage collection, as described for `caml_alloc_custom`.

## 22.10 Advanced topic: Bigarrays and the OCaml-C interface

This section explains how C stub code that interfaces C or Fortran code with OCaml code can use Bigarrays.

### 22.10.1 Include file

The include file `<caml/bigarray.h>` must be included in the C stub file. It declares the functions, constants and macros discussed below.

### 22.10.2 Accessing an OCaml bigarray from C or Fortran

If $v$ is a OCaml value representing a Bigarray, the expression `Caml_ba_data_val(v)` returns a pointer to the data part of the array. This pointer is of type `void *` and can be cast to the appropriate C type for the array (e.g. `double []`, `char [] [10]`, etc).

Various characteristics of the OCaml Bigarray can be consulted from C as follows:

<table><thead><tr><td>C expression</td><td>Returns</td></tr></thead><tbody><tr><td>Caml_ba_array_val(v)->num_dim</td><td>number of dimensions</td></tr><tr><td>Caml_ba_array_val(v)->dim[i]</td><td>i-th dimension</td></tr><tr><td>Caml_ba_array_val(v)->flags &amp; CAML_BA KIND_MASK</td><td>kind of array elements</td></tr></tbody></table>

The kind of array elements is one of the following constants:
### 23.3.10 Control of speculation

As described above, there are three parameters that restrict the search for inlining opportunities during speculation:

* the inlining threshold;

* the inlining depth;

* the unrolling depth.

These parameters are ultimately bounded by the arguments provided to the corresponding command-line flags (or their default values):

* `-inline` (or, if the call site that triggered speculation is at toplevel, `-inline-t LEVEL`);

* `-inline-max-depth`;

* `-inline-max-unroll`.

**Note in particular** that `-inline` does not have the meaning that it has in the previous compiler or in `-Oclassic` mode. In both of those situations `-inline` was effectively some kind of basic assessment of inlining benefit. However in Flambda inlining mode it corresponds to a constraint on the search; the assessment of benefit is independent, as described above.

When speculation starts the inlining threshold starts at the value set by `-inline` (or `-inline-tLEVEL` if appropriate, see above). Upon making a speculative inlining decision the threshold is reduced by the code size of the function being inlined. If the threshold becomes exhausted, at or below zero, no further speculation will be performed.

The inlining depth starts at zero and is increased by one every time the inliner descends into another function. It is then decreased by one every time the inliner leaves such function. If the depth exceeds the value set by `-inline-max-depth` then speculation stops. This parameter is intended as a general backstop for situations where the inlining threshold does not control the search sufficiently.

The unrolling depth applies to calls within the same mutually-recursive group of functions. Each time an inlining of such a call is performed the depth is incremented by one when examining the resulting body. If the depth reaches the limit set by `-inline-max-unroll` then speculation stops.

## 23.4 Specialisation

The inliner may discover a call site to a recursive function where something is known about the arguments: for example, they may be equal to some other variables currently in scope. In this situation it may be beneficial to *specialise* the function to those arguments. This is done by copying the declaration of the function (and any others involved in any same mutually-recursive declaration) and noting the extra information about the arguments. The arguments augmented by this information are known as *specialised arguments*. In order to try to ensure that specialisation is not performed uselessly, arguments are only specialised if it can be shown that they are *invariant*: in other words, during the execution of the recursive function(s) themselves, the arguments never change.

Unless overridden by an attribute (see below), specialisation of a function will not be attempted if:
<table><thead><tr><td>Constant</td><td>Element kind</td></tr></thead><tbody><tr><td>CAML_BA_FLOAT16</td><td>16-bit half-precision floats</td></tr><tr><td>CAML_BA_FLOAT32</td><td>32-bit single-precision floats</td></tr><tr><td>CAML_BA_FLOAT64</td><td>64-bit double-precision floats</td></tr><tr><td>CAML_BA_SINT8</td><td>8-bit signed integers</td></tr><tr><td>CAML_BA_UUID8</td><td>8-bit unsigned integers</td></tr><tr><td>CAML_BA_SINT16</td><td>16-bit signed integers</td></tr><tr><td>CAML_BA_UUID16</td><td>16-bit unsigned integers</td></tr><tr><td>CAML_BA_INT32</td><td>32-bit signed integers</td></tr><tr><td>CAML_BA_INT64</td><td>64-bit signed integers</td></tr><tr><td>CAML_BA_CAML_INT</td><td>31- or 63-bit signed integers</td></tr><tr><td>CAML_BA_native_INT</td><td>32- or 64-bit (platform-native) integers</td></tr><tr><td>CAML_BA_COMPLEX32</td><td>32-bit single-precision complex numbers</td></tr><tr><td>CAML_BA_COMPLEX64</td><td>64-bit double-precision complex numbers</td></tr><tr><td>CAML_BA_CHAR</td><td>8-bit characters</td></tr></tbody></table>

**Warning:** `Caml_ba_array_val(v)` must always be dereferenced immediately and not stored anywhere, including local variables. It resolves to a derived pointer: it is not a valid OCaml value but points to a memory region managed by the GC. For this reason this value must not be stored in any memory location that could be live cross a GC.

The following example shows the passing of a two-dimensional Bigarray to a C function and a Fortran function.

```c
extern void my_c_function(double * data, int dimx, int dimy);
extern void my_fortran_function_(double * data, int * dimx, int * dimy);

CAMLprim value camlstub(value bigarray)
{
    int dimx = Caml_ba_array_val(bigarray)->dim[0];
    int dimy = Caml_ba_array_val(bigarray)->dim[1];
    /* C passes scalar parameters by value */
    my_c_function(Caml_ba_data_val(bigarray), dimx, dimy);
    /* Fortran passes all parameters by reference */
    my_fortran_function_(Caml_ba_data_val(bigarray), &dimx, &dimy);
    return Val_unit;
}
```

### 22.10.3 Wrapping a C or Fortran array as an OCaml Bigarray

A pointer `p` to an already-allocated C or Fortran array can be wrapped and returned to OCaml as a Bigarray using the `caml_ba_alloc` or `caml_ba_alloc_dim` functions.

* `caml_ba_alloc(kind | layout, numdim`, `p`, `dim`)

Return an OCaml Bigarray wrapping the data pointed to by `p`. `kind` is the kind of array elements (one of the `CAML_BA_` kind constants above). `layout` is `CAML_BA_C_LAYOUT` for an array with C layout and `CAML_BA_FORTRAN_LAYOUT` for an array with Fortran layout. `numdim`
* the compiler is in `-Oclassic` mode;

* the function is not obviously recursive;

* the function is not closed.

The compiler can prove invariance of function arguments across multiple functions within a recursive group (although this has some limitations, as shown by the example below).

It should be noted that the *unboxing of closures* pass (see below) can introduce specialised arguments on non-recursive functions. (No other place in the compiler currently does this.)

**Example: the well-known `List.iter` function** This function might be written like so:

```python
let rec iter f l =
    match l with
    | [] -> ()
    | h :: t ->
        f h;
        iter f t
```

and used like this:

```python
let print_int x =
    print_endline (Int.to_string x)
```

```python
let run xs =
    iter print_int (List.rev xs)
```

The argument `f` to `iter` is invariant so the function may be specialised:

```python
let run xs =
    let rec iter' f l =
        (* The compiler knows: f holds the same value as foo throughout iter'. *)
        match l with
        | [] -> ()
        | h :: t ->
            f h;
            iter' f t
        in
        iter' print_int (List.rev xs)
```

The compiler notes down that for the function `iter'`, the argument `f` is specialised to the constant closure `print_int`. This means that the body of `iter'` may be simplified:

```python
let run xs =
    let rec iter' f l =
        (* The compiler knows: f holds the same value as foo throughout iter'. *)
        match l with
        | [] -> ()
```
is the number of dimensions in the array. ` dims ` is an array of ` numdimss ` long integers, giving the sizes of the array in each dimension.

* `caml_ba_alloc_dimsm (kind | layout, numdimsm, p, (long) dim₁, (long) dim₂, ..., (long) dimnumdimsm)`

Same as `caml_ba_alloc`, but the sizes of the array in each dimension are listed as extra arguments in the function call, rather than being passed as an array.

The following example illustrates how statically-allocated C and Fortran arrays can be made available to OCaml.

```c
extern long my_c_array[100][200];
extern float my_fortran_array_[300][400];

CAMLprim value caml_get_c_array(value unit)
{
    long dims[2];
    dims[0] = 100; dims[1] = 200;
    return caml_ba_alloc(CAML_BA_native_INT | CAML_BA_C_LAYOUT,
                          2, my_c_array, dims);
}

CAMLprim value caml_get_fortran_array(value unit)
{
    return caml_ba_alloc_dimsm(CAML_BA_FLOAT32 | CAML_BA_FORTRAN_LAYOUT,
                                 2, my_fortran_array_, 300L, 400L);
}
```

## 22.11 Advanced topic: cheaper C call

This section describe how to make calling C functions cheaper.

**Note:** This only applies to the native compiler. So whenever you use any of these methods, you have to provide an alternative byte-code stub that ignores all the special annotations.

### 22.11.1 Passing unboxed values

We said earlier that all OCaml objects are represented by the C type `value`, and one has to use macros such as `Int_val` to decode data from the `value` type. It is however possible to tell the OCaml native-code compiler to do this for us and pass arguments unboxed to the C function. Similarly it is possible to tell OCaml to expect the result unboxed and box it for us.

The motivation is that, by letting 'ocamlopt' deal with boxing, it can often decide to suppress it entirely.

For instance let's consider this example:

```c
external foo : float -> float -> float = "foo"
```
```h
| h :: t ->
  print_int h; (* this is now a direct call *)
  iter' f t

in
iter' print_int (List.rev xs)
```

The call to `print_int` can indeed be inlined:

```h
let run xs =
let rec iter' f l =
(* The compiler knows: f holds the same value as foo throughout iter'. *)
match l with
| [] -> ()
| h :: t ->
  print_endline (Int.to_string h);
  iter' f t

in
iter' print_int (List.rev xs)
```

The unused specialised argument `f` may now be removed, leaving:

```h
let run xs =
let rec iter' l =
match l with
| [] -> ()
| h :: t ->
  print_endline (Int.to_string h);
  iter' t

in
iter' (List.rev xs)
```

**Aside on invariant parameters.** The compiler cannot currently detect invariance in cases such as the following.

```h
let rec iter_swap f g l =
match l with
| [] -> ()
| 0 :: t ->
  iter_swap g f l
| h :: t ->
  f h;
  iter_swap f g t
```

### 23.4.1 Assessment of specialisation benefit

The benefit of specialisation is assessed in a similar way as for inlining. Specialised argument information may mean that the body of the function being specialised can be simplified: the removed operations are accumulated into a benefit. This, together with the size of the duplicated (specialised) function declaration, is then assessed against the size of the call to the original function.
``` OCaml
let f a b =
    let len = Array.length a in
    assert (Array.length b = len);
    let res = Array.make len 0. in
    for i = 0 to len - 1 do
        res.(i) <- foo a.(i) b.(i)
    done
```

Float arrays are unboxed in OCaml, however the C function `foo` expect its arguments as boxed floats and returns a boxed float. Hence the OCaml compiler has no choice but to box `a.(i)` and `b.(i)` and unbox the result of `foo`. This results in the allocation of `3 * len` temporary float values.

Now if we annotate the arguments and result with `[@unboxed]`, the native-code compiler will be able to avoid all these allocations:

``` OCaml
external foo
    : (float [@unboxed])
    -> (float [@unboxed])
    -> (float [@unboxed])
    = "foo_bytes" "foo"
```

In this case the C functions must look like:

``` C
CAMLprim double foo(double a, double b)
{
    ...
}
```

``` C
CAMLprim value foo_bytes(value a, value b)
{
    return caml_copy_double(foo(Double_val(a), Double_val(b)))
}
```

For convenience, when all arguments and the result are annotated with `[@unboxed]`, it is possible to put the attribute only once on the declaration itself. So we can also write instead:

``` OCaml
external foo : float -> float -> float = "foo_bytes" "foo" [@unboxed]
```

The following table summarize what OCaml types can be unboxed, and what C types should be used in correspondence:

<table><thead><tr><td>OCaml type</td><td>C type</td></tr></thead><tbody><tr><td>float</td><td>double</td></tr><tr><td>int32</td><td>int32_t</td></tr><tr><td>int64</td><td>int64_t</td></tr><tr><td>nativeint</td><td>intnat</td></tr></tbody></table>

Similarly, it is possible to pass untagged OCaml integers between OCaml and C. This is done by annotating the arguments and/or result with `[@untagged]`:
## 23.5 Default settings of parameters

The default settings (when not using `-Oclassic`) are for one round of optimisation using the following parameters.

<table><thead><tr><td>Parameter</td><td>Setting</td></tr></thead><tbody><tr><td>-inline</td><td>10</td></tr><tr><td>-inline-branch-factor</td><td>0.1</td></tr><tr><td>-inline-alloc-cost</td><td>7</td></tr><tr><td>-inline-branch-cost</td><td>5</td></tr><tr><td>-inline-call-cost</td><td>5</td></tr><tr><td>-inline-indirect-cost</td><td>4</td></tr><tr><td>-inline-prim-cost</td><td>3</td></tr><tr><td>-inline-lifting-benefit</td><td>1300</td></tr><tr><td>-inline-tLEVEL</td><td>160</td></tr><tr><td>-inline-max-depth</td><td>1</td></tr><tr><td>-inline-max-unroll</td><td>0</td></tr><tr><td>-unbox-closures-factor</td><td>10</td></tr></tbody></table>

### 23.5.1 Settings at -O2 optimisation level

When `-O2` is specified two rounds of optimisation are performed. The first round uses the default parameters (see above). The second uses the following parameters.

<table><thead><tr><td>Parameter</td><td>Setting</td></tr></thead><tbody><tr><td>-inline</td><td>25</td></tr><tr><td>-inline-branch-factor</td><td>Same as default</td></tr><tr><td>-inline-alloc-cost</td><td>Double the default</td></tr><tr><td>-inline-branch-cost</td><td>Double the default</td></tr><tr><td>-inline-call-cost</td><td>Double the default</td></tr><tr><td>-inline-indirect-cost</td><td>Double the default</td></tr><tr><td>-inline-prim-cost</td><td>Double the default</td></tr><tr><td>-inline-lifting-benefit</td><td>Same as default</td></tr><tr><td>-inline-tLEVEL</td><td>400</td></tr><tr><td>-inline-max-depth</td><td>2</td></tr><tr><td>-inline-max-unroll</td><td>Same as default</td></tr><tr><td>-unbox-closures-factor</td><td>Same as default</td></tr></tbody></table>

### 23.5.2 Settings at -O3 optimisation level

When `-O3` is specified three rounds of optimisation are performed. The first two rounds are as for `-O2`. The third round uses the following parameters.
external f : string -> (int [@untagged]) = "f_byte" "f"

The corresponding C type must be `intnat`.

**Note:** Do not use the C `int` type in correspondence with `(int [@untagged]])`. This is because they often differ in size.

It is possible to annotate with `[@untagged]` any immediate type, i.e. types that are represented like `int`. This includes `bool`, `char`, any variant type with only constant constructors. Note: this does not include `Unix.file_descr` which is not represented as an integer on all platforms.

### 22.11.2 Direct C call

In order to be able to run the garbage collector in the middle of a C function, the OCaml native-code compiler generates some bookkeeping code around C calls. Technically it wraps every C call with the C function `caml_c_call` which is part of the OCaml runtime.

For small functions that are called repeatedly, this indirection can have a big impact on performances. However this is not needed if we know that the C function doesn't allocate, doesn't raise exceptions, and doesn't release the domain lock (see section 22.12.2). We can instruct the OCaml native-code compiler of this fact by annotating the external declaration with the attribute `[@@noalloc]`:

external bar : int -> int -> int = "foo" [@@noalloc]

In this case calling `bar` from OCaml is as cheap as calling any other OCaml function, except for the fact that the OCaml compiler can't inline C functions...

### 22.11.3 Example: calling C library functions without indirection

Using these attributes, it is possible to call C library functions with no indirection. For instance many math functions are defined this way in the OCaml standard library:

external sqrt : float -> float = "camlsqrt float" "sqrt"
[@@unboxed] [@@noalloc]
(** Square root. *)

external exp : float -> float = "caml_exp_float" "exp" [@@unboxed] [@@noalloc]
(** Exponential. *)

external log : float -> float = "caml_log_float" "log" [@@unboxed] [@@noalloc]
(** Natural logarithm. *)

## 22.12 Advanced topic: multithreading

Using multiple threads (shared-memory concurrency) in a mixed OCaml/C application requires special precautions, which are described in this section.
<table><thead><tr><td>Parameter</td><td>Setting</td></tr></thead><tbody><tr><td>-inline</td><td>50</td></tr><tr><td>-inline-branch-factor</td><td>Same as default</td></tr><tr><td>-inline-alloc-cost</td><td>Triple the default</td></tr><tr><td>-inline-branch-cost</td><td>Triple the default</td></tr><tr><td>-inline-call-cost</td><td>Triple the default</td></tr><tr><td>-inline-indirect-cost</td><td>Triple the default</td></tr><tr><td>-inline-prim-cost</td><td>Triple the default</td></tr><tr><td>-inline-lifting-benefit</td><td>Same as default</td></tr><tr><td>-inline-tLEVEL</td><td>800</td></tr><tr><td>-inline-max-depth</td><td>3</td></tr><tr><td>-inline-max-unroll</td><td>1</td></tr><tr><td>-unbox-closures-factor</td><td>Same as default</td></tr></tbody></table>

## 23.6 Manual control of inlining and specialisation

Should the inliner prove recalcitrant and refuse to inline a particular function, or if the observed inlining decisions are not to the programmer's satisfaction for some other reason, inlining behaviour can be dictated by the programmer directly in the source code. One example where this might be appropriate is when the programmer, but not the compiler, knows that a particular function call is on a cold code path. It might be desirable to prevent inlining of the function so that the code size along the hot path is kept smaller, so as to increase locality.

The inliner is directed using attributes. For non-recursive functions (and one-step unrolling of recursive functions, although `@unroll` is more clear for this purpose) the following are supported:

**@@inline always or @@inline never**

Attached to a declaration of a function or functor, these direct the inliner to either always or never inline, irrespective of the size/benefit calculation. (If the function is recursive then the body is substituted and no special action is taken for the recursive call site(s).) `@@inline` with no argument is equivalent to `@@inline always`.

**@inlined always or @inlined never**

Attached to a function application, these direct the inliner likewise. These attributes at call sites override any other attribute that may be present on the corresponding declaration. `@inlined` with no argument is equivalent to `@inlined always`. `@@inlined hint` is equivalent to `@@inline always` except that it will not trigger warning 55 if the function application cannot be inlined.

For recursive functions the relevant attributes are:

**@@specialise always or @@specialise never**

Attached to a declaration of a function or functor, this directs the inliner to either always or never specialise the function so long as it has appropriate contextual knowledge, irrespective of the size/benefit calculation. `@@specialise` with no argument is equivalent to `@@specialise always`.
## 22.12.1 Registering threads created from C

Callbacks from C to OCaml are possible only if the calling thread is known to the OCaml run-time system. Threads created from OCaml (through the `Thread.create` function of the system threads library) are automatically known to the run-time system. If the application creates additional threads from C and wishes to callback into OCaml code from these threads, it must first register them with the run-time system. The following functions are declared in the include file <caml/threads.h>.

* `caml_c_thread_register()` registers the calling thread with the OCaml run-time system. Returns 1 on success, 0 on error. Registering an already-registered thread does nothing and returns 0.

* `caml_c_thread_unregister()` must be called before the thread terminates, to unregister it from the OCaml run-time system. Returns 1 on success, 0 on error. If the calling thread was not previously registered, does nothing and returns 0.

## 22.12.2 Parallel execution of long-running C code with systhreads

Domains are the unit of parallelism for OCaml programs. When using the systhreads library, multiple threads might be attached to the same domain. However, at any time, at most one of those thread can be executing OCaml code or C code that uses the OCaml run-time system by domain. Technically, this is enforced by a “domain lock” that any thread must hold while executing such code within a domain.

When OCaml calls the C code implementing a primitive, the domain lock is held, therefore the C code has full access to the facilities of the run-time system. However, no other thread in the same domain can execute OCaml code concurrently with the C code of the primitive. See also chapter 9.6 for the behaviour with multiple domains.

If a C primitive runs for a long time or performs potentially blocking input-output operations, it can explicitly release the domain lock, enabling other OCaml threads in the same domain to run concurrently with its operations. The C code must re-acquire the domain lock before returning to OCaml. This is achieved with the following functions, declared in the include file <caml/threads.h>.

* `caml_release_runtime_system()` The calling thread releases the domain lock and other OCaml resources, enabling other threads to run OCaml code in parallel with the execution of the calling thread.

* `caml_acquire_runtime_system()` The calling thread re-acquires the domain lock and other OCaml resources. It may block until no other thread in the same domain uses the OCaml run-time system.

These functions poll for pending signals by calling asynchronous callbacks (section 22.5.3) before releasing and after acquiring the lock. They can therefore execute arbitrary OCaml code including raising an asynchronous exception.

After `caml_release_runtime_system()` was called and until `caml_acquire_runtime_system()` is called, the C code must not access any OCaml data, nor call any function of the run-time system, nor call back into OCaml code. Consequently, arguments provided by OCaml to the C primitive must be copied into C data structures before calling `caml_release_runtime_system()`, and results
**@specialised always or @specialised never**

Attached to a function application, this directs the inliner likewise. This attribute at a call site overrides any other attribute that may be present on the corresponding declaration. (Note that the function will still only be specialised if there exist one or more invariant parameters whose values are known.) `@specialised` with no argument is equivalent to `@specialised always`.

**@unrolled *n***

This attribute is attached to a function application and always takes an integer argument. Each time the inliner sees the attribute it behaves as follows:

* If *n* is zero or less, nothing happens.

* Otherwise the function being called is substituted at the call site with its body having been rewritten such that any recursive calls to that function or any others in the same *mutually-recursive group* are annotated with the attribute `unrolled(n - 1)`. Inlining may continue on that body.

As such, *n* behaves as the “maximum depth of unrolling”.

A compiler warning will be emitted if it was found impossible to obey an annotation from an `@inlined` or `@specialised` attribute.

### Example showing correct placement of attributes

```python
module F (M : sig type t end) = struct
    let[@inline never] bar x =
        x * 3

    let foo x =
        (bar[@inlined]) (42 + x)
end[@inline never]

module X = F[@inlined] (struct type t = int end)
```

## 23.7 Simplification

Simplification, which is run in conjunction with inlining, propagates information (known as *approximations*) about which variables hold what values at runtime. Certain relationships between variables and symbols are also tracked: for example, some variable may be known to always hold the same value as some other variable; or perhaps some variable may be known to always hold the value pointed to by some symbol.

The propagation can help to eliminate allocations in cases such as:

```python
let f x y =
    ...
let p = x, y in
    ...
    (fst p) ... (snd p) ...
```
to be returned to OCaml must be encoded as OCaml values after `caml_acquire_runtime_system()` returns.

Example: the following C primitive invokes `rmdir` to delete a directory. The `rmdir` function can block for some time, so we choose to release the OCaml run-time system while it is running.

```c
#include <caml/memory.h>
#include <caml/threads.h>
#include <caml/unixsupport.h>

CAMLprim value stub_rmdir(value vpath)
{
    CAMLparam1(vpath);

    /* Raise Unix.Unix_error(Unix.ENOENT, ...) if the OCaml string
       contains embedded null bytes */
    caml_unix_check_path(vpath, "rmdir");

    /* Copy the string argument to a C string, allocated outside the
       OCaml heap. */
    char_os *path = caml_stat_strdup_to_os(String_val(vpath));
    /* Release the OCaml run-time system */
    caml_release_runtime_system();

    /* Delete the directory */
#ifdef _WIN32
    int ret = _wrmdir(path);
#else
    int ret = rmdir(path);
#endif

    /* Free the copy of the string, which we might as well do before
       acquiring the runtime system to benefit from parallelism. */
    caml_stat_free(path);
    /* Re-acquire the OCaml run-time system */
    caml_acquire_runtime_system();

    /* Raise Unix.Unix_error(...) if rmdir failed */
    if (ret == -1) caml_uerror("rmdir", vpath);

    /* Return to OCaml */
    CAMLreturn(Val_unit);
}
```

The macro `Caml_state` evaluates to the domain state variable, and checks in debug mode that the domain lock is held. Such a check is also placed in normal mode at key entry points of the C API; this is why calling some of the runtime functions and macros without correctly owning the domain
The projections from p may be replaced by uses of the variables x and y, potentially meaning
that p becomes unused.

The propagation performed by the simplification pass is also important for discovering which
functions flow to indirect call sites. This can enable the transformation of such call sites into direct
call sites, which makes them eligible for an inlining transformation.

Note that no information is propagated about the contents of strings, even in safe-string
mode, because it cannot yet be guaranteed that they are immutable throughout a given program.

## 23.8 Other code motion transformations

### 23.8.1 Lifting of constants

Expressions found to be constant will be lifted to symbol bindings—that is to say, they will be
statically allocated in the object file—when they evaluate to boxed values. Such constants may be
straightforward numeric constants, such as the floating-point number 42.0, or more complicated
values such as constant closures.

Lifting of constants to toplevel reduces allocation at runtime.

The compiler aims to share constants lifted to toplevel such that there are no duplicate definitions.
However if .cmx files are hidden from the compiler then maximal sharing may not be possible.

**Notes about float arrays** The following language semantics apply specifically to constant float
arrays. (By "constant float array" is meant an array consisting entirely of floating point numbers
that are known at compile time. A common case is a literal such as `[| 42.0; 43.0; |].`

* Constant float arrays at the toplevel are mutable and never shared. (That is to say, for each such definition there is a distinct symbol in the data section of the object file pointing at the array.)

* Constant float arrays not at toplevel are mutable and are created each time the expression is evaluated. This can be thought of as an operation that takes an immutable array (which in the source code has no associated name; let us call it the *initialising array*) and duplicates it into a fresh mutable array.

- If the array is of size four or less, the expression will create a fresh block and write the
  values into it one by one. There is no reference to the initialising array as a whole.

- Otherwise, the initialising array is lifted out and subject to the normal constant sharing
  procedure; creation of the array consists of bulk copying the initialising array into a fresh
  value on the OCaml heap.

### 23.8.2 Lifting of toplevel let bindings

TLEVEL LET-EXPRESSIONS MAY BE LIFTED TO SYMBOL BINDINGS TO ENSURE THAT THE CORRESPONDING BOUND
VARIABLES ARE NOT CAPTURED BY CLOSURES. IF THE DEFINING EXPRESSION OF A GIVEN BINDING IS FOUND TO BE
CONSTANT, IT IS BOUND AS SUCH (THE TECHNICAL TERM IS A *LET-SYMBOL* BINDING).

Otherwise, the symbol is bound to a (statically-allocated) *preallocated block* containing one field.
At runtime, the defining expression will be evaluated and the first field of the block filled with the
lock can result in a fatal error: `no domain lock held`. The variant `Caml_state_opt` does not perform any check but evaluates to `NULL` when the domain lock is not held. This lets you determine whether a thread belonging to a domain currently holds its domain lock, for various purposes.

Callbacks from C to OCaml must be performed while holding the domain lock to the OCaml run-time system. This is naturally the case if the callback is performed by a C primitive that did not release the run-time system. If the C primitive released the run-time system previously, or the callback is performed from other C code that was not invoked from OCaml (e.g. an event loop in a GUI application), the run-time system must be acquired before the callback and released after:

```c
 caml_acquire_runtime_system();
 /* Resolve OCaml function vfun to be invoked */
 /* Build OCaml argument varg to the callback */
 vres = callback(vfun, varg);
 /* Copy relevant parts of result vres to C data structures */
 caml_release_runtime_system();
```

Note: the `acquire` and `release` functions described above were introduced in OCaml 3.12. Older code uses the following historical names, declared in `<caml/signals.h>`:

* `caml_enter_blocking Brewster section` as an alias for `caml_release_runtime_system`

* `caml Leave blocking Brewster section` as an alias for `caml_acquire_runtime_system`

Intuition: a "blocking section" is a piece of C code that does not use the OCaml run-time system, typically a blocking input/output operation.

## 22.13 Advanced topic: interfacing with Windows Unicode APIs

This section contains some general guidelines for writing C stubs that use Windows Unicode APIs. The OCaml system under Windows can be configured at build time in one of two modes:

* **legacy mode:** All path names, environment variables, command line arguments, etc. on the OCaml side are assumed to be encoded using the current 8-bit code page of the system.

* **Unicode mode:** All path names, environment variables, command line arguments, etc. on the OCaml side are assumed to be encoded using UTF-8.

In what follows, we say that a string has the *OCaml encoding* if it is encoded in UTF-8 when in Unicode mode, in the current code page in legacy mode, or is an arbitrary string under Unix. A string has the *platform encoding* if it is encoded in UTF-16 under Windows or is an arbitrary string under Unix.

From the point of view of the writer of C stubs, the challenges of interacting with Windows Unicode APIs are twofold:

* The Windows API uses the UTF-16 encoding to support Unicode. The runtime system performs the necessary conversions so that the OCaml programmer only needs to deal with the OCaml encoding. C stubs that call Windows Unicode APIs need to use specific runtime functions to perform the necessary conversions in a compatible way.
resulting value. This *initialise-symbol* binding causes one extra indirection but ensures, by virtue of the symbol's address being known at compile time, that uses of the value are not captured by closures.

It should be noted that the blocks corresponding to *initialise-symbol* bindings are kept alive forever, by virtue of them occurring in a static table of GC roots within the object file. This extended lifetime of expressions may on occasion be surprising. If it is desired to create some non-constant value (for example when writing GC tests) that does not have this extended lifetime, then it may be created and used inside a function, with the application point of that function (perhaps at toplevel)—or indeed the function declaration itself—marked as to never be inlined. This technique prevents lifting of the definition of the value in question (assuming of course that it is not constant).

## 23.9 Unboxing transformations

The transformations in this section relate to the splitting apart of *boxed* (that is to say, non-immediate) values. They are largely intended to reduce allocation, which tends to result in a runtime performance profile with lower variance and smaller tails.

### 23.9.1 Unboxing of closure variables

This transformation is enabled unless `-no-unbox-free-vars-of-closures` is provided.

Variables that appear in closure environments may themselves be *boxed* values. As such, they may be split into further closure variables, each of which corresponds to some projection from the original closure variable(s). This transformation is called *unboxing of closure variables* or *unboxing of free variables of closures*. It is only applied when there is reasonable certainty that there are no uses of the *boxed* free variable itself within the corresponding function bodies.

**Example:** In the following code, the compiler observes that the closure returned from the function *f* contains a variable *pair* (free in the body of *f*) that may be split into two separate variables.

```pascal
let f x0 x1 =
  let pair = x0, x1 in
    Printf Acid "foo\n";
  fun y ->
    fst pair + snd pair + y
```

After some simplification one obtains:

```pascal
let f x0 x1 =
  let pair_0 = x0 in
  let pair_1 = x1 in
    Printf Acid "foo\n";
  fun y ->
    pair_0 + pair_1 + y
```

and then:
* When writing stubs that need to be compiled under both Windows and Unix, the stubs need to be written in a way that allow the necessary conversions under Windows but that also work under Unix, where typically nothing particular needs to be done to support Unicode.

The native C character type under Windows is `WCHAR`, two bytes wide, while under Unix it is `char`, one byte wide. A type `char_os` is defined in `<caml/misc.h>` that stands for the concrete C character type of each platform. Strings in the platform encoding are of type `char_os *`.

The following functions are exposed to help write compatible C stubs. To use them, you need to include both `<caml/misc.h>` and `<caml/osdeps.h>`.

* `char_os* caml_stat_strdup_to_os(const char *)` copies the argument while translating from OCaml encoding to the platform encoding. This function is typically used to convert the `char *` underlying an OCaml string before passing it to an operating system API that takes a Unicode argument. Under Unix, it is equivalent to `caml_stat_strdup`.

**Note:** For maximum backwards compatibility in Unicode mode, if the argument is not a valid UTF-8 string, this function will fall back to assuming that it is encoded in the current code page.

* `char* caml_stat_strdup_of_os(const char_os *)` copies the argument while translating from the platform encoding to the OCaml encoding. It is the inverse of `caml_stat_strdup_to_os`. This function is typically used to convert a string obtained from the operating system before passing it on to OCaml code. Under Unix, it is equivalent to `caml_stat_strdup`.

* `value caml_copy_string_of_os(char_os *)` allocates an OCaml string with contents equal to the argument string converted to the OCaml encoding. This function is essentially equivalent to `caml_stat_strdup_of_os` followed by `caml_copy_string`, except that it avoids the allocation of the intermediate string returned by `caml_stat_strdup_of_os`. Under Unix, it is equivalent to `caml_copy_string`.

**Note:** The strings returned by `caml_stat_strdup_to_os` and `caml_stat_strdup_of_os` are allocated using `caml_stat_alloc`, so they need to be deallocated using `caml_stat_free` when they are no longer needed.

**Example** We want to bind the function `getenv` in a way that works both under Unix and Windows. Under Unix this function has the prototype:

```c
char *getenv(const char *);
```

While the Unicode version under Windows has the prototype:

```c
WCHAR *wgetenv(const WCHAR *);
```

In terms of `char_os`, both functions take an argument of type `char_os *` and return a result of the same type. We begin by choosing the right implementation of the function to bind:
```h
let f x0 x1 =
    Printfprintf "foo\n";
fun y ->
    x0 + x1 + y
```

The allocation of the pair has been eliminated.

This transformation does not operate if it would cause the closure to contain more than twice as many closure variables as it did beforehand.

### 23.9.2 Unboxing of specialised arguments

This transformation is enabled unless `-no-unbox-specialised-args` is provided.

It may become the case during compilation that one or more invariant arguments to a function become specialised to a particular value. When such values are themselves boxed the corresponding specialised arguments may be split into more specialised arguments corresponding to the projections out of the boxed value that occur within the function body. This transformation is called *unboxing of specialised arguments*. It is only applied when there is reasonable certainty that the boxed argument itself is unused within the function.

If the function in question is involved in a recursive group then unboxing of specialised arguments may be immediately replicated across the group based on the dataflow between invariant arguments.

**Example:** Having been given the following code, the compiler will inline `loop` into `f`, and then observe `inv` being invariant and always the pair formed by adding 42 and 43 to the argument `x` of the function `f`.

```h
let rec loop inv xs =
    match xs with
    | [] -> fst inv + snd inv
    | x::xs -> x + loop2 xs inv
and loop2 ys inv =
    match ys with
    | [] -> 4
    | y::ys -> y - loop inv ys
```

```h
let f x =
    Printfprintf "%d\n" (loop (x + 42, x + 43) [1; 2; 3])
```

Since the functions have sufficiently few arguments, more specialised arguments will be added. After some simplification one obtains:

```h
let f x =
    let rec loop' xs inv_0 inv_1 =
        match xs with
        | [] -> inv_0 + inv_1
        | x::xs -> x + loop2' xs inv_0 inv_1
and loop2' ys inv_0 inv_1 =
    match ys with
```
```c
#ifdef _WIN32
#define getenv_os _wgetenv
#else
#define getenv_os getenv
#endif
```

The rest of the binding is the same for both platforms:

```c
#include <caml/mlvalues.h>
#include <caml/misc.h>
#include <caml/alloc.h>
#include <caml/fail.h>
#include <caml/osdeps.h>
#include <stdlib.h>

CAMLprim value stub_getenv(value var_name)
{
    CAMLparam1(var_name);
    CAMLlocal1(var_value);
    char_os *var_name_os, *var_value_os;

    var_name_os = caml_stat_strdup_to_os(String_val(var_name));
    var_value_os = getenv_os(var_name_os);
    caml_stat_free(var_name_os);

    if (var_value_os == NULL)
        camlOMPraise_not_found();

    var_value = caml_copy_string_of_os(var_value_os);

    CAMLreturn(var_value);
}
```

## 22.14 Building mixed C/OCaml libraries: ocamlmklib

The ocamlmklib command facilitates the construction of libraries containing both OCaml code and C code, and usable both in static linking and dynamic linking modes. This command is available under Windows since Objective Caml 3.11 and under other operating systems since Objective Caml 3.03.

The ocamlmklib command takes three kinds of arguments:

* OCaml source files and object files (`.cmo`, `.cmx`, `.ml`) comprising the OCaml part of the library;

* C object files (`.o`, `.a`, respectively, `.obj`, `.lib`) comprising the C part of the library;

* Support libraries for the C part (`-llib`).
```python
| [] -> 4
| y::ys -> y - loop' ys inv_0 inv_1
in
ensis
    printf "%d\n" (loop' [1; 2; 3] (x + 42) (x + 43))
```

The allocation of the pair within `f` has been removed. (Since the two closures for `loop'` and `loop2'` are constant they will also be lifted to toplevel with no runtime allocation penalty. This would also happen without having run the transformation to unbox specialise arguments.)

The transformation to unbox specialised arguments never introduces extra allocation.

The transformation will not unbox arguments if it would result in the original function having sufficiently many arguments so as to inhibit tail-call optimisation.

The transformation is implemented by creating a wrapper function that accepts the original arguments. Meanwhile, the original function is renamed and extra arguments are added corresponding to the unboxed specialised arguments; this new function is called from the wrapper. The wrapper will then be inlined at direct call sites. Indeed, all call sites will be direct unless `-unbox-closures` is being used, since they will have been generated by the compiler when originally specialising the function. (In the case of `-unbox-closures` other functions may appear with specialised arguments; in this case there may be indirect calls and these will incur a small penalty owing to having to bounce through the wrapper. The technique of *direct call surrogates* used for `-unbox-closures` is not used by the transformation to unbox specialised arguments.)

### 23.9.3 Unboxing of closures

This transformation is *not* enabled by default. It may be enabled using the `-unbox-closures` flag.

The transformation replaces closure variables by specialised arguments. The aim is to cause more closures to become closed. It is particularly applicable, as a means of reducing allocation, where the function concerned cannot be inlined or specialised. For example, some non-recursive function might be too large to inline; or some recursive function might offer no opportunities for specialisation perhaps because its only argument is one of type `unit`.

At present there may be a small penalty in terms of actual runtime performance when this transformation is enabled, although more stable performance may be obtained due to reduced allocation. It is recommended that developers experiment to determine whether the option is beneficial for their code. (It is expected that in the future it will be possible for the performance degradation to be removed.)

**Simple example:** In the following code (which might typically occur when `g` is too large to inline) the value of `x` would usually be communicated to the application of the `+` function via the closure of `g`.

```python
let f x =
let g y =
    x + y
in
(g [@inlined never]) 42
```
It generates the following outputs:

* An OCaml bytecode library `.cma` incorporating the `.cmo` and `.ml` OCaml files given as arguments, and automatically referencing the C library generated with the C object files.

* An OCaml native-code library `.cmxa` incorporating the `.cmx` and `.ml` OCaml files given as arguments, and automatically referencing the C library generated with the C object files.

* If dynamic linking is supported on the target platform, a `.so` (respectively, `.dll`) shared library built from the C object files given as arguments, and automatically referencing the support libraries.

* A C static library `.a` (respectively, `.lib`) built from the C object files.

In addition, the following options are recognized:

**-cclib, -ccopt, -I, -linkall**

These options are passed as is to `ocamlc` or `ocamlopt`. See the documentation of these commands.

**-rpath, -R, -Wl, -rpath, -Wl, -R**

These options are passed as is to the C compiler. Refer to the documentation of the C compiler.

**-custom**

Force the construction of a statically linked library only, even if dynamic linking is supported.

**-failsafe**

Fall back to building a statically linked library if a problem occurs while building the shared library (e.g. some of the support libraries are not available as shared libraries).

**-Ldir**

Add `dir` to the search path for support libraries (`-ldir`).

**-ocamlc cmd**

Use `cmd` instead of `ocamlc` to call the bytecode compiler.

**-ocamlopt cmd**

Use `cmd` instead of `ocamlopt` to call the native-code compiler.

**-o output**

Set the name of the generated OCaml library. `ocamlmklib` will generate `output.cma` and/or `output.cmxa`. If not specified, defaults to `a`.

**-oc outputc**

Set the name of the generated C library. `ocamlmklib` will generate `liboutputc.so` (if shared libraries are supported) and `liboutputc.a`. If not specified, defaults to the output name given with `-o`.
Unboxing of the closure causes the value for `x` inside `g` to be passed as an argument to `g` rather than through its closure. This means that the closure of `g` becomes constant and may be lifted to toplevel, eliminating the runtime allocation.

The transformation is implemented by adding a new wrapper function in the manner of that used when unboxing specialised arguments. The closure variables are still free in the wrapper, but the intention is that when the wrapper is inlined at direct call sites, the relevant values are passed directly to the main function via the new specialised arguments.

Adding such a wrapper will penalise indirect calls to the function (which might exist in arbitrary places; remember that this transformation is not for example applied only on functions the compiler has produced as a result of specialisation) since such calls will bounce through the wrapper. To mitigate this, if a function is small enough when weighed up against the number of free variables being removed, it will be duplicated by the transformation to obtain two versions: the original (used for indirect calls, since we can do no better) and the wrapper/rewritten function pair as described in the previous paragraph. The wrapper/rewritten function pair will only be used at direct call sites of the function. (The wrapper in this case is known as a *direct call surrogate*, since it takes the place of another function—the unchanged version used for indirect calls—at direct call sites.)

The `-unbox-closures-factor` command line flag, which takes an integer, may be used to adjust the point at which a function is deemed large enough to be ineligible for duplication. The benefit of duplication is scaled by the integer before being evaluated against the size.

**Harder example:** In the following code, there are two closure variables that would typically cause closure allocations. One is called `fv` and occurs inside the function `baz`; the other is called `z` and occurs inside the function `bar`. In this toy (yet sophisticated) example we again use an attribute to simulate the typical situation where the first argument of `baz` is too large to inline.

```hsharp
let foo c =
    let rec bar zs fv =
        match zs with
        | [] -> []
        | z::zs ->
            let rec baz f = function
              | [] -> []
              | a::l -> let r = fv + ((f [@inlined never]) a) in r :: baz f l
            in
              (map2 (fun y -> z + y) [z; 2; 3; 4]) @ bar zs fv
        in
    Printf printf "%d" (List.length (bar [1; 2; 3; 4] c))
```

The code resulting from applying `-O3 -unbox-closures` to this code passes the free variables via function arguments in order to eliminate all closure allocation in this example (aside from any that might be performed inside `printf`).
**Example** Consider an OCaml interface to the standard libz C library for reading and writing compressed files. Assume this library resides in `/usr/local/zlib`. This interface is composed of an OCaml part `zip.cmo/zip.cmx` and a C part `zipstubs.o` containing the stub code around the libz entry points. The following command builds the OCaml libraries `zip.cma` and `zip.cmxa`, as well as the companion C libraries `dllzip.so` and `libzip.a`:

```
ocamlmklib -o zip zip.cmo zip.cmx zipstubs.o -lz -L/usr/local/zlib
```

If shared libraries are supported, this performs the following commands:

```
ocamlc -a -o zip.cma zip.cmo -dllib -lzip \
       -cclib -lzip -cclib -lz -ccopt -L/usr/local/zlib
ocamlopt -a -o zip.cmxa zip.cmx -cclib -lzip \
           -cclib -lzip -cclib -lz -ccopt -L/usr/local/zlib
gcc -shared -o dllzip.so zipstubs.o -lz -L/usr/local/zlib
ar rc libzip.a zipstubs.o
```

Note: This example is on a Unix system. The exact command lines may be different on other systems.

If shared libraries are not supported, the following commands are performed instead:

```
ocamlc -a -custom -o zip.cma zip.cmo -cclib -lzip \
       -cclib -lz -ccopt -L/usr/local/zlib
ocamlopt -a -o zip.cmxa zip.cmx -lzip \
           -cclib -lz -ccopt -L/usr/local/zlib
ar rc libzip.a zipstubs.o
```

Instead of building simultaneously the bytecode library, the native-code library and the C libraries, `ocamlmklib` can be called three times to build each separately. Thus,

```
ocamlmklib -o zip zip.cmo -lz -L/usr/local/zlib
builds the bytecode library zip.cma, and

ocamlmklib -o zip zip.cmx -lz -L/usr/local/zlib
builds the native-code library zip.cmxa, and

ocamlmklib -o zip zipstubs.o -lz -L/usr/local/zlib
builds the C libraries dllzip.so and libzip.a. Notice that the support libraries (-lz) and the corresponding options (-L/usr/local/zlib) must be given on all three invocations of ocamlmklib, because they are needed at different times depending on whether shared libraries are supported.
```

### 22.15 Cautionary words: the internal runtime API

Not all headers available in the `caml/` directory were described in previous sections. All those unmentioned headers are part of the internal runtime API, for which there is no stability guarantee. If you really need access to this internal runtime API, this section provides some guidelines that may help you to write code that might not break on every new version of OCaml.
## 23.10 Removal of unused code and values

### 23.10.1 Removal of redundant let expressions

The simplification pass removes unused `let` bindings so long as their corresponding defining expressions have “no effects”. See the section “Treatment of effects” below for the precise definition of this term.

### 23.10.2 Removal of redundant program constructs

This transformation is analogous to the removal of `let`-expressions whose defining expressions have no effects. It operates instead on symbol bindings, removing those that have no effects.

### 23.10.3 Removal of unused arguments

This transformation is only enabled by default for specialised arguments. It may be enabled for all arguments using the `-remove-unused-arguments` flag.

The pass analyses functions to determine which arguments are unused. Removal is effected by creating a wrapper function, which will be inlined at every direct call site, that accepts the original arguments and then discards the unused ones before calling the original function. As a consequence, this transformation may be detrimental if the original function is usually indirectly called, since such calls will now bounce through the wrapper. (The technique of *direct call surrogates* used to reduce this penalty during unboxing of closure variables (see above) does not yet apply to the pass that removes unused arguments.)

### 23.10.4 Removal of unused closure variables

This transformation performs an analysis across the whole compilation unit to determine whether there exist closure variables that are never used. Such closure variables are then eliminated. (Note that this has to be a whole-unit analysis because a projection of a closure variable from some particular closure may have propagated to an arbitrary location within the code due to inlining.)

## 23.11 Other code transformations

### 23.11.1 Transformation of non-escaping references into mutable variables

Lambda performs a simple analysis analogous to that performed elsewhere in the compiler that can transform `refs` into mutable variables that may then be held in registers (or on the stack as appropriate) rather than being allocated on the OCaml heap. This only happens so long as the reference concerned can be shown to not escape from its defining scope.

### 23.11.2 Substitution of closure variables for specialised arguments

This transformation discovers closure variables that are known to be equal to specialised arguments. Such closure variables are replaced by the specialised arguments; the closure variables may then be removed by the “removal of unused closure variables” pass (see below).