commit 64c8f388a55382122fd60a67fd5dce2c30640133
parent 437a3ca788a8dccc495e79bb88d0449951e969cc
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 12 Dec 2020 11:16:03 -0500
Build initial riggings for type store
Diffstat:
4 files changed, 316 insertions(+), 7 deletions(-)
diff --git a/include/type_store.h b/include/type_store.h
@@ -5,16 +5,19 @@
#define TYPE_STORE_BUCKETS 256
-struct types {
+struct type_bucket {
struct type type;
- struct types *next;
+ struct type_bucket *next;
};
struct type_store {
- struct type buckets[TYPE_STORE_BUCKETS];
+ struct type_bucket *buckets[TYPE_STORE_BUCKETS];
};
unsigned long atype_hash(struct type_store *store, const struct ast_type *type);
unsigned long type_hash(struct type_store *store, const struct type *type);
+const struct type *type_store_lookup_atype(
+ struct type_store *store, const struct ast_type *atype);
+
#endif
diff --git a/include/types.h b/include/types.h
@@ -41,7 +41,7 @@ enum type_storage {
struct type;
enum pointer_flags {
- POINTER_NULLABLE = 1 << 0,
+ POINTER_FLAGS_NULLABLE = 1 << 0,
};
struct type_pointer {
@@ -50,7 +50,7 @@ struct type_pointer {
};
enum type_flags {
- TYPE_CONST = 1 << 0,
+ TYPE_FLAGS_CONST = 1 << 0,
};
struct type {
@@ -82,9 +82,29 @@ extern const struct type
builtin_type_u64,
builtin_type_uint,
builtin_type_uintptr,
+ builtin_type_rune,
builtin_type_size,
builtin_type_void,
+ // Const primitives
+ builtin_type_const_bool,
+ builtin_type_const_char,
+ builtin_type_const_f32,
+ builtin_type_const_f64,
+ builtin_type_const_i8,
+ builtin_type_const_i16,
+ builtin_type_const_i32,
+ builtin_type_const_i64,
+ builtin_type_const_int,
+ builtin_type_const_u8,
+ builtin_type_const_u16,
+ builtin_type_const_u32,
+ builtin_type_const_u64,
+ builtin_type_const_uint,
+ builtin_type_const_uintptr,
+ builtin_type_const_rune,
+ builtin_type_const_size,
+ builtin_type_const_void,
// Aggregate
- builtin_type_charptr;
+ builtin_type_const_ptr_char;
#endif
diff --git a/src/type_store.c b/src/type_store.c
@@ -1,4 +1,5 @@
#include <assert.h>
+#include <stdlib.h>
#include "type_store.h"
#include "util.h"
@@ -81,3 +82,174 @@ type_hash(struct type_store *store, const struct type *type)
}
return hash;
}
+
+static const struct type *
+builtin_for_atype(const struct ast_type *atype)
+{
+ bool is_const = (atype->flags & TYPE_FLAGS_CONST) != 0;
+ switch (atype->storage) {
+ case TYPE_STORAGE_BOOL:
+ return is_const ? &builtin_type_bool : &builtin_type_const_bool;
+ case TYPE_STORAGE_CHAR:
+ return is_const ? &builtin_type_char : &builtin_type_const_char;
+ case TYPE_STORAGE_F32:
+ return is_const ? &builtin_type_f32 : &builtin_type_const_f32;
+ case TYPE_STORAGE_F64:
+ return is_const ? &builtin_type_f64 : &builtin_type_const_f64;
+ case TYPE_STORAGE_I8:
+ return is_const ? &builtin_type_i8 : &builtin_type_const_i8;
+ case TYPE_STORAGE_I16:
+ return is_const ? &builtin_type_i16 : &builtin_type_const_i16;
+ case TYPE_STORAGE_I32:
+ return is_const ? &builtin_type_i32 : &builtin_type_const_i32;
+ case TYPE_STORAGE_I64:
+ return is_const ? &builtin_type_i64 : &builtin_type_const_i64;
+ case TYPE_STORAGE_INT:
+ return is_const ? &builtin_type_int : &builtin_type_const_int;
+ case TYPE_STORAGE_RUNE:
+ return is_const ? &builtin_type_rune : &builtin_type_const_rune;
+ case TYPE_STORAGE_SIZE:
+ return is_const ? &builtin_type_size : &builtin_type_const_size;
+ case TYPE_STORAGE_U8:
+ return is_const ? &builtin_type_u8 : &builtin_type_const_u8;
+ case TYPE_STORAGE_U16:
+ return is_const ? &builtin_type_u16 : &builtin_type_const_u16;
+ case TYPE_STORAGE_U32:
+ return is_const ? &builtin_type_u32 : &builtin_type_const_u32;
+ case TYPE_STORAGE_U64:
+ return is_const ? &builtin_type_u64 : &builtin_type_const_u64;
+ case TYPE_STORAGE_UINT:
+ return is_const ? &builtin_type_uint : &builtin_type_const_uint;
+ case TYPE_STORAGE_UINTPTR:
+ return is_const ? &builtin_type_uintptr : &builtin_type_const_uintptr;
+ case TYPE_STORAGE_VOID:
+ return is_const ? &builtin_type_void : &builtin_type_const_void;
+ case TYPE_STORAGE_POINTER:
+ if (atype->pointer.referent->storage == TYPE_STORAGE_CHAR
+ && atype->pointer.referent->flags == TYPE_FLAGS_CONST) {
+ return &builtin_type_const_ptr_char;
+ }
+ return NULL;
+ case TYPE_STORAGE_ALIAS:
+ case TYPE_STORAGE_ARRAY:
+ case TYPE_STORAGE_FUNCTION:
+ case TYPE_STORAGE_SLICE:
+ case TYPE_STORAGE_STRING:
+ case TYPE_STORAGE_STRUCT:
+ case TYPE_STORAGE_TAGGED_UNION:
+ case TYPE_STORAGE_UNION:
+ return NULL;
+
+ }
+ assert(0); // Unreachable
+}
+
+static bool
+type_eq_atype(struct type_store *store,
+ const struct type *type,
+ const struct ast_type *atype)
+{
+ if (type->storage != atype->storage || type->flags != atype->flags) {
+ return false;
+ }
+
+ switch (type->storage) {
+ case TYPE_STORAGE_BOOL:
+ case TYPE_STORAGE_CHAR:
+ case TYPE_STORAGE_F32:
+ case TYPE_STORAGE_F64:
+ case TYPE_STORAGE_I8:
+ case TYPE_STORAGE_I16:
+ case TYPE_STORAGE_I32:
+ case TYPE_STORAGE_I64:
+ case TYPE_STORAGE_INT:
+ case TYPE_STORAGE_RUNE:
+ case TYPE_STORAGE_SIZE:
+ case TYPE_STORAGE_U8:
+ case TYPE_STORAGE_U16:
+ case TYPE_STORAGE_U32:
+ case TYPE_STORAGE_U64:
+ case TYPE_STORAGE_UINT:
+ case TYPE_STORAGE_UINTPTR:
+ case TYPE_STORAGE_VOID:
+ return true;
+ case TYPE_STORAGE_ALIAS:
+ case TYPE_STORAGE_ARRAY:
+ case TYPE_STORAGE_FUNCTION:
+ case TYPE_STORAGE_POINTER:
+ case TYPE_STORAGE_SLICE:
+ case TYPE_STORAGE_STRING:
+ case TYPE_STORAGE_STRUCT:
+ case TYPE_STORAGE_TAGGED_UNION:
+ case TYPE_STORAGE_UNION:
+ assert(0); // TODO
+ }
+
+ assert(0); // Unreachable
+}
+
+static void
+type_init_from_atype(struct type_store *store,
+ struct type *type,
+ const struct ast_type *atype)
+{
+ type->storage = atype->storage;
+ type->flags = atype->flags;
+
+ switch (type->storage) {
+ case TYPE_STORAGE_BOOL:
+ case TYPE_STORAGE_CHAR:
+ case TYPE_STORAGE_F32:
+ case TYPE_STORAGE_F64:
+ case TYPE_STORAGE_I8:
+ case TYPE_STORAGE_I16:
+ case TYPE_STORAGE_I32:
+ case TYPE_STORAGE_I64:
+ case TYPE_STORAGE_INT:
+ case TYPE_STORAGE_RUNE:
+ case TYPE_STORAGE_SIZE:
+ case TYPE_STORAGE_U8:
+ case TYPE_STORAGE_U16:
+ case TYPE_STORAGE_U32:
+ case TYPE_STORAGE_U64:
+ case TYPE_STORAGE_UINT:
+ case TYPE_STORAGE_UINTPTR:
+ case TYPE_STORAGE_VOID:
+ assert(0); // Invariant
+ case TYPE_STORAGE_ALIAS:
+ case TYPE_STORAGE_ARRAY:
+ case TYPE_STORAGE_FUNCTION:
+ case TYPE_STORAGE_POINTER:
+ case TYPE_STORAGE_SLICE:
+ case TYPE_STORAGE_STRING:
+ case TYPE_STORAGE_STRUCT:
+ case TYPE_STORAGE_TAGGED_UNION:
+ case TYPE_STORAGE_UNION:
+ assert(0); // TODO
+ }
+}
+
+const struct type *
+type_store_lookup_atype(struct type_store *store, const struct ast_type *atype)
+{
+ const struct type *builtin = builtin_for_atype(atype);
+ if (builtin) {
+ return builtin;
+ }
+
+ unsigned long hash = atype_hash(store, atype);
+ struct type_bucket **next = &store->buckets[hash % TYPE_STORE_BUCKETS];
+
+ struct type_bucket *bucket;
+ while (*next) {
+ bucket = *next;
+ if (type_eq_atype(store, &bucket->type, atype)) {
+ return &bucket->type;
+ }
+ next = &bucket->next;
+ }
+
+ bucket = *next = calloc(1, sizeof(struct type_bucket));
+ type_init_from_atype(store, &bucket->type, atype);
+ return &bucket->type;
+}
diff --git a/src/types.c b/src/types.c
@@ -140,6 +140,11 @@ builtin_type_uintptr = {
.size = 8, // XXX: ARCH
.align = 8,
},
+builtin_type_rune = {
+ .storage = TYPE_STORAGE_RUNE,
+ .size = 4,
+ .align = 4,
+},
builtin_type_size = {
.storage = TYPE_STORAGE_SIZE,
.size = 8, // XXX: ARCH
@@ -149,11 +154,120 @@ builtin_type_void = {
.storage = TYPE_STORAGE_VOID,
.size = 0,
.align = 0,
+},
+builtin_type_const_bool = {
+ .storage = TYPE_STORAGE_BOOL,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 4, // XXX: ARCH
+ .align = 4,
+},
+builtin_type_const_char = {
+ .storage = TYPE_STORAGE_CHAR,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 1,
+ .align = 1,
+},
+builtin_type_const_f32 = {
+ .storage = TYPE_STORAGE_F32,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 4,
+ .align = 4,
+},
+builtin_type_const_f64 = {
+ .storage = TYPE_STORAGE_F64,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 8,
+ .align = 8,
+},
+builtin_type_const_i8 = {
+ .storage = TYPE_STORAGE_I8,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 1,
+ .align = 1,
+},
+builtin_type_const_i16 = {
+ .storage = TYPE_STORAGE_I16,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 2,
+ .align = 2,
+},
+builtin_type_const_i32 = {
+ .storage = TYPE_STORAGE_I32,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 4,
+ .align = 4,
+},
+builtin_type_const_i64 = {
+ .storage = TYPE_STORAGE_I64,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 8,
+ .align = 8,
+},
+builtin_type_const_int = {
+ .storage = TYPE_STORAGE_INT,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 4, // XXX: ARCH
+ .align = 4,
+},
+builtin_type_const_u8 = {
+ .storage = TYPE_STORAGE_U8,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 1,
+ .align = 1,
+},
+builtin_type_const_u16 = {
+ .storage = TYPE_STORAGE_U16,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 2,
+ .align = 2,
+},
+builtin_type_const_u32 = {
+ .storage = TYPE_STORAGE_U32,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 4,
+ .align = 4,
+},
+builtin_type_const_u64 = {
+ .storage = TYPE_STORAGE_U64,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 8,
+ .align = 8,
+},
+builtin_type_const_uint = {
+ .storage = TYPE_STORAGE_UINT,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 4,
+ .align = 4,
+},
+builtin_type_const_uintptr = {
+ .storage = TYPE_STORAGE_UINTPTR,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 8, // XXX: ARCH
+ .align = 8,
+},
+builtin_type_const_rune = {
+ .storage = TYPE_STORAGE_RUNE,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 4,
+ .align = 4,
+},
+builtin_type_const_size = {
+ .storage = TYPE_STORAGE_SIZE,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 8, // XXX: ARCH
+ .align = 8,
+},
+builtin_type_const_void = {
+ .storage = TYPE_STORAGE_VOID,
+ .flags = TYPE_FLAGS_CONST,
+ .size = 0,
+ .align = 0,
};
// Selected aggregate type singletons
-const struct type builtin_type_charptr = {
+const struct type builtin_type_const_ptr_char = {
.storage = TYPE_STORAGE_POINTER,
+ .flags = TYPE_FLAGS_CONST,
.size = 8, // XXX: ARCH
.align = 8,
.pointer = {