summaryrefslogtreecommitdiff
path: root/type_helpers.c
diff options
context:
space:
mode:
authorMatthew Sotoudeh <matthew@masot.net>2023-07-25 14:58:33 -0700
committerMatthew Sotoudeh <matthew@masot.net>2023-07-25 14:58:33 -0700
commit1d943da0cf9154e7ce78ce867cdbb91531c5d78e (patch)
tree40c5c6c3ba7fafa6567aa5b5aa216caecf3935fc /type_helpers.c
initial dietc commit
Diffstat (limited to 'type_helpers.c')
-rw-r--r--type_helpers.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/type_helpers.c b/type_helpers.c
new file mode 100644
index 0000000..0f6b022
--- /dev/null
+++ b/type_helpers.c
@@ -0,0 +1,78 @@
+#include <stddef.h>
+#include "chibicc.h"
+
+unsigned long hash_type(Type *type) {
+ unsigned long hash = 6997;
+ if (!type) return hash;
+ if (type->hashing) return hash;
+ type->hashing = 1;
+#define EXTEND_HASH(v) hash = (hash * 33) ^ (size_t)(v)
+ EXTEND_HASH(type->kind);
+ EXTEND_HASH(type->size);
+ EXTEND_HASH(type->align);
+ EXTEND_HASH(type->is_unsigned);
+ EXTEND_HASH(type->is_atomic);
+ // EXTEND_HASH(hash_type(type->origin));
+
+ EXTEND_HASH(hash_type(type->base));
+ EXTEND_HASH(type->array_len);
+ EXTEND_HASH(type->vla_len);
+ EXTEND_HASH(type->vla_size);
+ EXTEND_HASH(type->members);
+
+ // TODO: assume the members pointers are actually same?
+ // for (Member *m = type->members; m; m = m->next) {
+ // EXTEND_HASH(hash_type(m->ty));
+ // EXTEND_HASH(m->name); // token
+ // EXTEND_HASH(m->idx);
+ // EXTEND_HASH(m->align);
+ // EXTEND_HASH(m->offset);
+ // EXTEND_HASH(m->is_bitfield);
+ // EXTEND_HASH(m->bit_offset);
+ // EXTEND_HASH(m->bit_width);
+ // }
+ EXTEND_HASH(type->is_flexible);
+ EXTEND_HASH(type->is_packed);
+
+ EXTEND_HASH(hash_type(type->return_ty));
+ EXTEND_HASH(hash_type(type->params));
+ EXTEND_HASH(type->is_variadic);
+ // EXTEND_HASH(type->next);
+
+ type->hashing = 0;
+ return hash;
+}
+
+int definitely_same_type(Type *type1, Type *type2) {
+ if (!type1 || !type2) return type1 == type2;
+ if (type1->hashing != type2->hashing) return 0;
+ if (type1->hashing) return type1 == type2;
+ type1->hashing = 1;
+ type2->hashing = 1;
+#define FIELD_CHECK(field) if (type1->field != type2->field) goto disequal
+#define RECURSE_CHECK(field) if (!definitely_same_type(type1->field, type2->field)) goto disequal
+ FIELD_CHECK(kind);
+ FIELD_CHECK(size);
+ FIELD_CHECK(align);
+ FIELD_CHECK(is_unsigned);
+ FIELD_CHECK(is_atomic);
+ // RECURSE_CHECK(origin);
+ RECURSE_CHECK(base);
+ FIELD_CHECK(array_len);
+ FIELD_CHECK(vla_len);
+ FIELD_CHECK(vla_size);
+ FIELD_CHECK(members);
+ FIELD_CHECK(is_flexible);
+ FIELD_CHECK(is_packed);
+ RECURSE_CHECK(return_ty);
+ FIELD_CHECK(params);
+ FIELD_CHECK(is_variadic);
+ // RECURSE_CHECK(next);
+ type1->hashing = 0;
+ type2->hashing = 0;
+ return 1;
+disequal:
+ type1->hashing = 0;
+ type2->hashing = 0;
+ return 0;
+}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback