Define libc_max_align_t
diff mbox

Message ID 551C1A60.4080507@redhat.com
State New
Headers show

Commit Message

Florian Weimer April 1, 2015, 4:18 p.m. UTC
This came out of the scratch_buffer discussion.  As far as I can tell,
this is exactly what GCC uses; I could not find a target-specific
definition there.

Comments

Andreas Schwab April 1, 2015, 10:01 p.m. UTC | #1
Florian Weimer <fweimer@redhat.com> writes:

> +/* This mirrors the C11 max_align_t type provided by GCC, but it is
> +   also available in C99 mode.  */
> +typedef struct {
> +  long long ll __attribute__ ((__aligned__ (__alignof__ (long long))));
> +  long double ld __attribute__ ((__aligned__ (__alignof__ (long double))));
> +} libc_max_align_t;

Why aren't the attributes no-ops?

Andreas.
Florian Weimer April 1, 2015, 10:17 p.m. UTC | #2
On 04/02/2015 12:01 AM, Andreas Schwab wrote:
> Florian Weimer <fweimer@redhat.com> writes:
> 
>> +/* This mirrors the C11 max_align_t type provided by GCC, but it is
>> +   also available in C99 mode.  */
>> +typedef struct {
>> +  long long ll __attribute__ ((__aligned__ (__alignof__ (long long))));
>> +  long double ld __attribute__ ((__aligned__ (__alignof__ (long double))));
>> +} libc_max_align_t;
> 
> Why aren't the attributes no-ops?

Quoting Joseph:

“The attributes there are because some targets may give types lower
alignment inside structures and unions than outside; 32-bit x86 in
particular.”

<https://gcc.gnu.org/ml/gcc-patches/2011-11/msg00841.html>
Rich Felker April 2, 2015, 12:40 a.m. UTC | #3
On Thu, Apr 02, 2015 at 12:01:34AM +0200, Andreas Schwab wrote:
> Florian Weimer <fweimer@redhat.com> writes:
> 
> > +/* This mirrors the C11 max_align_t type provided by GCC, but it is
> > +   also available in C99 mode.  */
> > +typedef struct {
> > +  long long ll __attribute__ ((__aligned__ (__alignof__ (long long))));
> > +  long double ld __attribute__ ((__aligned__ (__alignof__ (long double))));
> > +} libc_max_align_t;
> 
> Why aren't the attributes no-ops?

Because gcc is insane.

On gcc, __alignof__ returns the "preferred alignment for optimization"
that gcc would use allocating such objects individually, not the "ABI
alignment" that would be used in structs, etc.

Rich
Andrew Pinski April 2, 2015, 1:36 a.m. UTC | #4
> On Apr 2, 2015, at 8:40 AM, Rich Felker <dalias@libc.org> wrote:
> 
>> On Thu, Apr 02, 2015 at 12:01:34AM +0200, Andreas Schwab wrote:
>> Florian Weimer <fweimer@redhat.com> writes:
>> 
>>> +/* This mirrors the C11 max_align_t type provided by GCC, but it is
>>> +   also available in C99 mode.  */
>>> +typedef struct {
>>> +  long long ll __attribute__ ((__aligned__ (__alignof__ (long long))));
>>> +  long double ld __attribute__ ((__aligned__ (__alignof__ (long double))));
>>> +} libc_max_align_t;
>> 
>> Why aren't the attributes no-ops?
> 
> Because gcc is insane.

No. Just some abi's are insane. 

> 
> On gcc, __alignof__ returns the "preferred alignment for optimization"
> that gcc would use allocating such objects individually, not the "ABI
> alignment" that would be used in structs, etc.

Except some abis talk about different alignment for where the field is located. 

> 
> Rich
Rich Felker April 2, 2015, 2:32 a.m. UTC | #5
On Thu, Apr 02, 2015 at 09:36:56AM +0800, pinskia@gmail.com wrote:
> > On Apr 2, 2015, at 8:40 AM, Rich Felker <dalias@libc.org> wrote:
> > 
> >> On Thu, Apr 02, 2015 at 12:01:34AM +0200, Andreas Schwab wrote:
> >> Florian Weimer <fweimer@redhat.com> writes:
> >> 
> >>> +/* This mirrors the C11 max_align_t type provided by GCC, but it is
> >>> +   also available in C99 mode.  */
> >>> +typedef struct {
> >>> +  long long ll __attribute__ ((__aligned__ (__alignof__ (long long))));
> >>> +  long double ld __attribute__ ((__aligned__ (__alignof__ (long double))));
> >>> +} libc_max_align_t;
> >> 
> >> Why aren't the attributes no-ops?
> > 
> > Because gcc is insane.
> 
> No. Just some abi's are insane. 

