diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2017-11-13 08:51:41 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2017-11-13 10:16:51 -0800 |
commit | b1573a97e17b518723ab3f906eb6d521caed196d (patch) | |
tree | 2bcfe8f47a99d7ba9b46e75ed5bffd2ba37970e0 /src/lread.c | |
parent | 5d68dc9a2fd1b9b883db6bc1c226541b50de8bb1 (diff) | |
download | emacs-b1573a97e17b518723ab3f906eb6d521caed196d.tar.gz |
Use alignas to fix GCALIGN-related bugs
Use alignas and unions to specify alignments of objects needing
addresses that are at least a multiple of GCALIGNMENT. Using
these standard C facilities should be safer than relying on ad hoc
and poorly-understood features like GCC’s __attribute__
((aligned (N))), the root cause for recent porting bugs like
Bug#29040. The alignas macro was standardized by C11 and Gnulib
supports alignas for pre-C11 platforms. I have tested this on Sun
Studio 12 sparc (2007) and GCC 4.4.7 x86-64 (2012) as well as on
more recent platforms like GCC 7.2.1 (2017) on Fedora 26 (both
x86-64 and x86).
* lib-src/make-docfile.c (close_emacs_globals): lispsym is now
just an array of struct Lisp_Symbol, since struct Lisp_Symbol is
now properly aligned. All uses changed.
* src/alloc.c (NEXT_FREE_LISP_STRING): Just use the new u.next
member; this is simpler and safer than casting a pointer that
might not be aligned properly.
(aligned_Lisp_Symbol): Remove. No longer needed, now that struct
Lisp_Symbol is aligned properly. All uses replaced with struct
Lisp_Symbol.
* src/lisp.h (GCALIGNED): Remove, as it does not work as expected:
it can cause the natural alignment to be ignored. All uses
replaced by unions with a ‘char alignas (GCALIGNMENT)’ member as
described below.
(struct Lisp_Symbol, struct Lisp_Cons, struct Lisp_String):
Change definition from ‘struct TAG { MEMBERS };’ to
‘struct TAG { union { struct { MEMBERS } s; char alignas
(GCALIGNMENT) gcaligned; } u; };’. This guarantees ‘struct TAG’
to have an alignment that at least max (GCALIGNMENT, N) where N is
its old alignment. All uses like ‘PTR->MEMBER’ changed to
‘PTR->u.s.MEMBER’; these uses were supposed to be mostly private
anyway. Verify that the resulting ‘struct TAG’ is properly
aligned for Emacs.
(union vectorlike_header): New member ‘gcaligned’ to guarantee
that this type, and its containing types like ‘struct Lisp_Subr’,
‘struct buffer’ and ‘struct thread_state’, are all properly
aligned for Emacs.
(struct Lisp_String): New union member ‘next’, for the benefit
of NEXT_FREE_LISP_STRING.
(union Aligned_Cons, union Aligned_String): Remove. All uses
replaced by struct Lisp_Cons and struct Lisp_String, since they
are now properly aligned.
(USE_STACK_CONS, USE_STACK_STRING): Simplify now that we can
assume struct Lisp_Cons and struct Lisp_String are properly
aligned.
Diffstat (limited to 'src/lread.c')
-rw-r--r-- | src/lread.c | 52 |
1 files changed, 26 insertions, 26 deletions
diff --git a/src/lread.c b/src/lread.c index 33da8667228..b056f4aaf38 100644 --- a/src/lread.c +++ b/src/lread.c @@ -4043,14 +4043,14 @@ intern_sym (Lisp_Object sym, Lisp_Object obarray, Lisp_Object index) { Lisp_Object *ptr; - XSYMBOL (sym)->interned = (EQ (obarray, initial_obarray) - ? SYMBOL_INTERNED_IN_INITIAL_OBARRAY - : SYMBOL_INTERNED); + XSYMBOL (sym)->u.s.interned = (EQ (obarray, initial_obarray) + ? SYMBOL_INTERNED_IN_INITIAL_OBARRAY + : SYMBOL_INTERNED); if (SREF (SYMBOL_NAME (sym), 0) == ':' && EQ (obarray, initial_obarray)) { make_symbol_constant (sym); - XSYMBOL (sym)->redirect = SYMBOL_PLAINVAL; + XSYMBOL (sym)->u.s.redirect = SYMBOL_PLAINVAL; SET_SYMBOL_VAL (XSYMBOL (sym), sym); } @@ -4203,16 +4203,16 @@ usage: (unintern NAME OBARRAY) */) /* if (EQ (tem, Qnil) || EQ (tem, Qt)) error ("Attempt to unintern t or nil"); */ - XSYMBOL (tem)->interned = SYMBOL_UNINTERNED; + XSYMBOL (tem)->u.s.interned = SYMBOL_UNINTERNED; hash = oblookup_last_bucket_number; if (EQ (AREF (obarray, hash), tem)) { - if (XSYMBOL (tem)->next) + if (XSYMBOL (tem)->u.s.next) { Lisp_Object sym; - XSETSYMBOL (sym, XSYMBOL (tem)->next); + XSETSYMBOL (sym, XSYMBOL (tem)->u.s.next); ASET (obarray, hash, sym); } else @@ -4223,13 +4223,13 @@ usage: (unintern NAME OBARRAY) */) Lisp_Object tail, following; for (tail = AREF (obarray, hash); - XSYMBOL (tail)->next; + XSYMBOL (tail)->u.s.next; tail = following) { - XSETSYMBOL (following, XSYMBOL (tail)->next); + XSETSYMBOL (following, XSYMBOL (tail)->u.s.next); if (EQ (following, tem)) { - set_symbol_next (tail, XSYMBOL (following)->next); + set_symbol_next (tail, XSYMBOL (following)->u.s.next); break; } } @@ -4264,13 +4264,13 @@ oblookup (Lisp_Object obarray, register const char *ptr, ptrdiff_t size, ptrdiff else if (!SYMBOLP (bucket)) error ("Bad data in guts of obarray"); /* Like CADR error message. */ else - for (tail = bucket; ; XSETSYMBOL (tail, XSYMBOL (tail)->next)) + for (tail = bucket; ; XSETSYMBOL (tail, XSYMBOL (tail)->u.s.next)) { if (SBYTES (SYMBOL_NAME (tail)) == size_byte && SCHARS (SYMBOL_NAME (tail)) == size && !memcmp (SDATA (SYMBOL_NAME (tail)), ptr, size_byte)) return tail; - else if (XSYMBOL (tail)->next == 0) + else if (XSYMBOL (tail)->u.s.next == 0) break; } XSETINT (tem, hash); @@ -4290,9 +4290,9 @@ map_obarray (Lisp_Object obarray, void (*fn) (Lisp_Object, Lisp_Object), Lisp_Ob while (1) { (*fn) (tail, arg); - if (XSYMBOL (tail)->next == 0) + if (XSYMBOL (tail)->u.s.next == 0) break; - XSETSYMBOL (tail, XSYMBOL (tail)->next); + XSETSYMBOL (tail, XSYMBOL (tail)->u.s.next); } } } @@ -4332,12 +4332,12 @@ init_obarray (void) DEFSYM (Qnil, "nil"); SET_SYMBOL_VAL (XSYMBOL (Qnil), Qnil); make_symbol_constant (Qnil); - XSYMBOL (Qnil)->declared_special = true; + XSYMBOL (Qnil)->u.s.declared_special = true; DEFSYM (Qt, "t"); SET_SYMBOL_VAL (XSYMBOL (Qt), Qt); make_symbol_constant (Qt); - XSYMBOL (Qt)->declared_special = true; + XSYMBOL (Qt)->u.s.declared_special = true; /* Qt is correct even if CANNOT_DUMP. loadup.el will set to nil at end. */ Vpurify_flag = Qt; @@ -4361,7 +4361,7 @@ defalias (struct Lisp_Subr *sname, char *string) { Lisp_Object sym; sym = intern (string); - XSETSUBR (XSYMBOL (sym)->function, sname); + XSETSUBR (XSYMBOL (sym)->u.s.function, sname); } #endif /* NOTDEF */ @@ -4376,8 +4376,8 @@ defvar_int (struct Lisp_Intfwd *i_fwd, sym = intern_c_string (namestring); i_fwd->type = Lisp_Fwd_Int; i_fwd->intvar = address; - XSYMBOL (sym)->declared_special = 1; - XSYMBOL (sym)->redirect = SYMBOL_FORWARDED; + XSYMBOL (sym)->u.s.declared_special = true; + XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED; SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)i_fwd); } @@ -4391,8 +4391,8 @@ defvar_bool (struct Lisp_Boolfwd *b_fwd, sym = intern_c_string (namestring); b_fwd->type = Lisp_Fwd_Bool; b_fwd->boolvar = address; - XSYMBOL (sym)->declared_special = 1; - XSYMBOL (sym)->redirect = SYMBOL_FORWARDED; + XSYMBOL (sym)->u.s.declared_special = true; + XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED; SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)b_fwd); Vbyte_boolean_vars = Fcons (sym, Vbyte_boolean_vars); } @@ -4410,8 +4410,8 @@ defvar_lisp_nopro (struct Lisp_Objfwd *o_fwd, sym = intern_c_string (namestring); o_fwd->type = Lisp_Fwd_Obj; o_fwd->objvar = address; - XSYMBOL (sym)->declared_special = 1; - XSYMBOL (sym)->redirect = SYMBOL_FORWARDED; + XSYMBOL (sym)->u.s.declared_special = true; + XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED; SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)o_fwd); } @@ -4434,8 +4434,8 @@ defvar_kboard (struct Lisp_Kboard_Objfwd *ko_fwd, sym = intern_c_string (namestring); ko_fwd->type = Lisp_Fwd_Kboard_Obj; ko_fwd->offset = offset; - XSYMBOL (sym)->declared_special = 1; - XSYMBOL (sym)->redirect = SYMBOL_FORWARDED; + XSYMBOL (sym)->u.s.declared_special = true; + XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED; SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)ko_fwd); } @@ -4769,7 +4769,7 @@ to find all the symbols in an obarray, use `mapatoms'. */); DEFVAR_LISP ("values", Vvalues, doc: /* List of values of all expressions which were read, evaluated and printed. Order is reverse chronological. */); - XSYMBOL (intern ("values"))->declared_special = 0; + XSYMBOL (intern ("values"))->u.s.declared_special = true; DEFVAR_LISP ("standard-input", Vstandard_input, doc: /* Stream for read to get input from. |