On Sun, Nov 3, 2024 at 11:23 PM Lewis Hyatt <lhy...@gmail.com> wrote: > > libcpp makes use of the cpp_buffer pfile->a_buff to store things while it is > handling macros. It uses it to store pointers (cpp_hashnode*, for macro > arguments) and cpp_macro objects. This works fine because a cpp_hashnode* > and a cpp_macro have the same alignment requirement on either 32-bit or > 64-bit systems (namely, the same alignment as a pointer.) > > When 64-bit location_t is enabled on a 32-bit sytem, the alignment > requirement may cease to be the same, because the alignment requirement of a > cpp_macro object changes to that of a uint64_t, which be larger than that of > a pointer. It's not the case for x86 32-bit, but for example, on sparc, a > pointer has 4-byte alignment while a uint64_t has 8. In that case, > intermixing the two within the same cpp_buffer leads to a misaligned > access. The code path that triggers this is the one in _cpp_commit_buff in > which a hash table with its own allocator (i.e. ggc) is not being used, so > it doesn't happen within the compiler itself, but it happens in the other > libcpp clients, such as genmatch. > > Fix that up by ensuring _cpp_commit_buff commits a fully aligned chunk of the > buffer, so it's ready for anything it may be used for next. > > For good measure, also modify CPP_ALIGN so that it guarantees to return an > alignment at least the size of location_t. Currently it returns the max of > a pointer and a double. I am not aware of any platform where a double may > have smaller alignment than a uint64_t, but it does not hurt to add > location_t here to be sure.
OK. Thanks, Richard. > libcpp/ChangeLog: > > * lex.cc (_cpp_commit_buff): Make sure that the buffer is properly > aligned for the next allocation. > * internal.h (struct dummy): Make sure alignment is large enough for > a location_t, just in case. > --- > libcpp/internal.h | 1 + > libcpp/lex.cc | 10 ++++++++-- > 2 files changed, 9 insertions(+), 2 deletions(-) > > diff --git a/libcpp/internal.h b/libcpp/internal.h > index e65198e89da..358e77cd622 100644 > --- a/libcpp/internal.h > +++ b/libcpp/internal.h > @@ -85,6 +85,7 @@ struct dummy > { > double d; > int *p; > + location_t l; > } u; > }; > > diff --git a/libcpp/lex.cc b/libcpp/lex.cc > index 849447eb4d7..858970b5d17 100644 > --- a/libcpp/lex.cc > +++ b/libcpp/lex.cc > @@ -4997,7 +4997,8 @@ _cpp_aligned_alloc (cpp_reader *pfile, size_t len) > void * > _cpp_commit_buff (cpp_reader *pfile, size_t size) > { > - void *ptr = BUFF_FRONT (pfile->a_buff); > + const auto buff = pfile->a_buff; > + void *ptr = BUFF_FRONT (buff); > > if (pfile->hash_table->alloc_subobject) > { > @@ -5006,7 +5007,12 @@ _cpp_commit_buff (cpp_reader *pfile, size_t size) > ptr = copy; > } > else > - BUFF_FRONT (pfile->a_buff) += size; > + { > + BUFF_FRONT (buff) += size; > + /* Make sure the remaining space is maximally aligned for whatever this > + buffer holds next. */ > + BUFF_FRONT (buff) += BUFF_ROOM (buff) % DEFAULT_ALIGNMENT; > + } > > return ptr; > }