This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug target/37216] [cygming] Invalid alignment for SSE store to .comm data generated with -O3



------- Comment #44 from nickc at redhat dot com  2008-10-07 10:57 -------
Subject: Re:  [cygming] Invalid alignment for SSE store
 to .comm data generated with -O3

sherpya at netfarm dot it wrote:
> I mean that with -fno-common alignment works, even with non patched 4.2, my
> question is due to the fact that it's not so clear for me what no-common does

-fno-common stops uninitialized variables declared in C and C++ programs 
from being treated in the same way as common variables declared in 
FORTRAN programs.

> and adding -fno-common what are side effects?

Essentially there are two side effects:  The first is that you will get 
a link time error if you declare the same uninitialized variable twice 
in two different source files, without using the 'extern' keyword on one 
of them.  eg:

   % cat foo.c
   int a;

   % cat bar.c
   int a;
   int main (void) { return 0; }

   % gcc foo.c bar.c

   % gcc -fno-common foo.c bar.c
   multiple definition of `a'

This is often a problem with badly written header files which declare 
variables without using 'extern'.  eg:

   % cat header.h
   int a;

   % cat foo.c
   #include "header.h"
   int a;

   % cat bar.c
   #include "header.h"
   int main (void) { return 0; }

   % gcc -fno-common foo.c bar.c
   multiple definition of `a'

The other side-effect, and the one that is more interesting for our 
purposes, is that it forces uninitialised variables to be placed into 
the .bss section.  This is important because symbols in the PE/COFF file 
format do not have an alignment attribute of their own.  Instead the 
alignment is inherited by the containing section, with the maximum 
alignment of any symbol inside a section being taken as the section's 
alignment as a whole.  Symbols are placed inside the section on suitably 
aligned boundaries, so that providing that the section itself is placed 
on an alignment boundary everything will work.  eg:

   % cat foo.c
   int normal_align;
   int aligned_16 __attribute__((aligned(16)));

   % gcc -fno-common -c foo.c
   % objdump --syms foo.o
   [  8](sec 3)(fl 0x00)(ty 0)(scl 2)(nx 0) 0x00000000 _normal_align
   [  9](sec 3)(fl 0x00)(ty 0)(scl 2)(nx 0) 0x00000010 _aligned_16

   Note how the 'aligned_16' variable starts at an offset of
   00000010 from the start of section 3, whereas 'normal_align'
   starts at an offset of 00000000.  Ie there is a gap of 12
   bytes from offset 00000004 to 0000000f.

   % objdump -h foo.o
   Idx Name          Size      VMA       LMA     File off  Algn
   2 .bss          00000020  00000000  00000000  00000000  2**4

   Note that the .bss section has been given an alignment of 2^4.
   This is because it contains 'aligned_16'.  If that variable had
   not been declared then the .bss section would have been given
   its default alignment of 2^2.

   Also note that section numbering differs between the two uses
   of objdump.  Ie "(sec 3)" in the "objdump --syms" output refers
   to the third declared section which is the section with an
   index of 2 in the "objdump -h" output.

   % cat bar.c
   int a;

   % gcc -fno-common bar.c foo.o
   % nm a.exe
   00402000 B _a
   00402020 B _aligned_16
   00402010 B _normal_align

   So after linking 'aligned_16' still has a 16-bit alignment
   because of the 2^4 alignment of the .bss section in the foo.o
   object file.

The reason that all of this is important is that when common variables 
are stored in a PE/COFF object file they are not assigned to any 
section.  Since only sections, not symbols, have an alignment attribute 
in PE/COFF object files, any alignment requirements of common symbols 
are lost.  This is what has been causing the problems that you have 
experienced.  eg:

   % cat foo.c
   int normal_align;
   int aligned_16 __attribute__((aligned(16)));

   % gcc -c foo.c
   % objdump --syms foo.o
   [ 8](sec 0)(fl 0x00)(ty 0)(scl 2)(nx 0) 0x00000004 _normal_align
   [ 9](sec 0)(fl 0x00)(ty 0)(scl 2)(nx 0) 0x00000004 _aligned_16

   Note how the variables are assigned to "(sec 0)" which does not
   exist and that there is no field or flag specifying the alignment
   for either of them.

You may ask why common variables are not assigned to the .bss section. 
The reason is that if there are multiple declarations of the same 
variable and all but one of which are common, then the non-common 
declaration takes precedence.  eg:

   % cat foo.c
   int a;

   % cat bar.c
   int a = 1;

   % gcc foo.c bar.c
   % nm a.exe
   00402000 D _a

Ie the 'a' variable has been placed in the .data section and not the 
.bss section, despite the fact that it was declared uninitialised in 
foo.c.

So common variables are not assigned to a section until the final link 
takes places.  If there are no non-common definitions of a variable to 
specify where they should be placed then they are assigned to the .bss 
section, but by then it is too late - the alignment requirements of the 
symbol have been lost.

Cheers
   Nick


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37216


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]