diff --git a/include/mruby/boxing_word.h b/include/mruby/boxing_word.h index 7fb88d974..4fbbd3b31 100644 --- a/include/mruby/boxing_word.h +++ b/include/mruby/boxing_word.h @@ -14,8 +14,37 @@ #ifndef MRB_NO_FLOAT struct RFloat { MRB_OBJECT_HEADER; +#ifdef MRB_WORDBOX_NO_FLOAT_TRUNCATE + /* avoid 8-byte alignment on 32-bit; use memcpy-based accessors */ + char f[sizeof(mrb_float)]; +#else mrb_float f; +#endif }; + +#include + +static inline mrb_float +mrb_rfloat_value(const struct RFloat *p) +{ +#ifdef MRB_WORDBOX_NO_FLOAT_TRUNCATE + mrb_float f; + memcpy(&f, p->f, sizeof(mrb_float)); + return f; +#else + return p->f; +#endif +} + +static inline void +mrb_rfloat_set(struct RFloat *p, mrb_float f) +{ +#ifdef MRB_WORDBOX_NO_FLOAT_TRUNCATE + memcpy(p->f, &f, sizeof(mrb_float)); +#else + p->f = f; +#endif +} #endif struct RInteger { @@ -155,7 +184,7 @@ MRB_API mrb_value mrb_boxing_int_value(struct mrb_state*, mrb_int); MRB_API mrb_float mrb_word_boxing_value_float(mrb_value v); #define mrb_float(o) mrb_word_boxing_value_float(o) #else -#define mrb_float(o) mrb_val_union(o).fp->f +#define mrb_float(o) mrb_rfloat_value(mrb_val_union(o).fp) #endif #endif #define mrb_fixnum(o) (mrb_int)(((intptr_t)(o).w) >> WORDBOX_FIXNUM_SHIFT) diff --git a/src/class.c b/src/class.c index 04eeb562d..1f95a08d6 100644 --- a/src/class.c +++ b/src/class.c @@ -3997,7 +3997,7 @@ init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj) case MRB_TT_FLOAT: { struct RFloat *f = (struct RFloat*)mrb_obj_ptr(dest); - f->f = mrb_float(obj); + mrb_rfloat_set(f, mrb_float(obj)); } break; #endif diff --git a/src/etc.c b/src/etc.c index d45bbeee5..c35bf262c 100644 --- a/src/etc.c +++ b/src/etc.c @@ -288,7 +288,7 @@ mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f) #ifdef MRB_WORDBOX_NO_FLOAT_TRUNCATE v.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class); - v.fp->f = f; + mrb_rfloat_set(v.fp, f); v.bp->frozen = 1; #elif defined(MRB_64BIT) && defined(MRB_USE_FLOAT32) v.w = 0; @@ -323,7 +323,7 @@ mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f) else { float_heap: v.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class); - v.fp->f = f; + mrb_rfloat_set(v.fp, f); v.bp->frozen = 1; } } @@ -357,7 +357,7 @@ mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f) else { float_heap: v.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class); - v.fp->f = f; + mrb_rfloat_set(v.fp, f); v.bp->frozen = 1; } } @@ -399,7 +399,7 @@ mrb_word_boxing_value_float(mrb_value v) else { union mrb_value_ u; u.value = v; - return u.fp->f; + return mrb_rfloat_value(u.fp); } #else /* 32-bit + float32: rotation decoding */ @@ -420,7 +420,7 @@ mrb_word_boxing_value_float(mrb_value v) else { union mrb_value_ u; u.value = v; - return u.fp->f; + return mrb_rfloat_value(u.fp); } #endif }