This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug target/37216] [cygming] Invalid alignment for SSE store to .comm data generated with -O3
- From: "nickc at redhat dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 7 Oct 2008 10:57:44 -0000
- Subject: [Bug target/37216] [cygming] Invalid alignment for SSE store to .comm data generated with -O3
- References: <bug-37216-16627@http.gcc.gnu.org/bugzilla/>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- 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