/* Bench-only bump allocator stub.
 *
 * Used by `ail build --alloc=bump` as the bench-floor allocator paired
 * with the canonical RC runtime. The whole runtime is a 256 MB
 * statically-allocated arena and a single bump pointer; there is no
 * `free`, no scan, no anything. If the workload exceeds 256 MB we
 * abort — this is bench code, the right response to overflow is to
 * notice and pick a smaller workload.
 *
 * The function signature `void *bump_malloc(size_t)` is the bench-floor
 * allocator interface; codegen lowers ADT/lambda/closure-pair allocation
 * sites to `call ptr @bump_malloc` when the bench harness selects
 * `--alloc=bump`.
 */

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#define ARENA_BYTES (256ul * 1024ul * 1024ul)

static uint8_t arena[ARENA_BYTES];
static size_t cursor = 0;

void *bump_malloc(size_t n) {
    /* Align bump pointer up to 8 bytes — AILang's allocations are all
     * 8-byte aligned (tag + 8-byte fields, env pointers, closure pairs
     * of two `ptr`s). 8-byte alignment matches the ADT box layout. */
    size_t aligned = (cursor + 7ul) & ~((size_t)7ul);
    if (aligned + n > ARENA_BYTES) {
        fprintf(stderr,
                "bump_malloc: arena exhausted (cursor=%zu, requested=%zu, arena=%zu)\n",
                aligned, n, (size_t)ARENA_BYTES);
        abort();
    }
    void *p = (void *)(arena + aligned);
    cursor = aligned + n;
    return p;
}
