hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Mhare/types/+test.ha | 42++++++++++++++++++++++++------------------
Mhare/types/store.ha | 11+++++++++++
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(