diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2022-05-23 11:50:47 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2022-05-23 11:50:47 -0700 |
commit | 4666a2fa59648e02b057038aa68fa99958f34ecf (patch) | |
tree | 18da340538e98357a3fa4dbf4abde438f274e3c4 /txr.1 | |
parent | 16eb3d22a29911981371b98e83008f8741903cc8 (diff) | |
download | txr-4666a2fa59648e02b057038aa68fa99958f34ecf.tar.gz txr-4666a2fa59648e02b057038aa68fa99958f34ecf.tar.bz2 txr-4666a2fa59648e02b057038aa68fa99958f34ecf.zip |
ffi: bitfield tests and fixes.
The bitfield allocation rules are wrong. Some of it is due
to the recent changes which are based on incorrect analysis,
but reverting things doesn't fix it.
The idea that we compare the current member's alignment
with the previous is wrong; it is not borne out by empirical
tests with gcc. So we do a straight revert of that.
In GNU C, an __attribute__((aligned (N))) attribute applied
to a bitfield member will perform the requested alignment if,
evidently, the bit field is already being placed into a new
byte. (If the bit field is about to be packed into an existing
byte, then there is a warning about the align attribute being
ignored). Because we don't have alignment as a member attribute,
but only as a type attribute, we must implement a flag which
indicates that a type has had align applied to it (even if
the alignment didn't change) so we can then honor this in the
right place in the bitfield allocation code.
* ffi.c (struct txr_ffi_type): New attribute flag, aligned.
(make_ffi_type_struct): Remove the prev_align variable and
all related logic. Consolidate all alignment into one place,
which is done before we allocate the bitfield or regular member.
We align if the new member isn't a bitfield, or even if it is
a bitfield if it has the aligned attribute, or if the bitfield
is changing endian compared to the previous member (our local
rule, not from GNU C).
(ffi_type_compile): The align and pack operators now set the
aligned attribute, except in the (pack 1 ...) case which
semantically denotes lack of alignment.
* tests/017/bitfields.tl: New file.
* txr.1: Documented.
Diffstat (limited to 'txr.1')
-rw-r--r-- | txr.1 | 29 |
1 files changed, 23 insertions, 6 deletions
@@ -81293,12 +81293,29 @@ a structure can be read or written at the misaligned offsets depends on whether the individual members support it. If they are integer or floating-point types, or aggregates thereof, the usage is supported in a machine-independent manner. -Alignment interacts with bitfields. If a bitfield's type has an alignment -different from the previous member (whether that member is a bitfield or not), -then the bitfield is placed into a new cell, which is aligned according to -the alignment of its own type. The alignment of bitfields, other than -zero width bitfields, contributes to the determination of the most -strictly aligned member of the structure. +Alignment interacts with the allocation of bitfields in special ways. If +.meta width +is greater than 1, or regardless of +.meta width +if the operator is +.codn align , +the type is marked with a Boolean attribute indicating that it has +altered alignment. Then, when a bitfield is based on a type which has altered +alignment, then that bitfield isn't packed together with the previous +field, even if the allocation rules otherwise call for it. Due to the +alignment request, the byte offset is first adjusted according to the requested +alignment and the bit offset is reset to zero. The bit field is then allocated +at the new alignment. This requirement applies even if the requested alignment +is 1, which is possible via a combination of both +.code pack +and +.codn align , +both specified with a +.meta width +of 1. If the requested alignment for the type of a bitfield is 1, and +the previous member is a bitfield which has left a byte partially filled, +then the new bitfield starts on a fresh byte, even if it would otherwise +be packed with the previous bitfield. When .meta type |