diff options
-rw-r--r-- | libguile/ChangeLog | 7 | ||||
-rw-r--r-- | libguile/inline.h | 20 | ||||
-rw-r--r-- | libguile/num2float.i.c | 8 | ||||
-rw-r--r-- | libguile/numbers.c | 11 |
4 files changed, 31 insertions, 15 deletions
diff --git a/libguile/ChangeLog b/libguile/ChangeLog index fb7da086c..13ac529d0 100644 --- a/libguile/ChangeLog +++ b/libguile/ChangeLog @@ -1,3 +1,10 @@ +2002-09-24 Gary Houston <ghouston@arglist.com> + + * inline.h (scm_double_cell): prevent reordering of statements + with any following code (for GCC 3 strict-aliasing). + * numbers.c (scm_make_real), num2float.i.c (FLOAT2NUM): removed + the earlier version of the reordering prevention. + 2002-09-19 Han-Wen Nienhuys <hanwen@cs.uu.nl> * inline.h (scm_double_cell): move SET_GCMARK set out of if body. diff --git a/libguile/inline.h b/libguile/inline.h index d4cd67606..393182b6a 100644 --- a/libguile/inline.h +++ b/libguile/inline.h @@ -215,6 +215,26 @@ scm_double_cell (scm_t_bits car, scm_t_bits cbr, #endif + /* When this function is inlined, it's possible that the last + SCM_GC_SET_CELL_WORD above will be adjacent to a following + initialization of z. E.g., it occurred in scm_make_real. GCC + from around version 3 (e.g., certainly 3.2) began taking + advantage of strict C aliasing rules which say that it's OK to + interchange the initialization above and the one below when the + pointer types appear to differ sufficiently. We don't want that, + of course. GCC allows this behaviour to be disabled with the + -fno-strict-aliasing option, but would also need to be supplied + by Guile users. Instead, the following statements prevent the + reordering. + */ +#ifdef __GNUC__ + asm volatile ("" : : : "memory"); +#else + /* portable version, just in case any other compiler does the same + thing. */ + scm_remember_upto_here_1 (z); +#endif + return z; } diff --git a/libguile/num2float.i.c b/libguile/num2float.i.c index 5fd9180c7..08687a875 100644 --- a/libguile/num2float.i.c +++ b/libguile/num2float.i.c @@ -31,12 +31,8 @@ NUM2FLOAT (SCM num, unsigned long int pos, const char *s_caller) SCM FLOAT2NUM (FTYPE n) { - SCM z; - z = scm_double_cell (scm_tc16_real, 0, 0, 0); - /* - See scm_make_real(). - */ - scm_remember_upto_here_1 (z); + SCM z = scm_double_cell (scm_tc16_real, 0, 0, 0); + SCM_REAL_VALUE (z) = n; return z; } diff --git a/libguile/numbers.c b/libguile/numbers.c index 8393c62ca..bb01d7ad3 100644 --- a/libguile/numbers.c +++ b/libguile/numbers.c @@ -3013,15 +3013,8 @@ SCM_DEFINE (scm_string_to_number, "string->number", 1, 1, 0, SCM scm_make_real (double x) { - SCM z; - z = scm_double_cell (scm_tc16_real, 0, 0, 0); - - /* - scm_double_cell is inlined. strict C aliasing rules say that it's - OK to interchange the initialization above and the one below. We - don't want that, of course. - */ - scm_remember_upto_here_1 (z); + SCM z = scm_double_cell (scm_tc16_real, 0, 0, 0); + SCM_REAL_VALUE (z) = x; return z; } |