From 297520852f4f0e11a34a8a867c13fdf03d83eafd Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mattias=20Engdeg=C3=A5rd?= Date: Wed, 2 Feb 2022 16:51:43 +0100 Subject: [PATCH] Turn specpdl_ref into a type of its own Wrap the specpdl_ref contents in a struct, which gives us some very useful type checking to make sure that all code that assumed integral specpdl refs has been converted. We only do this on 64-bit platforms, since those tend to have modern ABIs where small structs are optimised as scalars. In other words, this change should not affect the compiled code. * src/lisp.h (specpdl_ref): Now a struct on 64-bit platforms. (wrap_specpdl_ref, unwrap_specpdl_ref): New. (specpdl_count_to_ref, specpdl_ref_to_count) (specpdl_ref_eq, specpdl_ref_lt) (specpdl_ref_valid_p, make_invalid_specpdl_ref): Use new wrappers. --- src/lisp.h | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/lisp.h b/src/lisp.h index 3ff9dccc4ec..9b82307f675 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3350,45 +3350,79 @@ union specbinding } bt; }; +/* We use 64-bit platforms as a proxy for ones with ABIs that treat + small structs efficiently. */ +#if SIZE_MAX > 0xffffffff +#define WRAP_SPECPDL_REF 1 +#endif + /* Abstract reference to to a specpdl entry. */ +#ifdef WRAP_SPECPDL_REF +/* Use a proper type for specpdl_ref if it does not make the code slower, + since the type checking is quite useful. */ +typedef struct { ptrdiff_t n; } specpdl_ref; +#else typedef ptrdiff_t specpdl_ref; +#endif +/* Internal use only. */ INLINE specpdl_ref -specpdl_count_to_ref (ptrdiff_t count) +wrap_specpdl_ref (ptrdiff_t count) { +#ifdef WRAP_SPECPDL_REF + return (specpdl_ref) {.n = count}; +#else return count; +#endif } +/* Internal use only. */ INLINE ptrdiff_t -specpdl_ref_to_count (specpdl_ref ref) +unwrap_specpdl_ref (specpdl_ref ref) { +#ifdef WRAP_SPECPDL_REF + return ref.n; +#else return ref; +#endif +} + +INLINE specpdl_ref +specpdl_count_to_ref (ptrdiff_t count) +{ + return wrap_specpdl_ref (count); +} + +INLINE ptrdiff_t +specpdl_ref_to_count (specpdl_ref ref) +{ + return unwrap_specpdl_ref (ref); } /* Whether two `specpdl_ref' refer to the same entry. */ INLINE bool specpdl_ref_eq (specpdl_ref a, specpdl_ref b) { - return a == b; + return unwrap_specpdl_ref (a) == unwrap_specpdl_ref (b); } /* Whether `a' refers to an earlier entry than `b'. */ INLINE bool specpdl_ref_lt (specpdl_ref a, specpdl_ref b) { - return a < b; + return unwrap_specpdl_ref (a) < unwrap_specpdl_ref (b); } INLINE bool specpdl_ref_valid_p (specpdl_ref ref) { - return specpdl_ref_to_count (ref) >= 0; + return unwrap_specpdl_ref (ref) >= 0; } INLINE specpdl_ref make_invalid_specpdl_ref (void) { - return specpdl_count_to_ref (-1); + return wrap_specpdl_ref (-1); } /* Return a reference that is `delta' steps more recent than `ref'. -- 2.39.5