[PATCH v4] ungetc: Guarantee single char pushback
Maciej W. Rozycki
macro@redhat.com
Thu Dec 12 12:16:23 GMT 2024
On Wed, 11 Dec 2024, Siddhesh Poyarekar wrote:
> > > - int _flags2;
> > > + int _flags2:24;
> > > + char _short_backupbuf[1];
> >
> > This doesn't create a 3-byte flags2, if that's what you're trying.
> > The underlying storage will still be int-sized, now with 8 unallocated bits.
>
> gcc and clang both appear to pack in the struct just fine, which effectively
> gives flags2 3-bytes storage and _short_backupbuf right next to it. Maybe
> I've misunderstood the issue you're trying to point out, could you please
> elaborate?
Indeed a bit-field does get packed with an eligible adjacent non-bitfield
member of the structure, although ISO C defers storage unit allocation to
the implementation and therefore I do believe it is down to the individual
platform-specific ABI.
Then e.g. the o32 MIPS ABI has this clause[1]:
"* Bit-fields can share a storage unit with other struct/union members,
including members that are not bit-fields. Of course, struct members
occupy different parts of the storage unit."
and the updated structure is laid out accordingly:
struct _IO_FILE {
int _flags; /* 0 4 */
char * _IO_read_ptr; /* 4 4 */
char * _IO_read_end; /* 8 4 */
char * _IO_read_base; /* 12 4 */
char * _IO_write_base; /* 16 4 */
char * _IO_write_ptr; /* 20 4 */
char * _IO_write_end; /* 24 4 */
char * _IO_buf_base; /* 28 4 */
char * _IO_buf_end; /* 32 4 */
char * _IO_save_base; /* 36 4 */
char * _IO_backup_base; /* 40 4 */
char * _IO_save_end; /* 44 4 */
struct _IO_marker * _markers; /* 48 4 */
struct _IO_FILE * _chain; /* 52 4 */
int _fileno; /* 56 4 */
/* XXX 3 bytes hole, try to pack */
/* Bitfield combined with previous fields */
static int _flags2 /* 0: 0 0 */
char _short_backupbuf[1]; /* 63 1 */
__off_t _old_offset; /* 64 4 */
short unsigned int _cur_column; /* 68 2 */
signed char _vtable_offset; /* 70 1 */
char _shortbuf[1]; /* 71 1 */
_IO_lock_t * _lock; /* 72 4 */
/* size: 76, cachelines: 1, members: 21, static members: 1 */
/* sum members: 85, holes: 1, sum holes: 3 */
/* last cacheline: 76 bytes */
/* BRAIN FART ALERT! 76 != 85 + 3(holes), diff = -12 */
};
(although the tool does seem confused a little here).
AFAICT from `place_field' in gcc/stor-layout.cc it is the same across all
the !TARGET_MS_BITFIELD_LAYOUT_P ABIs GCC supports, there's no provision
for a per-target variation.
Maciej
More information about the Libc-alpha
mailing list