commit e2d0cd2b3cd312619c29f09ecabee8994e4e4e35
parent 4665cbeee798723f124b45a9814deb055fb06e85
Author: Drew DeVault <sir@cmpwn.com>
Date: Fri, 30 Apr 2021 09:38:58 -0400
hare::types: refactor type hashmap
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
5 files changed, 78 insertions(+), 22 deletions(-)
diff --git a/hare/types/+test.ha b/hare/types/+test.ha
@@ -0,0 +1,35 @@
+use bufio;
+use hare::ast;
+use hare::lex;
+use hare::parse;
+use io;
+use strings;
+
+fn parse_type(in: str) ast::_type = {
+ let buf = bufio::fixed(strings::toutf8(in), io::mode::READ);
+ defer io::close(buf);
+ let lex = lex::init(buf, "<test>");
+ return parse::_type(&lex)!;
+};
+
+@test fn store() void = {
+ let st = store(x86_64, null, null);
+ defer store_free(st);
+
+ let atype = parse_type("int");
+ defer ast::type_free(atype);
+ let htype = lookup(st, &atype)!;
+ assert(htype._type is builtin);
+ assert(htype._type as builtin == builtin::INT);
+ assert(htype.sz == x86_64._int && htype.align == x86_64._int);
+
+ let type2 = lookup(st, &atype)!;
+ assert(htype == type2, "types should be singletons");
+
+ let atype = parse_type("*int");
+ defer ast::type_free(atype);
+ let htype = lookup(st, &atype)!;
+ assert(htype.sz == x86_64._pointer && htype.align == x86_64._pointer);
+ let htype = htype._type as pointer;
+ assert(htype.referent._type as builtin == builtin::INT);
+};
diff --git a/hare/types/store.ha b/hare/types/store.ha
@@ -13,17 +13,18 @@ export type resolver = fn(
export type typestore = struct {
arch: arch,
- map: [BUCKETS][]struct {
- hash: u32,
- _type: _type,
- },
- resolve: *resolver,
- rstate: *void,
+ map: [BUCKETS][]_type,
+ resolve: nullable *resolver,
+ rstate: nullable *void,
};
// Initializes a new type store. Optionally, provide a function which
// type-checks and evaluates an [[ast::expr]].
-export fn store(arch: arch, resolver: *resolver, rstate: *void) *typestore = {
+export fn store(
+ arch: arch,
+ resolver: nullable *resolver,
+ rstate: nullable *void,
+) *typestore = {
return alloc(typestore {
arch = arch,
resolve = resolver,
@@ -32,6 +33,16 @@ export fn store(arch: arch, resolver: *resolver, rstate: *void) *typestore = {
});
};
+export fn store_free(store: *typestore) void = {
+ for (let i = 0z; i < len(store.map); i += 1) {
+ for (let j = 0z; j < len(store.map[i]); j += 1) {
+ type_finish(&store.map[i][j]);
+ };
+ free(store.map[i]);
+ };
+ free(store);
+};
+
// Returned from [[lookup]] when we are unable to resolve this type, but it does
// not necessarily have an error. This occurs when a type includes an unknown
// forward reference.
@@ -47,23 +58,21 @@ export type error = (noresolver | errors::opaque)!;
// Retrieves a [[_type]] for a given [[ast::_type]].
export fn lookup(
store: *typestore,
- t: *ast::_type,
+ ty: *ast::_type,
) (const *_type | deferred | error) = {
- const t = fromast(store, t)?;
- const h = hash(&t);
- let bucket = &store.map[h % BUCKETS];
+ const ty = fromast(store, ty)?;
+ const id = hash(&ty);
+ let bucket = &store.map[id % BUCKETS];
// XXX: Should not have to dereference bucket
for (let i = 0z; i < len(*bucket); i += 1) {
- if (bucket[i].hash == h) {
- type_finish(&t);
- return &bucket[i]._type;
+ if (bucket[i].id == id) {
+ type_finish(&ty);
+ return &bucket[i];
};
};
- append(*bucket, struct {
- hash: u32 = h,
- _type: _type = t,
- });
- return &bucket[len(*bucket) - 1]._type;
+ ty.id = id;
+ append(*bucket, ty);
+ return &bucket[len(*bucket) - 1];
};
fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = {
diff --git a/hare/types/types.ha b/hare/types/types.ha
@@ -43,6 +43,7 @@ export def SIZE_UNDEFINED: size = -1: size;
export type _type = struct {
flags: flags,
_type: (alias | builtin | pointer),
+ id: u32,
sz: size,
align: size,
};
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -358,12 +358,22 @@ hare_ast() {
gen_ssa hare::ast hare::lex strings
}
-hare_types() {
+gensrcs_hare_types() {
gen_srcs hare::types \
arch.ha \
hash.ha \
store.ha \
- types.ha
+ types.ha \
+ $*
+}
+
+hare_types() {
+ if [ $testing -eq 1 ]
+ then
+ gensrcs_hare_types +test.ha
+ else
+ gensrcs_hare_types
+ fi
gen_ssa hare::types hare::ast hash hash::fnv endian
}
diff --git a/stdlib.mk b/stdlib.mk
@@ -1552,7 +1552,8 @@ testlib_hare_types_srcs= \
$(STDLIB)/hare/types/arch.ha \
$(STDLIB)/hare/types/hash.ha \
$(STDLIB)/hare/types/store.ha \
- $(STDLIB)/hare/types/types.ha
+ $(STDLIB)/hare/types/types.ha \
+ $(STDLIB)/hare/types/+test.ha
$(TESTCACHE)/hare/types/hare_types.ssa: $(testlib_hare_types_srcs) $(testlib_rt) $(testlib_hare_ast) $(testlib_hash) $(testlib_hash_fnv) $(testlib_endian)
@printf 'HAREC \t$@\n'