@@ -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;
}
@@ -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;
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 from these, 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. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com> --- linearize.c | 13 +++++++++++-- symbol.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-)