commit a79ab2a24937d20e97dc6be79c52574e346ca8f2
parent 9b6817741924a014cb6a7906997fd4beef6801ab
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 4 May 2021 16:38:24 -0400
hare::types: implement tuples
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
2 files changed, 71 insertions(+), 1 deletion(-)
diff --git a/hare/types/+test.ha b/hare/types/+test.ha
@@ -91,7 +91,7 @@ fn resolve(
assert(y.offs == 0);
assert(y._type._type as builtin == builtin::INT);
- // Alignment
+ // Padding
let atype = parse_type("struct { w: u8, x: u32, y: u8, z: u64 }");
defer ast::type_free(atype);
let htype = lookup(st, &atype)!;
@@ -195,3 +195,35 @@ fn resolve(
assert(stype.fields[2].name == "z");
assert(stype.fields[2].offs == 32);
};
+
+@test fn tuples() void = {
+ let st = store(x86_64, &resolve, null);
+ defer store_free(st);
+
+ // Basic case
+ let atype = parse_type("(int, int)");
+ defer ast::type_free(atype);
+ let htype = lookup(st, &atype)!;
+ assert(htype.sz == 8);
+ assert(htype.align == 4);
+ let tup = htype._type as tuple;
+ assert(len(tup) == 2);
+
+ assert(tup[0].offs == 0);
+ assert(tup[0]._type._type as builtin == builtin::INT);
+ assert(tup[1].offs == 4);
+ assert(tup[1]._type._type as builtin == builtin::INT);
+
+ // Padding
+ let atype = parse_type("(i8, i32, i8, i64)");
+ defer ast::type_free(atype);
+ let htype = lookup(st, &atype)!;
+ assert(htype.sz == 24);
+ assert(htype.align == 8);
+
+ let tup = htype._type as tuple;
+ assert(tup[0].offs == 0);
+ assert(tup[1].offs == 4);
+ assert(tup[2].offs == 8);
+ assert(tup[3].offs == 16);
+};
diff --git a/hare/types/store.ha b/hare/types/store.ha
@@ -224,6 +224,20 @@ fn fromast(store: *typestore, atype: *ast::_type) (_type | deferred | error) = {
};
st;
},
+ tu: ast::tuple_type => {
+ let tu = tuple_from_ast(store, tu)?;
+ sz = 0; align = 0;
+ for (let i = 0z; i < len(tu); i += 1) {
+ const value = tu[i];
+ if (value.offs + value._type.sz > sz) {
+ sz = value.offs + value._type.sz;
+ };
+ if (value._type.align > align) {
+ align = value._type.align;
+ };
+ };
+ tu;
+ },
* => abort(), // TODO
};
return _type {
@@ -314,6 +328,30 @@ fn struct_from_ast(
};
};
+fn tuple_from_ast(
+ store: *typestore,
+ membs: ast::tuple_type,
+) (tuple | deferred | error) = {
+ let values: []tuple_value = [];
+ let offs = 0z;
+ for (let i = 0z; i < len(membs); i += 1) {
+ const val = membs[i];
+ const vtype = lookup(store, val)?;
+
+ if (offs % vtype.align != 0) {
+ offs += vtype.align - (offs % vtype.align);
+ };
+
+ append(values, tuple_value {
+ _type = vtype,
+ offs = offs,
+ });
+
+ offs += vtype.sz;
+ };
+ return values;
+};
+
fn field_cmp(a: const *void, b: const *void) int = {
const a = a: const *struct_field, b = b: *const struct_field;
return ascii::strcmp(a.name, b.name) as int;