diff options
author | Nathan Ringo <nathan@remexre.com> | 2024-11-27 20:28:40 -0600 |
---|---|---|
committer | Nathan Ringo <nathan@remexre.com> | 2024-11-27 20:28:40 -0600 |
commit | b252d0de46cf12b8e2521b3eb42da9acc41a4cc1 (patch) | |
tree | 456bfed5547745edacebe8c89194c26f03a25908 /src/value.c | |
parent | 62e41dcb40d0450d493a804e7f0ac3e32f35aabf (diff) |
new simpler GC
Diffstat (limited to 'src/value.c')
-rw-r--r-- | src/value.c | 53 |
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. |