mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
boxing_word.h: use memcpy-based RFloat access for unaligned 32-bit
On 32-bit with MRB_WORDBOX_NO_FLOAT_TRUNCATE, RFloat stores a double (8-byte alignment) but GC heap slots only guarantee 4-byte alignment. Use char array + memcpy accessors to avoid misaligned access (SIGBUS on MIPS, undefined behavior per C standard). Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -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 <string.h>
|
||||
|
||||
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)
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user