LazyOffsetPtr currently relies on uint64_t being able to store a pointer
and, unless sizeof(uint64_t) == sizeof(void *), little endianness, since
getAddressOfPointer reinterprets the memory as a pointer. This also
doesn't properly respect the C++ object model.
As removing getAddressOfPointer would have wide-reaching implications,
improve the implementation to account for these problems by using
placement new and a suitably sized-and-aligned buffer, "right"-aligning
the objects on big-endian platforms so the LSBs are in the same place
for use as the discriminator.
Fixes: bc73ef0031b50f7443615fef614fb4ecaaa4bd11
Fixes: https://github.com/llvm/llvm-project/issues/111993
(cherry picked from commit 76196998e25b98d81abc437708622261810782ca)