aboutsummaryrefslogtreecommitdiffstats
path: root/src/buffer.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/buffer.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/buffer.c')
-rw-r--r--src/buffer.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/src/buffer.c b/src/buffer.c
index edeed55e8be..4ae5e811b07 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -61,7 +61,7 @@ struct buffer *all_buffers;
61 Setting the default value also goes through the alist of buffers 61 Setting the default value also goes through the alist of buffers
62 and stores into each buffer that does not say it has a local value. */ 62 and stores into each buffer that does not say it has a local value. */
63 63
64struct GCALIGNED buffer buffer_defaults; 64struct buffer buffer_defaults;
65 65
66/* This structure marks which slots in a buffer have corresponding 66/* This structure marks which slots in a buffer have corresponding
67 default values in buffer_defaults. 67 default values in buffer_defaults.
@@ -84,7 +84,7 @@ struct buffer buffer_local_flags;
84/* This structure holds the names of symbols whose values may be 84/* This structure holds the names of symbols whose values may be
85 buffer-local. It is indexed and accessed in the same way as the above. */ 85 buffer-local. It is indexed and accessed in the same way as the above. */
86 86
87struct GCALIGNED buffer buffer_local_symbols; 87struct buffer buffer_local_symbols;
88 88
89/* Return the symbol of the per-buffer variable at offset OFFSET in 89/* Return the symbol of the per-buffer variable at offset OFFSET in
90 the buffer structure. */ 90 the buffer structure. */
@@ -1021,7 +1021,8 @@ reset_buffer_local_variables (struct buffer *b, bool permanent_too)
1021 newlist = Fcons (elt, newlist); 1021 newlist = Fcons (elt, newlist);
1022 } 1022 }
1023 newlist = Fnreverse (newlist); 1023 newlist = Fnreverse (newlist);
1024 if (XSYMBOL (local_var)->trapped_write == SYMBOL_TRAPPED_WRITE) 1024 if (XSYMBOL (local_var)->u.s.trapped_write
1025 == SYMBOL_TRAPPED_WRITE)
1025 notify_variable_watchers (local_var, newlist, 1026 notify_variable_watchers (local_var, newlist,
1026 Qmakunbound, Fcurrent_buffer ()); 1027 Qmakunbound, Fcurrent_buffer ());
1027 XSETCDR (XCAR (tmp), newlist); 1028 XSETCDR (XCAR (tmp), newlist);
@@ -1034,7 +1035,7 @@ reset_buffer_local_variables (struct buffer *b, bool permanent_too)
1034 else 1035 else
1035 XSETCDR (last, XCDR (tmp)); 1036 XSETCDR (last, XCDR (tmp));
1036 1037
1037 if (XSYMBOL (local_var)->trapped_write == SYMBOL_TRAPPED_WRITE) 1038 if (XSYMBOL (local_var)->u.s.trapped_write == SYMBOL_TRAPPED_WRITE)
1038 notify_variable_watchers (local_var, Qnil, 1039 notify_variable_watchers (local_var, Qnil,
1039 Qmakunbound, Fcurrent_buffer ()); 1040 Qmakunbound, Fcurrent_buffer ());
1040 } 1041 }
@@ -1166,7 +1167,7 @@ buffer_local_value (Lisp_Object variable, Lisp_Object buffer)
1166 sym = XSYMBOL (variable); 1167 sym = XSYMBOL (variable);
1167 1168
1168 start: 1169 start:
1169 switch (sym->redirect) 1170 switch (sym->u.s.redirect)
1170 { 1171 {
1171 case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; 1172 case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
1172 case SYMBOL_PLAINVAL: result = SYMBOL_VAL (sym); break; 1173 case SYMBOL_PLAINVAL: result = SYMBOL_VAL (sym); break;
@@ -2096,7 +2097,7 @@ void set_buffer_internal_2 (register struct buffer *b)
2096 { 2097 {
2097 Lisp_Object var = XCAR (XCAR (tail)); 2098 Lisp_Object var = XCAR (XCAR (tail));
2098 struct Lisp_Symbol *sym = XSYMBOL (var); 2099 struct Lisp_Symbol *sym = XSYMBOL (var);
2099 if (sym->redirect == SYMBOL_LOCALIZED /* Just to be sure. */ 2100 if (sym->u.s.redirect == SYMBOL_LOCALIZED /* Just to be sure. */
2100 && SYMBOL_BLV (sym)->fwd) 2101 && SYMBOL_BLV (sym)->fwd)
2101 /* Just reference the variable 2102 /* Just reference the variable
2102 to cause it to become set for this buffer. */ 2103 to cause it to become set for this buffer. */
@@ -2752,7 +2753,7 @@ swap_out_buffer_local_variables (struct buffer *b)
2752 for (alist = oalist; CONSP (alist); alist = XCDR (alist)) 2753 for (alist = oalist; CONSP (alist); alist = XCDR (alist))
2753 { 2754 {
2754 Lisp_Object sym = XCAR (XCAR (alist)); 2755 Lisp_Object sym = XCAR (XCAR (alist));
2755 eassert (XSYMBOL (sym)->redirect == SYMBOL_LOCALIZED); 2756 eassert (XSYMBOL (sym)->u.s.redirect == SYMBOL_LOCALIZED);
2756 /* Need not do anything if some other buffer's binding is 2757 /* Need not do anything if some other buffer's binding is
2757 now cached. */ 2758 now cached. */
2758 if (EQ (SYMBOL_BLV (XSYMBOL (sym))->where, buffer)) 2759 if (EQ (SYMBOL_BLV (XSYMBOL (sym))->where, buffer))
@@ -5423,8 +5424,8 @@ defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring,
5423 bo_fwd->type = Lisp_Fwd_Buffer_Obj; 5424 bo_fwd->type = Lisp_Fwd_Buffer_Obj;
5424 bo_fwd->offset = offset; 5425 bo_fwd->offset = offset;
5425 bo_fwd->predicate = predicate; 5426 bo_fwd->predicate = predicate;
5426 sym->declared_special = 1; 5427 sym->u.s.declared_special = true;
5427 sym->redirect = SYMBOL_FORWARDED; 5428 sym->u.s.redirect = SYMBOL_FORWARDED;
5428 SET_SYMBOL_FWD (sym, (union Lisp_Fwd *) bo_fwd); 5429 SET_SYMBOL_FWD (sym, (union Lisp_Fwd *) bo_fwd);
5429 XSETSYMBOL (PER_BUFFER_SYMBOL (offset), sym); 5430 XSETSYMBOL (PER_BUFFER_SYMBOL (offset), sym);
5430 5431