commit 75e23a3629cfbfb134b76c1d1ff5aebf43aa103b
parent e5bfff86c09a0ed4a82baabe3f9bc7b91b2348a9
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 4 May 2021 14:00:21 -0400
hare::types: fix embedded union offset computation
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
2 files changed, 35 insertions(+), 18 deletions(-)
diff --git a/hare/types/+test.ha b/hare/types/+test.ha
@@ -114,20 +114,23 @@ fn parse_type(in: str) ast::_type = {
z: int,
q: int,
},
+ p: int,
}");
defer ast::type_free(atype);
let htype = lookup(st, &atype)!;
- assert(htype.sz == 16);
+ assert(htype.sz == 20);
assert(htype.align == 4);
let stype = htype._type as _struct;
- assert(stype.fields[0].name == "q");
- assert(stype.fields[0].offs == 12);
- assert(stype.fields[1].name == "x");
- assert(stype.fields[1].offs == 0);
- assert(stype.fields[2].name == "y");
- assert(stype.fields[2].offs == 4);
- assert(stype.fields[3].name == "z");
- assert(stype.fields[3].offs == 8);
+ assert(stype.fields[0].name == "p");
+ assert(stype.fields[0].offs == 16);
+ assert(stype.fields[1].name == "q");
+ assert(stype.fields[1].offs == 12);
+ assert(stype.fields[2].name == "x");
+ assert(stype.fields[2].offs == 0);
+ assert(stype.fields[3].name == "y");
+ assert(stype.fields[3].offs == 4);
+ assert(stype.fields[4].name == "z");
+ assert(stype.fields[4].offs == 8);
// Embedded union
let atype = parse_type("struct {
@@ -137,20 +140,23 @@ fn parse_type(in: str) ast::_type = {
z: int,
q: int,
},
+ p: int,
}");
defer ast::type_free(atype);
let htype = lookup(st, &atype)!;
- assert(htype.sz == 12);
+ assert(htype.sz == 16);
assert(htype.align == 4);
let stype = htype._type as _struct;
- assert(stype.fields[0].name == "q");
- assert(stype.fields[0].offs == 8);
- assert(stype.fields[1].name == "x");
- assert(stype.fields[1].offs == 0);
- assert(stype.fields[2].name == "y");
- assert(stype.fields[2].offs == 4);
- assert(stype.fields[3].name == "z");
- assert(stype.fields[3].offs == 8);
+ assert(stype.fields[0].name == "p");
+ assert(stype.fields[0].offs == 12);
+ assert(stype.fields[1].name == "q");
+ assert(stype.fields[1].offs == 8);
+ assert(stype.fields[2].name == "x");
+ assert(stype.fields[2].offs == 0);
+ assert(stype.fields[3].name == "y");
+ assert(stype.fields[3].offs == 4);
+ assert(stype.fields[4].name == "z");
+ assert(stype.fields[4].offs == 8);
// Embedded (struct) alias
// TODO
diff --git a/hare/types/store.ha b/hare/types/store.ha
@@ -237,6 +237,7 @@ fn _struct_from_ast(
fields: *[]struct_field,
offs: *size,
) (void | deferred | error) = {
+ let nfields = len(*fields);
for (let i = 0z; i < len(membs); i += 1) {
*offs = match (membs[i]._offset) {
ex: *ast::expr => match (store.resolve) {
@@ -282,6 +283,16 @@ fn _struct_from_ast(
*offs += _type.sz;
};
};
+
+ if (is_union) {
+ let max = 0z;
+ for (let i = nfields; i < len(*fields); i += 1) {
+ if (fields[i].offs + fields[i]._type.sz > max) {
+ max = fields[i].offs + fields[i]._type.sz;
+ };
+ };
+ *offs = max;
+ };
};
fn struct_from_ast(