On 26/12/2020 17:51, Luc Van Oostenryck wrote: > There is (at least) 2 ways by which packed bitfields doesn't > follow normal layout/access rules and as consequence can't (always) > be accessed the usual way (load the whole underlying word, then shift > and mask to isolate the bitfield). > > At least two different cases are a concern: > 1) there is no padding at the end of a bitfield sequence. For example, > the following struct is only 3 bytes width: > struct s { > int f:24; > } __packed; > So, trying to access the bitfield by first doing a 32-bit load > will create an out-of-bound access. > > 2) a bitfield smaller than one word may need more than one word to be > accessed. For example, with the following struct > struct { > int a:5; > int f:30; > int z:5; > } __packed; > the bitfield 'f', while smaller than one 32-bit word, can't be accessed > with a single 32-bit access. > > At machine level, these bitfields should be accessed with several, possibly > smaller, loads and their corresponding values reconstructed form these, s/form/from/ > making things much more complicated than for non-packed bitfields. > > But at IR level, things can be a little more flexible and things can stay > simple by using sub-word or super-word accesses (until these need to > be lowered to be usable at machine level). In other words, the example here > can be safely accessed with respectively a 24-bit and a 40-bit load. > This is what is done in this patch. Hmm, I didn't know the IR could represent this! ;-) Is the 'lowering' code already present? Maybe next patch. ATB, Ramsay Jones > --- > linearize.c | 13 +++++++++++-- > symbol.h | 1 + > 2 files changed, 12 insertions(+), 2 deletions(-) > > diff --git a/linearize.c b/linearize.c > index 0250c6bb17ef..e80715ab2458 100644 > --- a/linearize.c > +++ b/linearize.c > @@ -977,8 +977,17 @@ static struct symbol *bitfield_base_type(struct symbol *sym) > if (sym) { > if (sym->type == SYM_NODE) > base = base->ctype.base_type; > - if (base->type == SYM_BITFIELD) > - return base->ctype.base_type; > + if (base->type == SYM_BITFIELD) { > + base = base->ctype.base_type; > + if (sym->packed) { > + int size = bits_to_bytes(sym->bit_offset + sym->bit_size); > + sym = __alloc_symbol(0); > + *sym = *base; > + sym->bit_size = bytes_to_bits(size); > + return sym; > + } > + return base; > + } > } > return sym; > } > diff --git a/symbol.h b/symbol.h > index 5c5a7f12affa..866d57522f49 100644 > --- a/symbol.h > +++ b/symbol.h > @@ -192,6 +192,7 @@ struct symbol { > accessed:1, > builtin:1, > torename:1, > + packed:1, > transparent_union:1; > int rank:3; // arithmetic's rank > struct expression *array_size; >