aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
authorPaul Eggert2017-11-13 08:51:41 -0800
committerPaul Eggert2017-11-13 10:16:51 -0800
commitb1573a97e17b518723ab3f906eb6d521caed196d (patch)
tree2bcfe8f47a99d7ba9b46e75ed5bffd2ba37970e0 /src/eval.c
parent5d68dc9a2fd1b9b883db6bc1c226541b50de8bb1 (diff)
downloademacs-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.c59
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
3227do_specbind (struct Lisp_Symbol *sym, union specbinding *bind, 3227do_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)));