Allocator selection is instruction selection.
Mica’s intermediate language never names malloc. It emits allocator
intrinsics, and which implementation those bind to is decided when you link.
Code generation is byte-identical across both deployment classes. The same object code, the same instruction schedule, the same register assignment — only the archive it links against differs. This is measured, not asserted: the generated assembly and object file match by SHA-256 across hosted, fixed-arena, and a fixed-arena built with a different byte budget.
The two classes
Hosted — libc calloc/free underneath. The point of keeping this is
tooling: Valgrind and AddressSanitizer keep working, because to them a Mica
program allocates the way a C program does.
Fixed-arena — a statically budgeted bump allocator with no OS heap at all,
selected as --memory-class fixed-arena and optionally sized
(fixed-arena=<bytes>). This is the freestanding class: the program’s entire
memory footprint is decided before it runs. Changing the budget does not change
one instruction of the program; it changes only a generated data-only object
holding the arena reservation.
Regions are scheduled, not selected
The region allocator is not a deployment class, and there is no flag for it.
Within whichever class you link, the compiler picks the allocator per allocation
site from the lifetime it proved: an owner-bound site (new T until F) gets a
region, with bulk reclaim when the owner exits; manual and transferred sites get
per-cell allocation. Both appear in the same binary, and regions work inside the
fixed-arena class too.
The lineage is the region calculus of Tofte and Talpin, with one deliberate
difference: the region is chosen by the compiler from a proven lifetime and
named by the programmer (until F), rather than inferred invisibly. You can see
which allocations landed in which region, because the compiler tells you — one
line per site, naming the lifetime class and the allocator it selected.
Why this shape
A systems language usually forces the deployment decision into the source. Code
written against a pool allocator is not the code you would write against
malloc, and porting between them is a rewrite.
Here it is a link flag. One source tree serves a Linux server, an
allocation-bound batch job that benefits from bulk reclaim, and a statically
budgeted embedded target — with no #ifdef, no allocator abstraction layer in
your own code, and no divergent test corpus, because the generated code is the
same in every case.
The seam is a genuine plug-in rather than an internal switch: a third-party archive that honours the symbol contract links and runs with no compiler change.