#include "value.h" #include "gc.h" #include "util.h" #include 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, BUILTIN_BUILTIN_CLASS_BUILTIN_CLASS, BUILTIN_BUILTIN_CLASS_BUILTIN_FUNCTION, BUILTIN_BUILTIN_CLASS_BUILTIN_OBJECT, BUILTIN_BUILTIN_CLASS_CHARACTER, BUILTIN_BUILTIN_CLASS_COMPILED_FUNCTION, BUILTIN_BUILTIN_CLASS_CONS, BUILTIN_BUILTIN_CLASS_DIRECT_SLOT_DEFINITION, BUILTIN_BUILTIN_CLASS_EFFECTIVE_SLOT_DEFINITION, BUILTIN_BUILTIN_CLASS_FIXNUM, BUILTIN_BUILTIN_CLASS_GENERIC_FUNCTION, BUILTIN_BUILTIN_CLASS_HASHTABLE_EQ, BUILTIN_BUILTIN_CLASS_HASHTABLE_EQUAL, BUILTIN_BUILTIN_CLASS_METHOD, BUILTIN_BUILTIN_CLASS_NULL, BUILTIN_BUILTIN_CLASS_PACKAGE, BUILTIN_BUILTIN_CLASS_STANDARD_CLASS, BUILTIN_BUILTIN_CLASS_STANDARD_OBJECT, BUILTIN_BUILTIN_CLASS_STRING, BUILTIN_BUILTIN_CLASS_SYMBOL, BUILTIN_BUILTIN_CLASS_THREADED_FUNCTION, BUILTIN_BUILTIN_CLASS_VECTOR_VALUE_ADJ_FILL, BUILTIN_BUILTIN_CLASS_VECTOR_VALUE_NOADJ_FILL, BUILTIN_BUILTIN_CLASS_VECTOR_VALUE_NOADJ_NOFILL, BUILTIN_FUNCTION_CLASS_DIRECT_SLOTS, BUILTIN_FUNCTION_CLASS_DIRECT_SUBCLASSES, BUILTIN_FUNCTION_CLASS_DIRECT_SUPERCLASSES, BUILTIN_FUNCTION_CLASS_NAME, BUILTIN_FUNCTION_CLASS_PRECEDENCE_LIST, BUILTIN_FUNCTION_CLASS_SLOTS, BUILTIN_FUNCTION_EQ, BUILTIN_FUNCTION_EQUAL, BUILTIN_FUNCTION_GETHASH, BUILTIN_FUNCTION_GETSLOT, BUILTIN_FUNCTION_SETHASH, BUILTIN_FUNCTION_SETSLOT, BUILTIN_FUNCTION_SLOT_LOCATION, BUILTIN_FUNCTION_SLOT_NAME, BUILTIN_FUNCTION_SLOT_TYPE, BUILTIN_FUNCTION_VECTOR_GET, BUILTIN_FUNCTION_VECTOR_PUSH, BUILTIN_FUNCTION_VECTOR_PUSH_EXTEND, BUILTIN_FUNCTION_VECTOR_SET, BUILTIN_VARIABLE_DSTACK, BUILTIN_VARIABLE_RSTACK, BUILTINS_COUNT, }; static struct value builtins[BUILTINS_COUNT]; enum builtin_class_slot_index { BUILTIN_CLASS__NAME, BUILTIN_CLASS__FINALIZED, BUILTIN_CLASS__DIRECT_SUPERCLASSES, BUILTIN_CLASS__DIRECT_SUBCLASSES, BUILTIN_CLASS__PRECEDENCE_LIST, BUILTIN_CLASS_SLOT_COUNT, }; enum standard_class_slot_index { STANDARD_CLASS__NAME, STANDARD_CLASS__FINALIZED, STANDARD_CLASS__DIRECT_SUPERCLASSES, STANDARD_CLASS__DIRECT_SUBCLASSES, STANDARD_CLASS__PRECEDENCE_LIST, STANDARD_CLASS__DIRECT_SLOTS, STANDARD_CLASS__SLOTS, STANDARD_CLASS_SLOT_COUNT, }; static void push(struct value value) {} 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); else if (class.bits == builtins[BUILTIN_BUILTIN_CLASS_HASHTABLE_EQ].bits) obj = gc_alloc_hashtable_eq(value_slot_count, untraced_slot_count); else obj = gc_alloc(value_slot_count, untraced_slot_count); gc_write_value_slot(obj, 0, class); return (struct value){ .bits = (uintptr_t)obj | TAG_BUILTIN_OBJECT, }; } 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 == TAG_BIGINT_OR_NIL || tag == TAG_BUILTIN_OBJECT || tag == TAG_SIMPLE_ARRAY || tag == TAG_STANDARD_OBJECT || tag == TAG_GC_INTERNAL); 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) { // Register every builtin slot as a root. for (size_t i = 0; i < BUILTINS_COUNT; i++) gc_root_push(&builtins[i]); // Since it is its own class, standard-class needs to be constructed // manually. { builtins[BUILTIN_BUILTIN_CLASS_STANDARD_CLASS] = tag_ptr(gc_alloc(STANDARD_CLASS_SLOT_COUNT + 1, 0), TAG_BUILTIN_OBJECT); builtin_object_write_value_slot( builtins[BUILTIN_BUILTIN_CLASS_STANDARD_CLASS], 0, builtins[BUILTIN_BUILTIN_CLASS_STANDARD_CLASS]); // TODO } // }