From 7aaa45187b87573080e92671336ed623f02428a8 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 19 May 2022 19:08:57 -0700 Subject: ffi: bugfix: transition between bitfield cell sizes. * ffi.c (make_ffi_type_struct): When a bitfield is declared for a type whose alignment is different from that of the previous member, then we start the new bitfield on a fresh alignment. As usual, if the previous member is a bitfield which left a partially filled byte, we skip to the next byte and then do the alignment. This seems to match GCC behavior. --- ffi.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ffi.c b/ffi.c index 364fa25a..5db3df87 100644 --- a/ffi.c +++ b/ffi.c @@ -3462,6 +3462,7 @@ static val make_ffi_type_struct(val syntax, val lisp_type, cobj(coerce(mem_t *, tft), ffi_type_cls, &ffi_type_struct_ops)); ucnum offs = 0; ucnum most_align = 1; + ucnum prev_align = 1; int need_out_handler = 0; int bit_offs = 0; const unsigned bits_int = 8 * sizeof(int); @@ -3527,6 +3528,13 @@ static val make_ffi_type_struct(val syntax, val lisp_type, setcheck(obj, slot); setcheck(obj, type); + if (mtft->bitfield && align != prev_align) { + if (bit_offs) + offs++; + offs = (offs + almask) & ~almask; + bit_offs = 0; + } + if (mtft->bitfield) { ucnum bits_type = 8 * size; ucnum bits = mtft->nelem; @@ -3593,6 +3601,8 @@ static val make_ffi_type_struct(val syntax, val lisp_type, most_align = align; } + prev_align = align; + need_out_handler = need_out_handler || mtft->out != 0; if (mtft->by_value_in) -- cgit v1.2.3