${BUILDDIR}/eval.o: src/eval.c src/ccera.h src/jmp.h src/defer.h src/framealloc.h \
src/align.h src/stacktrack.h src/memutils.h src/panic.h src/value.h \
src/value_get.h src/value_types.h src/value_new.h src/arith.h \
- src/arc.h src/atomic.h src/builtin_register.h
+ src/arc.h src/atomic.h src/builtin_register.h src/execalloc.h \
+ src/miniobj.h
+${BUILDDIR}/execalloc.o: src/execalloc.c src/panic.h src/jmp.h
${BUILDDIR}/framealloc.o: src/framealloc.c src/framealloc.h src/align.h \
src/stacktrack.h
+${BUILDDIR}/miniobj.o: src/miniobj.c src/miniobj.h src/panic.h src/jmp.h src/defer.h \
+ src/framealloc.h src/align.h src/stacktrack.h src/memutils.h src/vec.h \
+ src/execalloc.h
+${BUILDDIR}/miniobj_lifetime.o: src/miniobj_lifetime.c src/miniobj.h src/memutils.h \
+ src/panic.h src/jmp.h
${BUILDDIR}/panic.o: src/panic.c src/panic.h src/jmp.h src/defer.h src/framealloc.h \
src/align.h src/stacktrack.h src/memutils.h
${BUILDDIR}/stacktrack.o: src/stacktrack.c src/stacktrack.h
vgcore.*
.direnv
.norm_fail
-Makefile.tmp
*.tmp
flamegraph.svg
perf.data
NAME=ccera.a
-SRCS=src/arc.c src/builtin_add.c src/builtin.c src/builtin_list_get.c src/builtin_list_set.c src/builtin_list_set_drop.c src/builtin_lte.c src/builtin_mul.c src/builtin_noop.c src/builtin_register.c src/builtin_sub.c src/defer.c src/eval.c src/framealloc.c src/panic.c src/stacktrack.c src/value_debug.c src/value_lifetime.c src/value_list.c src/value_move.c src/value_new.c src/value_new_utils.c
+SRCS=src/arc.c src/builtin_add.c src/builtin.c src/builtin_list_get.c src/builtin_list_set.c src/builtin_list_set_drop.c src/builtin_lte.c src/builtin_mul.c src/builtin_noop.c src/builtin_register.c src/builtin_sub.c src/defer.c src/eval.c src/execalloc.c src/framealloc.c src/miniobj.c src/miniobj_lifetime.c src/panic.c src/stacktrack.c src/value_debug.c src/value_lifetime.c src/value_list.c src/value_move.c src/value_new.c src/value_new_utils.c
-HEADERS=src/align.h src/arc.h src/arith.h src/atomic.h src/builtin_register.h src/ccera.h src/defer.h src/framealloc.h src/jmp.h src/memutils.h src/panic.h src/stacktrack.h src/value_get.h src/value.h src/value_new.h src/value_types.h
+HEADERS=src/align.h src/arc.h src/arith.h src/atomic.h src/builtin_register.h src/ccera.h src/defer.h src/execalloc.h src/framealloc.h src/jmp.h src/memutils.h src/miniobj.h src/panic.h src/stacktrack.h src/value_get.h src/value.h src/value_new.h src/value_types.h src/vec.h
CC = cc
-LTO=1
-OPT=1
+LTO=0
+OPT=0
CC=clang
#UBSAN=1
#TSAN=1
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/04/29 16:08:57 by agilliar #+# #+# */
-/* Updated: 2026/05/20 14:06:31 by agilliar ### ########.fr */
+/* Updated: 2026/06/01 18:27:59 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
# include "stacktrack.h"
# include "atomic.h"
# include "builtin_register.h"
+# include "execalloc.h"
+# include "miniobj.h"
// The expression value is a tuple of an evaluatable and the argument to give it
//
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* execalloc.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/05/29 19:54:36 by agilliar #+# #+# */
+/* Updated: 2026/06/01 18:43:36 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include <stddef.h>
+#include <stdbool.h>
+#include "panic.h"
+
+#define EXECALLOC_SIZE_N 1000000
+#define EXECALLOC_SIZE "1000000"
+
+asm (
+ ".section rwx, \"awx\"\n"
+ ".global _execalloc_store\n"
+ "_execalloc_store:\n"
+ ".zero " EXECALLOC_SIZE "\n"
+ ".size _execaclloc_store, " EXECALLOC_SIZE "\n"
+ );
+
+char *execalloc(size_t n)
+{
+ static size_t used = 0;
+ extern char _execalloc_store[EXECALLOC_SIZE_N];
+ size_t prev_used;
+ size_t next_used;
+
+ while (true)
+ {
+ prev_used = __atomic_load_n(&used, __ATOMIC_RELAXED);
+ if (__builtin_add_overflow(prev_used, n, &next_used)
+ || next_used > EXECALLOC_SIZE_N)
+ panic("execalloc failed");
+ if (__atomic_compare_exchange_n(&used, &prev_used, next_used,
+ true, __ATOMIC_RELAXED, __ATOMIC_RELAXED))
+ return (&_execalloc_store[prev_used]);
+ }
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* execalloc.h :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/05/31 22:52:39 by agilliar #+# #+# */
+/* Updated: 2026/05/31 23:51:15 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#ifndef EXECALLOC_H
+# define EXECALLOC_H
+
+char *execalloc(size_t n);
+
+#endif
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* miniobj.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/05/31 22:55:45 by agilliar #+# #+# */
+/* Updated: 2026/06/01 18:55:02 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include <stdint.h>
+#include "miniobj.h"
+#include "panic.h"
+#include "defer.h"
+#include "memutils.h"
+#include "vec.h"
+#include "execalloc.h"
+
+void miniobj_write_s(t_miniobj *obj, const char *s)
+{
+ miniobj_write(obj, s, cera_strlen(s));
+}
+
+void miniobj_write(t_miniobj *obj, const char *s, size_t n)
+{
+ vec_grow((void **) &obj->byte_buf, &obj->byte_capacity, obj->byte_len + n);
+ cera_memcpy(&obj->byte_buf[obj->byte_len], s, n);
+ obj->byte_len += n;
+}
+
+t_objaddr miniobj_label(t_miniobj *obj, t_label label)
+{
+ obj->resolved_labels[label] = obj->byte_len;
+ return (obj->byte_len);
+}
+
+void miniobj_write_reloc(t_miniobj *obj, t_label label, t_reloc_kind kind)
+{
+ const uintptr_t s = 0;
+
+ vec_grow((void **) &obj->reloc_buf,
+ &obj->reloc_capacity, (obj->reloc_len + 1) * sizeof(t_relocation));
+ obj->reloc_buf[obj->reloc_len] = (t_relocation){obj->byte_len, label, kind};
+ miniobj_write(obj, (const char *)&s, sizeof(int32_t));
+ obj->reloc_len += 1;
+}
+
+const char *miniobj_finish(t_miniobj obj)
+{
+ char *res;
+ size_t i;
+ t_relocation reloc;
+ int32_t offset;
+
+ defer(miniobj_drop, &obj);
+ res = execalloc(obj.byte_len);
+ cera_memcpy(res, obj.byte_buf, obj.byte_len);
+ i = 0;
+ while (i < obj.reloc_len)
+ {
+ reloc = obj.reloc_buf[i++];
+ if (reloc.kind == REL_I32)
+ {
+ offset = obj.resolved_labels[reloc.label] - reloc.loc
+ - sizeof(int32_t);
+ cera_memcpy(
+ &res[reloc.loc],
+ (const char *) &offset,
+ sizeof(int32_t));
+ }
+ }
+ return (res);
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* miniobj.h :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/05/31 22:55:56 by agilliar #+# #+# */
+/* Updated: 2026/06/01 17:56:03 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#ifndef MINIOBJ_H
+# define MINIOBJ_H
+
+# include <stddef.h>
+
+typedef size_t t_objaddr;
+typedef size_t t_label;
+
+typedef enum e_reloc_kind
+{
+ REL_I32,
+} t_reloc_kind;
+
+typedef struct s_relocation
+{
+ t_objaddr loc;
+ t_label label;
+ t_reloc_kind kind;
+} t_relocation;
+
+typedef struct s_miniobj
+{
+ char *byte_buf;
+ size_t byte_len;
+ size_t byte_capacity;
+ t_relocation *reloc_buf;
+ size_t reloc_len;
+ size_t reloc_capacity;
+ t_objaddr *resolved_labels;
+} t_miniobj;
+
+t_miniobj miniobj_new(size_t label_count);
+void miniobj_drop(t_miniobj *obj);
+
+void miniobj_write_s(t_miniobj *obj, const char *s);
+void miniobj_write(t_miniobj *obj, const char *s, size_t n);
+t_objaddr miniobj_label(t_miniobj *obj, t_label label);
+void miniobj_write_reloc(t_miniobj *obj, t_label label,
+ t_reloc_kind kind);
+// the returned buffer is addressable by the return values of defining labels
+const char *miniobj_finish(t_miniobj obj);
+
+#endif
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* miniobj_lifetime.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/06/01 00:06:44 by agilliar #+# #+# */
+/* Updated: 2026/06/01 00:09:00 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "miniobj.h"
+#include "memutils.h"
+
+t_miniobj miniobj_new(size_t label_count)
+{
+ t_miniobj res;
+
+ cera_memset(&res, 0, sizeof(t_miniobj));
+ res.resolved_labels = cera_malloc(label_count * sizeof(t_objaddr));
+ return (res);
+}
+
+void miniobj_drop(t_miniobj *obj)
+{
+ free(obj->byte_buf);
+ free(obj->reloc_buf);
+ free(obj->resolved_labels);
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* vec.h :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/05/31 23:16:07 by agilliar #+# #+# */
+/* Updated: 2026/06/01 18:31:18 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#ifndef VEC_H
+# define VEC_H
+
+# include <stddef.h>
+# include "memutils.h"
+
+static inline void vec_grow(void **p, size_t *cap, size_t to)
+{
+ void *nxt;
+
+ if (to <= *cap)
+ return ;
+ if (to < *cap * 2)
+ to = *cap * 2;
+ nxt = cera_malloc(to);
+ cera_memcpy(nxt, *p, *cap);
+ free(*p);
+ *p = nxt;
+ *cap = to;
+}
+
+#endif
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/04/30 17:19:58 by agilliar #+# #+# */
-/* Updated: 2026/05/27 17:25:44 by agilliar ### ########.fr */
+/* Updated: 2026/06/01 18:55:35 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
defer(free, s2);
strcpy(s2, orig);
//t_value res = expr_eval(test_expr(), value_new_uint(0));
- t_value res = expr_eval(fact(), value_new_uint(1000000));
+ t_value res = expr_eval(fact(), value_new_uint(5000000));
value_debug(0, &res);
defer(value_drop, &res);
printf("%s\n", s2);
}
+/*
int main(void)
{
char *msg;
char *s2 = malloc(strlen(orig) + 1);
defer(free, s2);
}
+*/
+
+int main(void)
+{
+ t_miniobj obj;
+ t_objaddr func;
+ size_t (*fact)(size_t);
+
+ obj = miniobj_new(2);
+ func = miniobj_label(&obj, 0); // func:
+ miniobj_write_s(&obj, "\x48\x85\xff"); // test rdi, rdi
+ miniobj_write_s(&obj, "\x0f\x84");
+ miniobj_write_reloc(&obj, 1, REL_I32); // je rel32 end
+ miniobj_write_s(&obj, "\x57"); // push rdi
+ miniobj_write_s(&obj, "\x48\xff\xcf"); // dec rdi
+ miniobj_write_s(&obj, "\xe8");
+ miniobj_write_reloc(&obj, 0, REL_I32); // call func
+ miniobj_write_s(&obj, "\x5f"); // pop rdi
+ miniobj_write_s(&obj, "\x48\x0f\xaf\xc7"); // imul rdi, rax
+ miniobj_write_s(&obj, "\xc3"); // ret
+ miniobj_label(&obj, 1); // end:
+ miniobj_write(&obj, "\xb8\x01\x00\x00\x00", 5); // mov 1, eax
+ miniobj_write_s(&obj, "\xc3"); // ret
+ fact = (void *) &miniobj_finish(obj)[func];
+ printf("%lu\n", fact(10));
+}