shithub: scc

Download patch

ref: 0d6543afdd79d7e9abbc09b266bb592d760ebf59
parent: ab2e4ae3a9cf10339b0340865bc12aa58a90fa4f
author: Roberto E. Vargas Caballero <[email protected]>
date: Wed Sep 13 12:19:29 EDT 2017

[lib] Add generic arena allocator

At this moment we are using a specific arena allocator in cc2 for nodes,
but there are other places in the code where an arena allocator can be
used, so it is a good idea to have a generic implementation.

--- a/cc2/target/qbe/code.c
+++ b/cc2/target/qbe/code.c
@@ -13,7 +13,7 @@
 
 static void binary(void), unary(void), store(void), jmp(void), ret(void),
             branch(void), call(void), ecall(void), param(void),
-            alloc(void), form2local(void), ldir(void), vastart(void),
+            asalloc(void), form2local(void), ldir(void), vastart(void),
             vaarg(void);
 
 static struct opdata {
@@ -146,7 +146,7 @@
 	[ASCALLEX] = {.fun = ecall, .txt = ", ...)"},
 	[ASPAR] = {.fun = param, .txt = "%s %s, "},
 	[ASPARE] = {.fun = param, .txt = "%s %s"},
-	[ASALLOC] = {.fun = alloc},
+	[ASALLOC] = {.fun = asalloc},
 	[ASFORM] = {.fun = form2local},
 
 	[ASVSTAR] = {.fun = vastart},
@@ -516,7 +516,7 @@
 }
 
 static void
-alloc(void)
+asalloc(void)
 {
 	Symbol *sym = pc->to.u.sym;
 	Type *tp = &sym->type;
--- a/inc/scc.h
+++ b/inc/scc.h
@@ -19,6 +19,20 @@
 	unsigned n;
 };
 
+typedef struct alloc Alloc;
+
+struct arena;
+union hdr;
+
+struct alloc {
+	size_t size;
+	size_t nmemb;
+	size_t padding;
+	struct arena *arena;
+	union hdr *freep;
+};
+
+
 extern void die(const char *fmt, ...);
 extern void dbg(const char *fmt, ...);
 extern void newitem(struct items *items, char *item);
@@ -26,3 +40,7 @@
 extern void *xcalloc(size_t nmemb, size_t size);
 extern char *xstrdup(const char *s);
 extern void *xrealloc(void *buff, register size_t size);
+extern Alloc *alloc(size_t size, size_t nmemb);
+extern void dealloc(Alloc *allocp);
+extern void *new(Alloc *allocp);
+extern void delete(Alloc *allocp, void *p);
--- /dev/null
+++ b/lib/scc/alloc.c
@@ -1,0 +1,104 @@
+static char sccsid[] = "@(#) ./lib/alloc.c";
+#include <stdlib.h>
+#include "../../inc/scc.h"
+
+/*
+ * This is the most pedantic piece of code that I have written
+ * in my life. The next union is used to enforce the aligmnet
+ * of the address returned by new(). A union has the aligment
+ * of the field with the biggest aligment. This union has all
+ * the types that we use in scc, and we round all the address
+ * to the aligment of this struct, so we can be sure that any
+ * pointer using that address will be safe. The field ap is
+ * in the union to be sure that struct pointers are included
+ * in the list, although they will have the same aligment or
+ * smaller than void *, but I wanted to be pedantic.
+ */
+union hdr {
+	union hdr *next;
+	struct arena *ap;
+	char c;
+	unsigned char uc;
+	int i;
+	short s;
+	long l;
+	long long ll;
+	float f;
+	double d;
+	long double ld;
+	void *vp;
+};
+
+struct arena {
+	struct arena *next;
+	union hdr *array;
+};
+
+static void
+newarena(Alloc *allocp)
+{
+	struct arena *ap;
+	union hdr *bp, *lim;
+	size_t unit, n = allocp->nmemb;
+
+	unit = (allocp->size-1) / sizeof(union hdr) + 1;
+	ap = xmalloc(sizeof(struct arena));
+	ap->array = xmalloc(unit * sizeof(union hdr) * n);
+
+	bp = ap->array;
+	for (lim = &bp[unit * (n-1)]; bp < lim; bp += unit)
+		bp->next = bp + unit;
+	bp->next = NULL;
+
+	ap->next = allocp->arena;
+	allocp->arena = ap;
+	allocp->freep = ap->array;
+}
+
+Alloc *
+alloc(size_t size, size_t nmemb)
+{
+	Alloc *allocp = xmalloc(sizeof(*allocp));
+
+	allocp->size = size;
+	allocp->nmemb = nmemb;
+	allocp->arena = NULL;
+	allocp->freep = NULL;
+
+	return allocp;
+}
+
+void
+dealloc(Alloc *allocp)
+{
+	struct arena *ap, *next;
+
+	for (ap = allocp->arena; ap; ap = next) {
+		next = ap->next;
+		free(ap->array);
+		free(ap);
+	}
+	free(allocp);
+}
+
+void *
+new(Alloc *allocp)
+{
+	union hdr *bp;
+
+	if (!allocp->freep)
+		newarena(allocp);
+	bp = allocp->freep;
+	allocp->freep = bp->next;
+
+	return bp;
+}
+
+void
+delete(Alloc *allocp, void *p)
+{
+	union hdr *bp = p;
+
+	bp->next = allocp->freep;
+	allocp->freep = bp;
+}
--- a/lib/scc/libdep.mk
+++ b/lib/scc/libdep.mk
@@ -5,3 +5,4 @@
           $(LIBDIR)/xmalloc.o \
           $(LIBDIR)/xrealloc.o \
           $(LIBDIR)/xstrdup.o \
+          $(LIBDIR)/alloc.o \