I agree it was a bad ABI choice not to require alignment equal to size
for all types, but at least it's consistent. On the other hand gcc is
inconsistent here. The fact that Andreas had to ask why the above
attributes are not no-ops should be sufficient to establish that the
gcc behavior is inconsistent and confusing.

> > On gcc, __alignof__ returns the "preferred alignment for optimization"
> > that gcc would use allocating such objects individually, not the "ABI
> > alignment" that would be used in structs, etc.
> 
> Except some abis talk about different alignment for where the field is located. 

Someone can write meaningless text like that in the ABI, but it's not
ABI if it's not observable.

Rich
Paul Eggert April 2, 2015, 5 a.m. UTC | #6
On 04/01/2015 03:01 PM, Andreas Schwab wrote:
>> +typedef struct {
>> >+  long long ll __attribute__ ((__aligned__ (__alignof__ (long long))));
>> >+  long double ld __attribute__ ((__aligned__ (__alignof__ (long double))));
>> >+} libc_max_align_t;
> Why aren't the attributes no-ops?

I wondered the same thing and reread the relevant sections of the C11 committee 
draft of Apri 12, 2011.  It's a subtle point. max_align_t is not defined to be a 
type whose alignment is equal to the maximum of the alignments of all the 
standard types.  Instead, it is defined to be a type whose alignment "is as 
great as is supported by the implementation in all contexts", which is not 
necessarily the same thing.  As there doesn't seem to be any portable way to 
define max_align_t on a pre-C11 compiler (defining a union whose members include 
all standard types doesn't seem to suffice), I suppose GCC uses those attributes 
as a nonportable way to do the job.  If so, glibc might as well be compatible 
with GCC.
Andreas Schwab April 2, 2015, 7:33 a.m. UTC | #7
Rich Felker <dalias@libc.org> writes:

> gcc behavior is inconsistent and confusing.

gcc just implements the ABI.

Andreas.
Andreas Schwab April 2, 2015, 7:38 a.m. UTC | #8
Florian Weimer <fweimer@redhat.com> writes:

> On 04/02/2015 12:01 AM, Andreas Schwab wrote:
>> Florian Weimer <fweimer@redhat.com> writes:
>> 
>>> +/* This mirrors the C11 max_align_t type provided by GCC, but it is
>>> +   also available in C99 mode.  */
>>> +typedef struct {
>>> +  long long ll __attribute__ ((__aligned__ (__alignof__ (long long))));
>>> +  long double ld __attribute__ ((__aligned__ (__alignof__ (long double))));
>>> +} libc_max_align_t;
>> 
>> Why aren't the attributes no-ops?
>
> Quoting Joseph:
>
> “The attributes there are because some targets may give types lower
> alignment inside structures and unions than outside; 32-bit x86 in
> particular.”

This should probably be added to the comment.

Andreas.
Rich Felker April 2, 2015, 3:18 p.m. UTC | #9
On Thu, Apr 02, 2015 at 09:33:45AM +0200, Andreas Schwab wrote:
> Rich Felker <dalias@libc.org> writes:
> 
> > gcc behavior is inconsistent and confusing.
> 
> gcc just implements the ABI.

No it doesn't. It uses "alignment of X" for two radically different
things. This even resulted in a bug where they chose the wrong one
initially for implementing C11 _Alignof; early gcc versions return the
wrong value for it.

Rich

Patch
diff mbox

From a521ad17ef640ff077eccd997defb4779d7040c3 Mon Sep 17 00:00:00 2001
From: Florian Weimer <fweimer@redhat.com>
Date: Wed, 1 Apr 2015 18:14:50 +0200
Subject: [PATCH] Define libc_max_align_t for internal use

---
 ChangeLog               | 4 ++++
 include/libc-internal.h | 7 +++++++
 2 files changed, 11 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 3e8df42..cc4daeb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@ 
+2015-04-01  Florian Weimer  <fweimer@redhat.com>
+
+	* include/libc-internal.h (libc_max_align_t): Define.
+
 2015-03-31  H.J. Lu  <hongjiu.lu@intel.com>
 
 	[BZ #18185]
diff --git a/include/libc-internal.h b/include/libc-internal.h
index bca59a4..9ddf409 100644
--- a/include/libc-internal.h
+++ b/include/libc-internal.h
@@ -107,4 +107,11 @@  extern void __init_misc (int, char **, char **);
 #define DIAG_IGNORE_NEEDS_COMMENT(version, option)	\
   _Pragma (_DIAG_STR (GCC diagnostic ignored option))
 
+/* This mirrors the C11 max_align_t type provided by GCC, but it is
+   also available in C99 mode.  */
+typedef struct {
+  long long ll __attribute__ ((__aligned__ (__alignof__ (long long))));
+  long double ld __attribute__ ((__aligned__ (__alignof__ (long double))));
+} libc_max_align_t;
+
 #endif /* _LIBC_INTERNAL  */
-- 
2.1.0