brintos

brintos / glibc public Read only

0
0

wasm32: SIZE_MAX is unsigned-int-typed vs size_t = unsigned long; ssize_t stays int (mismatches %zd) — same type-identity class as #1 #2

Closed jdbrinton opened this issue · 1 comment
jdbrinton jdbrinton commented

Split out of #1 (found while fixing it, 2026-07-14). Pre-existing, NOT created by the #1 fix.

On the wasm32 port, clang's __SIZE_TYPE__ is unsigned long (so size_t from the compiler's stddef.h is unsigned long), but:

  • SIZE_MAX in <stdint.h> is still typed unsigned int (__WORDSIZE32_SIZE_ULONG is 0 for the port — it inherits sysdeps/wordsize-32/bits/wordsize.h, now overridden by sysdeps/wasm32/bits/wordsize.h from the #1 fix, which deliberately left this knob at 0), so SIZE_MAX is not type-identical to size_t.
  • ssize_t is __SWORD_TYPE == int, mismatching %zd and -Werror=format users, and SSIZE_MAX's type would drift from ssize_t if __WORDSIZE32_SIZE_ULONG were naively flipped.

Doing it right (per the #1 investigation): flip __WORDSIZE32_SIZE_ULONG=1 in sysdeps/wasm32/bits/wordsize.h and add a port bits/typesizes.h setting __SSIZE_T_TYPE = __SLONGWORD_TYPE (s390-32 precedent: sysdeps/unix/sysv/linux/s390/bits/typesizes.h), then validate with a full glibc rebuild — __SSIZE_T_TYPE feeds __ssize_t throughout the library ABI surface (type-identity only on wasm32; int/long both 32-bit).

All 32-bit so ABI-neutral; breaks type-strict C/C++ (_Generic, template deduction, format-string checking) exactly like #1.

Refs #1 (fixed on joel-dev, commit 6ba49279).

jdbrinton jdbrinton commented

Fixed (agent for joel, 2026-07-15), glibc 6a4d9e61a5 on joel-dev, pushed; pool rebuilt (2544 bitcode TUs) and the glibc image relinked against it. Both halves land together, per the #1 investigation (flipping the knob alone would have retyped SSIZE_MAX to long while ssize_t stayed int):

  • sysdeps/wasm32/bits/wordsize.h: __WORDSIZE32_SIZE_ULONG = 1SIZE_MAX becomes 4294967295UL, type-identical to size_t, and SSIZE_MAX becomes LONG_MAX.
  • new sysdeps/unix/sysv/linux/wasm32/bits/typesizes.h: __SSIZE_T_TYPE = __SLONGWORD_TYPE (the s390 -m31 precedent — "size_t is unsigned long, so ssize_t is long"), otherwise byte-identical to the generic Linux file.

Compile-time proof is now a tracked TU, distros/linux-6.12-glibc-bash-coreutils/tools/size-ssize-identity/check.c (superproject ecb8f63): _Generic(SIZE_MAX, unsigned long), _Generic((ssize_t)0, long), SSIZE_MAX long, sizeof(size_t)==4, %zd/%zu clean under -Wformat -Werror — compiles clean post-fix, and both RED probes (_Generic(SIZE_MAX, unsigned int), _Generic((ssize_t)0, int)) fail as they must. Honesty note: clang's -Wformat is width-lenient on same-width types, so the _Generic asserts are the discriminating proof, not the printf lines. ILP32 int↔long: type identity only, no ABI change — full userland (bash/gmp/coreutils/iproute2) rebuilt clean against the new headers, all gates green. Closing.

jdbrinton closed this as completed