aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-06-23 18:17:56 +0200
committerThomas Voss <mail@thomasvoss.com> 2024-06-23 18:17:56 +0200
commite5e3724046655286bf04d21b6dbdd58f33375ad9 (patch)
tree883f7a969ebf326f65acdd18a64302a7f86d1dc7 /src
parente4d068f1229df9a64bd37dd4a4fd0d61bad085bb (diff)
Implement a temporary allocator
Diffstat (limited to 'src')
-rw-r--r--src/alloc.h14
-rw-r--r--src/codegen.c18
-rw-r--r--src/scratch.c59
3 files changed, 80 insertions, 11 deletions
diff --git a/src/alloc.h b/src/alloc.h
index 2c67fb7..79d7c0b 100644
--- a/src/alloc.h
+++ b/src/alloc.h
@@ -7,12 +7,26 @@
#include "common.h"
typedef struct _arena *arena_t;
+typedef struct {
+ void *p;
+ size_t sz;
+} scratch_t;
/* Allocate a buffer of NMEMB elements of size SIZE. If PTR is non-null then
reallocate the buffer it points to. Aborts on out-of-memory or overflow. */
void *bufalloc(void *ptr, size_t nmemb, size_t size)
__attribute__((returns_nonnull, warn_unused_result, alloc_size(2, 3)));
+/* Alloc a buffer of NMEMB elements of size SIZE for one time use. Each
+ time this function is invoked previous allocations are overwritten. */
+void *tmpalloc(scratch_t *s, size_t nmemb, size_t size)
+ __attribute__((returns_nonnull, warn_unused_result, nonnull,
+ alloc_size(2, 3)));
+
+/* Reallocate all memory associated with S */
+void tmpfree(scratch_t *s)
+ __attribute__((nonnull));
+
/* Allocate a buffer of NMEMB elements of size SIZE with alignment ALIGN using
the arena-allocator A. */
void *arena_alloc(arena_t *a, size_t nmemb, size_t size, size_t align)
diff --git a/src/codegen.c b/src/codegen.c
index 08f5ab5..1431693 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -21,6 +21,7 @@
have easy access to everything */
struct cgctx {
arena_t a;
+ scratch_t *s;
LLVMContextRef ctx;
LLVMModuleRef mod;
LLVMBuilderRef bob;
@@ -43,6 +44,7 @@ codegen(const char *file, mpq_t *folds, scope_t *scps, type_t *types,
struct cgctx ctx;
ctx.a = NULL;
+ ctx.s = &(scratch_t){0};
ctx.namespace.p = NULL;
ctx.ctx = LLVMContextCreate();
ctx.mod = LLVMModuleCreateWithNameInContext("oryx", ctx.ctx);
@@ -54,6 +56,7 @@ codegen(const char *file, mpq_t *folds, scope_t *scps, type_t *types,
codegenast(ctx, folds, types, ast, aux, toks);
arena_free(&ctx.a);
+ tmpfree(ctx.s);
LLVMDisposeBuilder(ctx.bob);
@@ -188,12 +191,9 @@ codegendecl(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, aux_t aux,
strview_t sv = toks.strs[ast.lexemes[i]];
/* TODO: Namespace the name */
- /* TODO: Temporary allocator */
- char *name = bufalloc(NULL, sv.len + 1, 1);
+ char *name = tmpalloc(ctx.s, sv.len + 1, 1);
svtocstr(name, sv);
- i = codegenfunc(ctx, folds, types, ast, aux, toks, p.rhs, name);
- free(name);
- return i;
+ return codegenfunc(ctx, folds, types, ast, aux, toks, p.rhs, name);
}
assert(ast.kinds[i] == ASTDECL);
@@ -201,11 +201,9 @@ codegendecl(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, aux_t aux,
if (!types[i].isfloat && aux.buf[p.lhs].decl.isstatic) {
strview_t sv = toks.strs[ast.lexemes[i]];
/* TODO: Namespace the name */
- /* TODO: Temporary allocator */
- char *name = bufalloc(NULL, sv.len + 1, 1);
+ char *name = tmpalloc(ctx.s, sv.len + 1, 1);
LLVMTypeRef t = type2llvm(ctx, types[i]);
LLVMValueRef globl = LLVMAddGlobal(ctx.mod, t, svtocstr(name, sv));
- free(name);
LLVMValueRef v;
i = codegentypedexpr(ctx, folds, types, ast, aux, toks, p.rhs, types[i], &v);
@@ -216,12 +214,10 @@ codegendecl(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, aux_t aux,
if (!types[i].isfloat /* && !aux.buf[p.lhs].decl.isstatic */) {
strview_t sv = toks.strs[ast.lexemes[i]];
/* TODO: Namespace the name */
- /* TODO: Temporary allocator */
- char *name = bufalloc(NULL, sv.len + 1, 1);
+ char *name = tmpalloc(ctx.s, sv.len + 1, 1);
LLVMTypeRef t = type2llvm(ctx, types[i]);
LLVMValueRef var, val;
var = LLVMBuildAlloca(ctx.bob, t, svtocstr(name, sv));
- free(name);
i = codegentypedexpr(ctx, folds, types, ast, aux, toks, p.rhs, types[i], &val);
LLVMBuildStore(ctx.bob, val, var);
return i;
diff --git a/src/scratch.c b/src/scratch.c
new file mode 100644
index 0000000..ae48ff6
--- /dev/null
+++ b/src/scratch.c
@@ -0,0 +1,59 @@
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <stdint.h>
+
+#include "alloc.h"
+#include "common.h"
+#include "errors.h"
+
+/* TODO: Support malloc() backend for systems without MAP_ANON */
+#ifndef MAP_ANON
+# error "System not supported (missing MAP_ANON)"
+#endif
+
+#if DEBUG
+# define TMP_DFLT_BUFSZ (8)
+#else /* Probably super overkill, but that’s fine */
+# define TMP_DFLT_BUFSZ (1 * 1024)
+#endif
+
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+
+void *
+tmpalloc(scratch_t *s, size_t nmemb, size_t size)
+{
+ if (unlikely(size > SIZE_MAX / nmemb)) {
+ errno = ENOMEM;
+ err("%s:", __func__);
+ }
+ size *= nmemb;
+
+ if (s->p == NULL) {
+#if !__linux__
+do_mmap:
+#endif
+ s->sz = MAX(size, TMP_DFLT_BUFSZ);
+ s->p = mmap(s->p, s->sz, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON, -1, 0);
+ if (s->p == MAP_FAILED)
+ err("mmap:");
+ } else if (size > s->sz) {
+#if __linux__
+ if ((s->p = mremap(s->p, s->sz, size, MREMAP_MAYMOVE)) == MAP_FAILED)
+ err("mremap:");
+ s->sz = size;
+#else
+ munmap(s->p, s->sz);
+ goto do_mmap;
+#endif
+ }
+
+ return s->p;
+}
+
+void
+tmpfree(scratch_t *s)
+{
+ munmap(s->p, s->sz);
+}