summaryrefslogtreecommitdiff
path: root/src/value.c
diff options
context:
space:
mode:
authorNathan Ringo <nathan@remexre.com>2024-11-27 20:28:40 -0600
committerNathan Ringo <nathan@remexre.com>2024-11-27 20:28:40 -0600
commitb252d0de46cf12b8e2521b3eb42da9acc41a4cc1 (patch)
tree456bfed5547745edacebe8c89194c26f03a25908 /src/value.c
parent62e41dcb40d0450d493a804e7f0ac3e32f35aabf (diff)
new simpler GC
Diffstat (limited to 'src/value.c')
-rw-r--r--src/value.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/value.c b/src/value.c
index 07af689..b4e22a9 100644
--- a/src/value.c
+++ b/src/value.c
@@ -1,5 +1,11 @@
#include "value.h"
#include "gc.h"
+#include "util.h"
+#include <inttypes.h>
+
+static const intptr_t FIXNUM_MIN = -((intptr_t)1 << (4 * sizeof(void *) - 3)),
+ FIXNUM_MAX =
+ ((intptr_t)1 << (4 * sizeof(void *) - 3)) - 1;
enum builtin {
BUILTIN_BUILTIN_CLASS_BIGNUM,
@@ -83,6 +89,8 @@ static struct value pop(void) { return (struct value){.bits = 0}; }
struct value alloc_builtin_object(struct value class, size_t value_slot_count,
size_t untraced_slot_count) {
+ assume(value_slot_count != 0);
+
struct object *obj;
if (class.bits == builtins[BUILTIN_BUILTIN_CLASS_COMPILED_FUNCTION].bits)
obj = gc_alloc_compiled_function(value_slot_count, untraced_slot_count);
@@ -96,6 +104,51 @@ struct value alloc_builtin_object(struct value class, size_t value_slot_count,
};
}
+struct value integer_of_int(intptr_t n) {
+ if (FIXNUM_MIN <= n && n <= FIXNUM_MAX) {
+ struct value value = (struct value){.bits = (n << 2) | TAG_FIXNUM};
+ assume(untag_fixnum(value) == n);
+ return value;
+ } else {
+ todo("integer_of_int: bigint %" PRIdPTR, n);
+ }
+}
+
+enum value_tag get_tag(struct value value) {
+ uintptr_t low_bits = value.bits & 0b111;
+ switch (low_bits) {
+ case 0b000:
+ case 0b010:
+ case 0b100:
+ case 0b110:
+ return (enum value_tag)low_bits;
+ case 0b001:
+ case 0b101:
+ return TAG_FIXNUM;
+ default:
+ unreachable("invalid tag for value %p", (void *)value.bits);
+ }
+}
+
+bool is_ptr(struct value value) { return !(value.bits & 1); }
+
+struct value tag_ptr(struct object *obj, enum value_tag tag) {
+ assume((tag & 0b1) == 0);
+ assume(((uintptr_t)obj & 0b111) == 0);
+ return (struct value){.bits = (uintptr_t)obj | tag};
+}
+
+intptr_t untag_fixnum(struct value value) {
+ assume(get_tag(value) == TAG_FIXNUM);
+ intptr_t bits = value.bits;
+ return bits >> 2;
+}
+
+struct object *untag_ptr(struct value value) {
+ assume(is_ptr(value));
+ return (struct object *)((uintptr_t)value.bits & ~0b111);
+}
+
void bootstrap(void) {
// Since it is its own class, standard-class needs to be constructed
// manually.