sic

The sic programming language, compiler and tools (WIP)
Log | Files | Refs

commit d8295a48cf792eafc3d1fb12c80b2946bfa66427
parent 23be80cdbfceac075f9bc4f8744ec2f78b59fa67
Author: citbl <citbl@citbl.org>
Date:   Wed, 13 May 2026 22:25:06 +1000

basic arena wip

Diffstat:
Asrc/arena.c | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/arena.h | 17+++++++++++++++++
2 files changed, 121 insertions(+), 0 deletions(-)

diff --git a/src/arena.c b/src/arena.c @@ -0,0 +1,104 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +#include "arena.h" +#include "check.h" + +// not thread safe + +struct Arena { + uint8_t* buf; + size_t cap; + size_t pos; +}; + +Arena* arena_init(size_t bytes) +{ + Arena* a; + if (!bytes || bytes == 0) { + bytes = 1024; + } + a = malloc(sizeof(Arena)); + if (!a) { + fprintf(stderr, "arena_init failed to alloc\n"); + return NULL; + } + a->buf = malloc(bytes); + if (!a->buf) { + free(a); + fprintf(stderr, "arena_init: failed to allocate buffer\n"); + return NULL; + } + a->cap = bytes; + a->pos = 0; + + return a; +} + +static size_t align_to(size_t offset, size_t align) +{ + // align to a power of 2 + return (offset + align - 1) & ~(align - 1); +} + +void* arena_alloc(Arena* a, size_t size, size_t align) +{ + size_t pos, new_cap; + void* ptr; + uint8_t* p; + + if (!a) { + fprintf(stderr, "arena: no arena given to alloc to\n"); + return NULL; + } + if (!size) { + fprintf(stderr, "arena: no arena size given to alloc to\n"); + return NULL; + } + if (!align) { + fprintf(stderr, "arena: no arena alignment given to alloc to\n"); + return NULL; + } + if ((align & (align - 1)) != 0) { /* not power of two */ + fprintf(stderr, "arena: alignment must be a power of two\n"); + return NULL; + } + + pos = align_to(a->pos, align); + if (SIZE_MAX - pos < size) { + fprintf(stderr, "arena_alloc: too large for available memory\n"); + free(a->buf); + return NULL; + } + if (pos + size > a->cap) { + new_cap = a->cap == 0 ? 1024 : a->cap * 2; + check(new_cap <= a->cap || new_cap > SIZE_MAX / sizeof(uint8_t), "arena: could not reallocate arena, underflow or overflow\n"); + p = realloc(a->buf, new_cap); + if (!p) { + fprintf(stderr, "arena: could not reallocate double its size!\n"); + free(a->buf); + return NULL; + } + a->buf = p; + a->cap = new_cap; + } + + ptr = a->buf + pos; + a->pos = pos + size; + return (void*)ptr; +} + +void arena_reset(Arena* a) +{ + if (!a) return; + a->pos = 0; +} + +void arena_destroy(Arena* a) +{ + if (!a) return; + free(a->buf); + free(a); +} + diff --git a/src/arena.h b/src/arena.h @@ -0,0 +1,17 @@ +#pragma once + +#include <stddef.h> + +#define ARENA_ALLOC(arena, type) \ + ((type*)arena_alloc((arena), sizeof(type), alignof(type))) + +typedef struct Arena Arena; + +Arena* arena_init(size_t bytes); + +void* arena_alloc(Arena*, size_t size, size_t align); + +void arena_reset(Arena*); + +void arena_destroy(Arena*); +