diff options
| author | Paul Eggert | 2017-11-13 08:51:41 -0800 |
|---|---|---|
| committer | Paul Eggert | 2017-11-13 10:16:51 -0800 |
| commit | b1573a97e17b518723ab3f906eb6d521caed196d (patch) | |
| tree | 2bcfe8f47a99d7ba9b46e75ed5bffd2ba37970e0 /src/eval.c | |
| parent | 5d68dc9a2fd1b9b883db6bc1c226541b50de8bb1 (diff) | |
| download | emacs-b1573a97e17b518723ab3f906eb6d521caed196d.tar.gz emacs-b1573a97e17b518723ab3f906eb6d521caed196d.zip | |
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/eval.c')
| -rw-r--r-- | src/eval.c | 59 |
1 files changed, 30 insertions, 29 deletions
diff --git a/src/eval.c b/src/eval.c index 52e4c96d4b2..40b47968be2 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -603,7 +603,7 @@ The return value is BASE-VARIABLE. */) | |||
| 603 | 603 | ||
| 604 | sym = XSYMBOL (new_alias); | 604 | sym = XSYMBOL (new_alias); |
| 605 | 605 | ||
| 606 | switch (sym->redirect) | 606 | switch (sym->u.s.redirect) |
| 607 | { | 607 | { |
| 608 | case SYMBOL_FORWARDED: | 608 | case SYMBOL_FORWARDED: |
| 609 | error ("Cannot make an internal variable an alias"); | 609 | error ("Cannot make an internal variable an alias"); |
| @@ -632,14 +632,14 @@ The return value is BASE-VARIABLE. */) | |||
| 632 | error ("Don't know how to make a let-bound variable an alias"); | 632 | error ("Don't know how to make a let-bound variable an alias"); |
| 633 | } | 633 | } |
| 634 | 634 | ||
| 635 | if (sym->trapped_write == SYMBOL_TRAPPED_WRITE) | 635 | if (sym->u.s.trapped_write == SYMBOL_TRAPPED_WRITE) |
| 636 | notify_variable_watchers (new_alias, base_variable, Qdefvaralias, Qnil); | 636 | notify_variable_watchers (new_alias, base_variable, Qdefvaralias, Qnil); |
| 637 | 637 | ||
| 638 | sym->declared_special = 1; | 638 | sym->u.s.declared_special = true; |
| 639 | XSYMBOL (base_variable)->declared_special = 1; | 639 | XSYMBOL (base_variable)->u.s.declared_special = true; |
| 640 | sym->redirect = SYMBOL_VARALIAS; | 640 | sym->u.s.redirect = SYMBOL_VARALIAS; |
| 641 | SET_SYMBOL_ALIAS (sym, XSYMBOL (base_variable)); | 641 | SET_SYMBOL_ALIAS (sym, XSYMBOL (base_variable)); |
| 642 | sym->trapped_write = XSYMBOL (base_variable)->trapped_write; | 642 | sym->u.s.trapped_write = XSYMBOL (base_variable)->u.s.trapped_write; |
| 643 | LOADHIST_ATTACH (new_alias); | 643 | LOADHIST_ATTACH (new_alias); |
| 644 | /* Even if docstring is nil: remove old docstring. */ | 644 | /* Even if docstring is nil: remove old docstring. */ |
| 645 | Fput (new_alias, Qvariable_documentation, docstring); | 645 | Fput (new_alias, Qvariable_documentation, docstring); |
| @@ -745,7 +745,7 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */) | |||
| 745 | tem = Fdefault_boundp (sym); | 745 | tem = Fdefault_boundp (sym); |
| 746 | 746 | ||
| 747 | /* Do it before evaluating the initial value, for self-references. */ | 747 | /* Do it before evaluating the initial value, for self-references. */ |
| 748 | XSYMBOL (sym)->declared_special = 1; | 748 | XSYMBOL (sym)->u.s.declared_special = true; |
| 749 | 749 | ||
| 750 | if (NILP (tem)) | 750 | if (NILP (tem)) |
| 751 | Fset_default (sym, eval_sub (XCAR (tail))); | 751 | Fset_default (sym, eval_sub (XCAR (tail))); |
| @@ -769,7 +769,7 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */) | |||
| 769 | LOADHIST_ATTACH (sym); | 769 | LOADHIST_ATTACH (sym); |
| 770 | } | 770 | } |
| 771 | else if (!NILP (Vinternal_interpreter_environment) | 771 | else if (!NILP (Vinternal_interpreter_environment) |
| 772 | && !XSYMBOL (sym)->declared_special) | 772 | && !XSYMBOL (sym)->u.s.declared_special) |
| 773 | /* A simple (defvar foo) with lexical scoping does "nothing" except | 773 | /* A simple (defvar foo) with lexical scoping does "nothing" except |
| 774 | declare that var to be dynamically scoped *locally* (i.e. within | 774 | declare that var to be dynamically scoped *locally* (i.e. within |
| 775 | the current file or let-block). */ | 775 | the current file or let-block). */ |
| @@ -818,7 +818,7 @@ usage: (defconst SYMBOL INITVALUE [DOCSTRING]) */) | |||
| 818 | if (!NILP (Vpurify_flag)) | 818 | if (!NILP (Vpurify_flag)) |
| 819 | tem = Fpurecopy (tem); | 819 | tem = Fpurecopy (tem); |
| 820 | Fset_default (sym, tem); | 820 | Fset_default (sym, tem); |
| 821 | XSYMBOL (sym)->declared_special = 1; | 821 | XSYMBOL (sym)->u.s.declared_special = true; |
| 822 | if (!NILP (docstring)) | 822 | if (!NILP (docstring)) |
| 823 | { | 823 | { |
| 824 | if (!NILP (Vpurify_flag)) | 824 | if (!NILP (Vpurify_flag)) |
| @@ -837,7 +837,7 @@ DEFUN ("internal-make-var-non-special", Fmake_var_non_special, | |||
| 837 | (Lisp_Object symbol) | 837 | (Lisp_Object symbol) |
| 838 | { | 838 | { |
| 839 | CHECK_SYMBOL (symbol); | 839 | CHECK_SYMBOL (symbol); |
| 840 | XSYMBOL (symbol)->declared_special = 0; | 840 | XSYMBOL (symbol)->u.s.declared_special = false; |
| 841 | return Qnil; | 841 | return Qnil; |
| 842 | } | 842 | } |
| 843 | 843 | ||
| @@ -877,7 +877,7 @@ usage: (let* VARLIST BODY...) */) | |||
| 877 | } | 877 | } |
| 878 | 878 | ||
| 879 | if (!NILP (lexenv) && SYMBOLP (var) | 879 | if (!NILP (lexenv) && SYMBOLP (var) |
| 880 | && !XSYMBOL (var)->declared_special | 880 | && !XSYMBOL (var)->u.s.declared_special |
| 881 | && NILP (Fmemq (var, Vinternal_interpreter_environment))) | 881 | && NILP (Fmemq (var, Vinternal_interpreter_environment))) |
| 882 | /* Lexically bind VAR by adding it to the interpreter's binding | 882 | /* Lexically bind VAR by adding it to the interpreter's binding |
| 883 | alist. */ | 883 | alist. */ |
| @@ -953,7 +953,7 @@ usage: (let VARLIST BODY...) */) | |||
| 953 | tem = temps[argnum]; | 953 | tem = temps[argnum]; |
| 954 | 954 | ||
| 955 | if (!NILP (lexenv) && SYMBOLP (var) | 955 | if (!NILP (lexenv) && SYMBOLP (var) |
| 956 | && !XSYMBOL (var)->declared_special | 956 | && !XSYMBOL (var)->u.s.declared_special |
| 957 | && NILP (Fmemq (var, Vinternal_interpreter_environment))) | 957 | && NILP (Fmemq (var, Vinternal_interpreter_environment))) |
| 958 | /* Lexically bind VAR by adding it to the lexenv alist. */ | 958 | /* Lexically bind VAR by adding it to the lexenv alist. */ |
| 959 | lexenv = Fcons (Fcons (var, tem), lexenv); | 959 | lexenv = Fcons (Fcons (var, tem), lexenv); |
| @@ -1022,7 +1022,7 @@ definitions to shadow the loaded ones for use in file byte-compilation. */) | |||
| 1022 | tem = Fassq (sym, environment); | 1022 | tem = Fassq (sym, environment); |
| 1023 | if (NILP (tem)) | 1023 | if (NILP (tem)) |
| 1024 | { | 1024 | { |
| 1025 | def = XSYMBOL (sym)->function; | 1025 | def = XSYMBOL (sym)->u.s.function; |
| 1026 | if (!NILP (def)) | 1026 | if (!NILP (def)) |
| 1027 | continue; | 1027 | continue; |
| 1028 | } | 1028 | } |
| @@ -1932,8 +1932,8 @@ this does nothing and returns nil. */) | |||
| 1932 | CHECK_STRING (file); | 1932 | CHECK_STRING (file); |
| 1933 | 1933 | ||
| 1934 | /* If function is defined and not as an autoload, don't override. */ | 1934 | /* If function is defined and not as an autoload, don't override. */ |
| 1935 | if (!NILP (XSYMBOL (function)->function) | 1935 | if (!NILP (XSYMBOL (function)->u.s.function) |
| 1936 | && !AUTOLOADP (XSYMBOL (function)->function)) | 1936 | && !AUTOLOADP (XSYMBOL (function)->u.s.function)) |
| 1937 | return Qnil; | 1937 | return Qnil; |
| 1938 | 1938 | ||
| 1939 | if (!NILP (Vpurify_flag) && EQ (docstring, make_number (0))) | 1939 | if (!NILP (Vpurify_flag) && EQ (docstring, make_number (0))) |
| @@ -2164,7 +2164,7 @@ eval_sub (Lisp_Object form) | |||
| 2164 | fun = original_fun; | 2164 | fun = original_fun; |
| 2165 | if (!SYMBOLP (fun)) | 2165 | if (!SYMBOLP (fun)) |
| 2166 | fun = Ffunction (Fcons (fun, Qnil)); | 2166 | fun = Ffunction (Fcons (fun, Qnil)); |
| 2167 | else if (!NILP (fun) && (fun = XSYMBOL (fun)->function, SYMBOLP (fun))) | 2167 | else if (!NILP (fun) && (fun = XSYMBOL (fun)->u.s.function, SYMBOLP (fun))) |
| 2168 | fun = indirect_function (fun); | 2168 | fun = indirect_function (fun); |
| 2169 | 2169 | ||
| 2170 | if (SUBRP (fun)) | 2170 | if (SUBRP (fun)) |
| @@ -2347,7 +2347,7 @@ usage: (apply FUNCTION &rest ARGUMENTS) */) | |||
| 2347 | 2347 | ||
| 2348 | /* Optimize for no indirection. */ | 2348 | /* Optimize for no indirection. */ |
| 2349 | if (SYMBOLP (fun) && !NILP (fun) | 2349 | if (SYMBOLP (fun) && !NILP (fun) |
| 2350 | && (fun = XSYMBOL (fun)->function, SYMBOLP (fun))) | 2350 | && (fun = XSYMBOL (fun)->u.s.function, SYMBOLP (fun))) |
| 2351 | { | 2351 | { |
| 2352 | fun = indirect_function (fun); | 2352 | fun = indirect_function (fun); |
| 2353 | if (NILP (fun)) | 2353 | if (NILP (fun)) |
| @@ -2759,7 +2759,7 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */) | |||
| 2759 | /* Optimize for no indirection. */ | 2759 | /* Optimize for no indirection. */ |
| 2760 | fun = original_fun; | 2760 | fun = original_fun; |
| 2761 | if (SYMBOLP (fun) && !NILP (fun) | 2761 | if (SYMBOLP (fun) && !NILP (fun) |
| 2762 | && (fun = XSYMBOL (fun)->function, SYMBOLP (fun))) | 2762 | && (fun = XSYMBOL (fun)->u.s.function, SYMBOLP (fun))) |
| 2763 | fun = indirect_function (fun); | 2763 | fun = indirect_function (fun); |
| 2764 | 2764 | ||
| 2765 | if (SUBRP (fun)) | 2765 | if (SUBRP (fun)) |
| @@ -3075,7 +3075,7 @@ function with `&rest' args, or `unevalled' for a special form. */) | |||
| 3075 | function = original; | 3075 | function = original; |
| 3076 | if (SYMBOLP (function) && !NILP (function)) | 3076 | if (SYMBOLP (function) && !NILP (function)) |
| 3077 | { | 3077 | { |
| 3078 | function = XSYMBOL (function)->function; | 3078 | function = XSYMBOL (function)->u.s.function; |
| 3079 | if (SYMBOLP (function)) | 3079 | if (SYMBOLP (function)) |
| 3080 | function = indirect_function (function); | 3080 | function = indirect_function (function); |
| 3081 | } | 3081 | } |
| @@ -3214,7 +3214,7 @@ let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol) | |||
| 3214 | if ((--p)->kind > SPECPDL_LET) | 3214 | if ((--p)->kind > SPECPDL_LET) |
| 3215 | { | 3215 | { |
| 3216 | struct Lisp_Symbol *let_bound_symbol = XSYMBOL (specpdl_symbol (p)); | 3216 | struct Lisp_Symbol *let_bound_symbol = XSYMBOL (specpdl_symbol (p)); |
| 3217 | eassert (let_bound_symbol->redirect != SYMBOL_VARALIAS); | 3217 | eassert (let_bound_symbol->u.s.redirect != SYMBOL_VARALIAS); |
| 3218 | if (symbol == let_bound_symbol | 3218 | if (symbol == let_bound_symbol |
| 3219 | && EQ (specpdl_where (p), buf)) | 3219 | && EQ (specpdl_where (p), buf)) |
| 3220 | return 1; | 3220 | return 1; |
| @@ -3227,10 +3227,10 @@ static void | |||
| 3227 | do_specbind (struct Lisp_Symbol *sym, union specbinding *bind, | 3227 | do_specbind (struct Lisp_Symbol *sym, union specbinding *bind, |
| 3228 | Lisp_Object value, enum Set_Internal_Bind bindflag) | 3228 | Lisp_Object value, enum Set_Internal_Bind bindflag) |
| 3229 | { | 3229 | { |
| 3230 | switch (sym->redirect) | 3230 | switch (sym->u.s.redirect) |
| 3231 | { | 3231 | { |
| 3232 | case SYMBOL_PLAINVAL: | 3232 | case SYMBOL_PLAINVAL: |
| 3233 | if (!sym->trapped_write) | 3233 | if (!sym->u.s.trapped_write) |
| 3234 | SET_SYMBOL_VAL (sym, value); | 3234 | SET_SYMBOL_VAL (sym, value); |
| 3235 | else | 3235 | else |
| 3236 | set_internal (specpdl_symbol (bind), value, Qnil, bindflag); | 3236 | set_internal (specpdl_symbol (bind), value, Qnil, bindflag); |
| @@ -3274,7 +3274,7 @@ specbind (Lisp_Object symbol, Lisp_Object value) | |||
| 3274 | sym = XSYMBOL (symbol); | 3274 | sym = XSYMBOL (symbol); |
| 3275 | 3275 | ||
| 3276 | start: | 3276 | start: |
| 3277 | switch (sym->redirect) | 3277 | switch (sym->u.s.redirect) |
| 3278 | { | 3278 | { |
| 3279 | case SYMBOL_VARALIAS: | 3279 | case SYMBOL_VARALIAS: |
| 3280 | sym = indirect_variable (sym); XSETSYMBOL (symbol, sym); goto start; | 3280 | sym = indirect_variable (sym); XSETSYMBOL (symbol, sym); goto start; |
| @@ -3298,10 +3298,10 @@ specbind (Lisp_Object symbol, Lisp_Object value) | |||
| 3298 | specpdl_ptr->let.where = Fcurrent_buffer (); | 3298 | specpdl_ptr->let.where = Fcurrent_buffer (); |
| 3299 | specpdl_ptr->let.saved_value = Qnil; | 3299 | specpdl_ptr->let.saved_value = Qnil; |
| 3300 | 3300 | ||
| 3301 | eassert (sym->redirect != SYMBOL_LOCALIZED | 3301 | eassert (sym->u.s.redirect != SYMBOL_LOCALIZED |
| 3302 | || (EQ (SYMBOL_BLV (sym)->where, Fcurrent_buffer ()))); | 3302 | || (EQ (SYMBOL_BLV (sym)->where, Fcurrent_buffer ()))); |
| 3303 | 3303 | ||
| 3304 | if (sym->redirect == SYMBOL_LOCALIZED) | 3304 | if (sym->u.s.redirect == SYMBOL_LOCALIZED) |
| 3305 | { | 3305 | { |
| 3306 | if (!blv_found (SYMBOL_BLV (sym))) | 3306 | if (!blv_found (SYMBOL_BLV (sym))) |
| 3307 | specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT; | 3307 | specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT; |
| @@ -3412,9 +3412,9 @@ do_one_unbind (union specbinding *this_binding, bool unwinding, | |||
| 3412 | { /* If variable has a trivial value (no forwarding), and isn't | 3412 | { /* If variable has a trivial value (no forwarding), and isn't |
| 3413 | trapped, we can just set it. */ | 3413 | trapped, we can just set it. */ |
| 3414 | Lisp_Object sym = specpdl_symbol (this_binding); | 3414 | Lisp_Object sym = specpdl_symbol (this_binding); |
| 3415 | if (SYMBOLP (sym) && XSYMBOL (sym)->redirect == SYMBOL_PLAINVAL) | 3415 | if (SYMBOLP (sym) && XSYMBOL (sym)->u.s.redirect == SYMBOL_PLAINVAL) |
| 3416 | { | 3416 | { |
| 3417 | if (XSYMBOL (sym)->trapped_write == SYMBOL_UNTRAPPED_WRITE) | 3417 | if (XSYMBOL (sym)->u.s.trapped_write == SYMBOL_UNTRAPPED_WRITE) |
| 3418 | SET_SYMBOL_VAL (XSYMBOL (sym), specpdl_old_value (this_binding)); | 3418 | SET_SYMBOL_VAL (XSYMBOL (sym), specpdl_old_value (this_binding)); |
| 3419 | else | 3419 | else |
| 3420 | set_internal (sym, specpdl_old_value (this_binding), | 3420 | set_internal (sym, specpdl_old_value (this_binding), |
| @@ -3546,7 +3546,7 @@ context where binding is lexical by default. */) | |||
| 3546 | (Lisp_Object symbol) | 3546 | (Lisp_Object symbol) |
| 3547 | { | 3547 | { |
| 3548 | CHECK_SYMBOL (symbol); | 3548 | CHECK_SYMBOL (symbol); |
| 3549 | return XSYMBOL (symbol)->declared_special ? Qt : Qnil; | 3549 | return XSYMBOL (symbol)->u.s.declared_special ? Qt : Qnil; |
| 3550 | } | 3550 | } |
| 3551 | 3551 | ||
| 3552 | 3552 | ||
| @@ -3702,7 +3702,8 @@ backtrace_eval_unrewind (int distance) | |||
| 3702 | just set it. No need to check for constant symbols here, | 3702 | just set it. No need to check for constant symbols here, |
| 3703 | since that was already done by specbind. */ | 3703 | since that was already done by specbind. */ |
| 3704 | Lisp_Object sym = specpdl_symbol (tmp); | 3704 | Lisp_Object sym = specpdl_symbol (tmp); |
| 3705 | if (SYMBOLP (sym) && XSYMBOL (sym)->redirect == SYMBOL_PLAINVAL) | 3705 | if (SYMBOLP (sym) |
| 3706 | && XSYMBOL (sym)->u.s.redirect == SYMBOL_PLAINVAL) | ||
| 3706 | { | 3707 | { |
| 3707 | Lisp_Object old_value = specpdl_old_value (tmp); | 3708 | Lisp_Object old_value = specpdl_old_value (tmp); |
| 3708 | set_specpdl_old_value (tmp, SYMBOL_VAL (XSYMBOL (sym))); | 3709 | set_specpdl_old_value (tmp, SYMBOL_VAL (XSYMBOL (sym))); |