summaryrefslogtreecommitdiff
path: root/src/core/allocator.c
diff options
context:
space:
mode:
authorLinnnus <[email protected]>2025-04-08 01:07:22 +0000
committerLinnnus <[email protected]>2025-04-08 01:07:34 +0000
commit8dd0c4f27aae02dd60f029db4cf03f9902cba26f (patch)
tree829c4bc0917f6615c55ae61d49932179c038c1e5 /src/core/allocator.c
feat: Initial commit
At this point we have some allocation routines but no work on the actual language has been done.
Diffstat (limited to 'src/core/allocator.c')
-rw-r--r--src/core/allocator.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/core/allocator.c b/src/core/allocator.c
new file mode 100644
index 0000000..5444b39
--- /dev/null
+++ b/src/core/allocator.c
@@ -0,0 +1,87 @@
+#include "allocator.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <stddef.h>
+
+#define DEFAULT_ALIGNMENT ((size_t)_Alignof(max_align_t))
+
+void *sand_allocate_aligned(SandAllocator *a, size_t size, size_t alignment) {
+ assert(a != NULL);
+ assert(size > 0);
+ assert(alignment > 0);
+ void *ptr = a->allocate(size, alignment, a->user_data);
+ assert(ptr == NULL || sand_pointer_is_aligned(ptr, alignment));
+ return ptr;
+}
+
+void *sand_allocate(SandAllocator *a, size_t size) {
+ return sand_allocate_aligned(a, size, DEFAULT_ALIGNMENT);
+}
+
+void *sand_reallocate_aligned(SandAllocator *a, void *old_ptr, size_t old_size, size_t new_size, size_t alignment) {
+ assert(a != NULL);
+ assert(old_ptr != NULL);
+ assert(old_size > 0);
+ assert(new_size > 0);
+ assert(alignment > 0);
+
+ if (a->reallocate != NULL) {
+ void *new_ptr = a->reallocate(old_ptr, old_size, new_size, alignment, a->user_data);
+ assert(sand_pointer_is_aligned(new_ptr, alignment));
+ return new_ptr;
+ } else {
+ void *new_ptr = a->allocate(new_size, alignment, a->user_data);
+ if (new_ptr == NULL) {
+ return NULL; // Note that we HAVEN'T freed `old_ptr`!
+ }
+ assert(sand_pointer_is_aligned(new_ptr, alignment));
+ memmove(new_ptr, old_ptr, old_size); // Can't know if they overlap.
+ a->deallocate(old_ptr, old_size, a->user_data);
+ return new_ptr;
+ }
+}
+
+void *sand_reallocate(SandAllocator *a, void *old_ptr, size_t old_size, size_t new_size) {
+ return sand_reallocate_aligned(a, old_ptr, old_size, new_size, DEFAULT_ALIGNMENT);
+}
+
+void sand_deallocate(SandAllocator *a, void *old_ptr, size_t old_size) {
+ assert(a != NULL);
+ assert(old_ptr != NULL);
+ assert(old_size > 0);
+
+ if (old_ptr == NULL) {
+ return;
+ }
+ a->deallocate(old_ptr, old_size, a->user_data);
+}
+
+bool sand_is_valid_alignment(size_t alignment) {
+ // Only powers of two are allowed as alignments for simplicity.
+ return alignment % 2 == 0;
+}
+
+void *sand_align_pointer_forward(void *ptr, size_t alignment) {
+ intptr_t p = (intptr_t)ptr;
+ intptr_t a = alignment;
+ intptr_t ap = ((p + a - 1) & ~(a - 1));
+ void *result = (void *)ap;
+ assert(sand_pointer_is_aligned(result, alignment));
+ return result;
+}
+
+size_t sand_align_size_forward(size_t n, size_t alignment) {
+ size_t result = ((n + alignment - 1) & ~(alignment - 1));
+ assert(sand_size_is_aligned(result, alignment));
+ return result;
+}
+
+bool sand_pointer_is_aligned(void *pointer, size_t alignment) {
+ return ((uintptr_t)pointer & (alignment - 1)) == 0;
+}
+
+bool sand_size_is_aligned(size_t n, size_t alignment) {
+ return (n & (alignment - 1)) == 0;
+}