From 6dd5f05525d7a983e27e4db6ed125c1e63eb5c5a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 16 Oct 2025 17:50:03 +0900 Subject: [PATCH] mruby-random: split 64-bit state into two 32-bit values on 32-bit platforms on 32-bit systems, the rand_state struct with uint64_t state (8 bytes, 8-byte aligned) followed by uint32_t seed_value (4 bytes) resulted in 16 bytes due to padding, exceeding the 12-byte ISTRUCT_DATA_SIZE limit. this caused the static_assert at line 540 to fail. split the state field into state_lo and state_hi on MRB_32BIT platforms to achieve perfect 12-byte alignment (4+4+4) without padding. add GET_STATE/SET_STATE macros to provide uniform access across platforms. Co-authored-by: Claude --- mrbgems/mruby-random/src/random.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index f7fe32319..31765996d 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -38,14 +38,33 @@ #define PCG_INCREMENT 1442695040888963407ULL typedef struct rand_state { +#ifdef MRB_32BIT + /* On 32-bit platforms, split state to avoid alignment padding */ + uint32_t state_lo; + uint32_t state_hi; +#else uint64_t state; +#endif uint32_t seed_value; /* Track last seed for srand compatibility */ } rand_state; +/* Helper macros for 64-bit state access */ +#ifdef MRB_32BIT +# define GET_STATE(t) (((uint64_t)(t)->state_hi << 32) | (t)->state_lo) +# define SET_STATE(t, val) do { \ + uint64_t v_ = (val); \ + (t)->state_lo = (uint32_t)v_; \ + (t)->state_hi = (uint32_t)(v_ >> 32); \ + } while (0) +#else +# define GET_STATE(t) ((t)->state) +# define SET_STATE(t, val) ((t)->state = (val)) +#endif + static void rand_init(rand_state *t) { - t->state = 0x853c49e6748fea9bULL; + SET_STATE(t, 0x853c49e6748fea9bULL); t->seed_value = 521288629; } @@ -57,9 +76,9 @@ rand_seed(rand_state *t, uint32_t seed) uint32_t old_seed = t->seed_value; /* PCG initialization: state=0, step, add seed, step, then mix */ - t->state = 0; + SET_STATE(t, 0); rand_uint32(t); - t->state += seed; + SET_STATE(t, GET_STATE(t) + seed); for (int i = 0; i < 10; i++) { rand_uint32(t); } @@ -72,10 +91,10 @@ static uint32_t rand_uint32(rand_state *rng) { /* PCG-XSH-RR: XorShift High (xorshift), then Random Rotate */ - uint64_t oldstate = rng->state; + uint64_t oldstate = GET_STATE(rng); /* LCG step: advance internal state */ - rng->state = oldstate * PCG_MULTIPLIER + PCG_INCREMENT; + SET_STATE(rng, oldstate * PCG_MULTIPLIER + PCG_INCREMENT); /* Output function: xorshift, then rotate by top bits */ uint32_t xorshifted = (uint32_t)(((oldstate >> 18u) ^ oldstate) >> 27u);