diff options
-rw-r--r-- | ffi.c | 29 | ||||
-rw-r--r-- | txr.1 | 17 |
2 files changed, 24 insertions, 22 deletions
@@ -3293,6 +3293,7 @@ static val make_ffi_type_struct(val syntax, val lisp_type, ucnum unit_offs = offs & align_mask; ucnum bits_alloc = 8 * (offs - unit_offs) + bit_offs; ucnum room = bits_type - bits_alloc; + ucnum align = if3(slot, mtft->align, 1); if (bits == 0) { if (offs != unit_offs || bit_offs > 0) @@ -3307,11 +3308,6 @@ static val make_ffi_type_struct(val syntax, val lisp_type, bit_offs = bits_alloc = 0; } - if (bits_alloc == 0) { - if (most_align < (ucnum) mtft->align) - most_align = mtft->align; - } - memb[i].offs = offs; #if HAVE_LITTLE_ENDIAN @@ -3326,6 +3322,9 @@ static val make_ffi_type_struct(val syntax, val lisp_type, bit_offs += bits; offs += bit_offs / 8; bit_offs %= 8; + + if (most_align < align) + most_align = align; } else { ucnum align = mtft->align; ucnum almask = align - 1; @@ -3451,14 +3450,10 @@ static val make_ffi_type_union(val syntax, val use_existing, val self) setcheck(obj, slot); setcheck(obj, type); - if (most_align < (ucnum) mtft->align) - most_align = mtft->align; - - if (biggest_size < (ucnum) mtft->size) - biggest_size = mtft->size; - if (mtft->bitfield) { ucnum bits = mtft->nelem; + ucnum size = (bits + 7) / 8; + ucnum align = if3(slot, mtft->align, 1); if (bits == 0) { nmemb--, i--; @@ -3474,6 +3469,16 @@ static val make_ffi_type_union(val syntax, val use_existing, val self) mtft->mask = UINT_MAX; else mtft->mask = ((1U << bits) - 1) << mtft->shift; + + if (most_align < align) + most_align = align; + if (biggest_size < size) + biggest_size = size; + } else { + if (most_align < (ucnum) mtft->align) + most_align = mtft->align; + if (biggest_size < (ucnum) mtft->size) + biggest_size = mtft->size; } } @@ -3486,7 +3491,7 @@ static val make_ffi_type_union(val syntax, val use_existing, val self) tft->nelem = i; - tft->size = biggest_size; + tft->size = (biggest_size + most_align - 1) & ~(most_align - 1); tft->align = most_align; #if HAVE_LIBFFI @@ -69387,16 +69387,6 @@ bitfield, according to the bitfield's width, then the bitfield is placed into that unit. Otherwise, the bitfield is placed into the next available unit. -Whenever a bitfield is placed at the start of new unit of its size, -it is called the -.IR "leading bitfield" . -The alignment of the leading bitfield is taken into account for -the purposes of determining the most strictly aligned member of -the structure. This alignment property of the leading bitfield -can be altered with the -.code align -type operator, applied either to the bitfield type, or to its base type. - After a bitfield is placed, the values of .I O and @@ -69432,6 +69422,13 @@ is incremented by one to cover that byte. As the last allocation step, the size of the structure is then padded up to a size which is a multiple of the alignment of the most strictly aligned member. +A named bitfield contributes to the alignment of the structure, according to +its type, the same way as a non-bitfield member of the same type. +An unnamed bitfield doesn't contribute alignment, or else may be regarded as +having the weakest possible alignment, which is byte alignment. +If all of the members of a structure are unnamed bitfield members of any type, +it exhibits byte alignment. + The description isn't complete without a treatment of byte and bit order. Bitfield allocation follows an imaginary "bit endianness" whose direction follows the machine's byte order: most significant bits are allocated first on |