commit 4665cbeee798723f124b45a9814deb055fb06e85
parent 4a7f2fddd1dc27db747d598d0b89e23cc2e8a845
Author: Drew DeVault <sir@cmpwn.com>
Date: Fri, 30 Apr 2021 09:18:39 -0400
hare::types: store type size & align
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
6 files changed, 157 insertions(+), 13 deletions(-)
diff --git a/hare/types/arch.ha b/hare/types/arch.ha
@@ -0,0 +1,20 @@
+// Configuration for a specific architecture.
+export type arch = struct {
+ _int: size,
+ _pointer: size,
+ _size: size,
+};
+
+// [[arch]] configuration for x86_64.
+export const x86_64: arch = arch {
+ _int = 4,
+ _pointer = 8,
+ _size = 8,
+};
+
+// [[arch]] configuration for aarch64.
+export const aarch64: arch = arch {
+ _int = 4,
+ _pointer = 8,
+ _size = 8,
+};
diff --git a/hare/types/hash.ha b/hare/types/hash.ha
@@ -60,8 +60,8 @@ export fn hash(t: *_type) u32 = {
write8(id, t.flags);
match (t._type) {
- a: alias => for (let i = len(a); i > 0; i -= 1) {
- hash::write(id, strings::toutf8(a[i - 1]));
+ a: alias => for (let i = len(a.id); i > 0; i -= 1) {
+ hash::write(id, strings::toutf8(a.id[i - 1]));
write8(id, 0);
},
builtin => void,
@@ -84,13 +84,19 @@ export fn hash(t: *_type) u32 = {
let sample = _type {
flags = flags::NONE,
- _type = ["foo", "bar"]: alias,
+ _type = alias {
+ id = ["foo", "bar"],
+ ...
+ },
};
assert(hash(&sample) == 1488828140);
let sample = _type {
flags = flags::ERROR,
- _type = ["foo", "bar"]: alias,
+ _type = alias {
+ id = ["foo", "bar"],
+ ...
+ },
};
assert(hash(&sample) == 4003927486);
diff --git a/hare/types/store.ha b/hare/types/store.ha
@@ -12,6 +12,7 @@ export type resolver = fn(
) (size | errors::opaque);
export type typestore = struct {
+ arch: arch,
map: [BUCKETS][]struct {
hash: u32,
_type: _type,
@@ -22,8 +23,9 @@ export type typestore = struct {
// Initializes a new type store. Optionally, provide a function which
// type-checks and evaluates an [[ast::expr]].
-export fn store(resolver: *resolver, rstate: *void) *typestore = {
+export fn store(arch: arch, resolver: *resolver, rstate: *void) *typestore = {
return alloc(typestore {
+ arch = arch,
resolve = resolver,
rstate = rstate,
...
@@ -65,27 +67,130 @@ export fn lookup(
};
fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = {
+ let sz = SIZE_UNDEFINED, align = SIZE_UNDEFINED;
let underlying = match (atype._type) {
a: ast::alias_type => {
- assert(!a.unwrap); // TODO
- ast::ident_dup(a.ident): alias;
+ // TODO: This is incomplete
+ assert(!a.unwrap);
+ alias {
+ id = ast::ident_dup(a.ident),
+ _type = null,
+ };
},
- b: ast::builtin_type => b: builtin,
- p: ast::pointer_type => pointer {
- referent = lookup(store, p.referent)?,
- flags = p.flags: pointer_flags,
+ // TODO: Tuple unpacking could improve this
+ b: ast::builtin_type => switch (b) {
+ ast::builtin_type::BOOL => {
+ sz = store.arch._int;
+ align = store.arch._int;
+ builtin::BOOL;
+ },
+ ast::builtin_type::CHAR => {
+ sz = 1; align = 1;
+ builtin::CHAR;
+ },
+ ast::builtin_type::F32 => {
+ sz = 4; align = 4;
+ builtin::F32;
+ },
+ ast::builtin_type::F64 => {
+ sz = 8; align = 8;
+ builtin::F64;
+ },
+ ast::builtin_type::I16 => {
+ sz = 2; align = 2;
+ builtin::I16;
+ },
+ ast::builtin_type::I32 => {
+ sz = 4; align = 4;
+ builtin::I32;
+ },
+ ast::builtin_type::I64 => {
+ sz = 8; align = 8;
+ builtin::I64;
+ },
+ ast::builtin_type::I8 => {
+ sz = 1; align = 1;
+ builtin::I8;
+ },
+ ast::builtin_type::INT => {
+ sz = store.arch._int;
+ align = store.arch._int;
+ builtin::INT;
+ },
+ ast::builtin_type::RUNE => {
+ sz = 4; align = 4;
+ builtin::RUNE;
+ },
+ ast::builtin_type::SIZE => {
+ sz = store.arch._size;
+ align = store.arch._size;
+ builtin::SIZE;
+ },
+ ast::builtin_type::STR => {
+ sz += store.arch._pointer;
+ sz += sz % store.arch._size + store.arch._size;
+ sz += store.arch._size;
+ align = if (store.arch._size > store.arch._pointer)
+ store.arch._size
+ else
+ store.arch._pointer;
+ builtin::STR;
+ },
+ ast::builtin_type::U16 => {
+ sz = 2; align = 2;
+ builtin::U16;
+ },
+ ast::builtin_type::U32 => {
+ sz = 4; align = 4;
+ builtin::U32;
+ },
+ ast::builtin_type::U64 => {
+ sz = 8; align = 8;
+ builtin::U64;
+ },
+ ast::builtin_type::U8 => {
+ sz = 1; align = 1;
+ builtin::U8;
+ },
+ ast::builtin_type::UINT => {
+ sz = store.arch._int;
+ align = store.arch._int;
+ builtin::UINT;
+ },
+ ast::builtin_type::UINTPTR => {
+ sz = store.arch._pointer;
+ align = store.arch._pointer;
+ builtin::UINTPTR;
+ },
+ ast::builtin_type::VOID => {
+ sz = 0; align = 0;
+ builtin::VOID;
+ },
+ ast::builtin_type::NULL => builtin::NULL,
+ ast::builtin_type::ICONST,
+ ast::builtin_type::FCONST => abort(), // TODO?
+ },
+ p: ast::pointer_type => {
+ sz = store.arch._pointer;
+ align = store.arch._pointer;
+ pointer {
+ referent = lookup(store, p.referent)?,
+ flags = p.flags: pointer_flags,
+ };
},
* => abort(), // TODO
};
return _type {
flags = atype.flags: flags,
_type = underlying,
+ sz = sz,
+ align = align,
};
};
fn type_finish(t: *_type) void = {
match (t._type) {
- a: alias => ast::ident_free(a),
+ a: alias => ast::ident_free(a.id),
builtin => void,
pointer => void,
* => abort(), // TODO
diff --git a/hare/types/types.ha b/hare/types/types.ha
@@ -1,7 +1,11 @@
use hare::ast;
// A type alias.
-export type alias = ast::ident;
+export type alias = struct {
+ id: ast::ident,
+ // null for forward referenced types
+ _type: const nullable *_type,
+};
// A built-in primitive type (int, bool, str, etc).
export type builtin = enum u8 {
@@ -31,8 +35,14 @@ export type flags = enum u8 {
ERROR = 1 << 1,
};
+// The sz field of [[_type]] is set to this value to indicate that the size of
+// the type is undefined.
+export def SIZE_UNDEFINED: size = -1: size;
+
// A Hare type.
export type _type = struct {
flags: flags,
_type: (alias | builtin | pointer),
+ sz: size,
+ align: size,
};
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -360,6 +360,7 @@ hare_ast() {
hare_types() {
gen_srcs hare::types \
+ arch.ha \
hash.ha \
store.ha \
types.ha
diff --git a/stdlib.mk b/stdlib.mk
@@ -578,6 +578,7 @@ $(HARECACHE)/hare/parse/hare_parse.ssa: $(stdlib_hare_parse_srcs) $(stdlib_rt) $
# hare::types
stdlib_hare_types_srcs= \
+ $(STDLIB)/hare/types/arch.ha \
$(STDLIB)/hare/types/hash.ha \
$(STDLIB)/hare/types/store.ha \
$(STDLIB)/hare/types/types.ha
@@ -1548,6 +1549,7 @@ $(TESTCACHE)/hare/parse/hare_parse.ssa: $(testlib_hare_parse_srcs) $(testlib_rt)
# hare::types
testlib_hare_types_srcs= \
+ $(STDLIB)/hare/types/arch.ha \
$(STDLIB)/hare/types/hash.ha \
$(STDLIB)/hare/types/store.ha \
$(STDLIB)/hare/types/types.ha