* AMD64 ABI and comparison of structures
@ 2006-05-25 10:42 José Bollo
2006-05-25 10:53 ` Andrew Haley
0 siblings, 1 reply; 2+ messages in thread
From: José Bollo @ 2006-05-25 10:42 UTC (permalink / raw)
To: gcc-help
hi all,
I repost here a problem that I met using GCC 3.4.4 and ABI for AMD64
(-march=athlon64).
the following C code
typedef struct {
int32_t a;
void *b;
} S;
void fs() {
char t[255];
int i;
for(i=0;i<255;i++)
t[i]=(char)(i+1);
}
int cmp1(S a1, S a2) {
return !memcmp(&a1,&a2,sizeof(S));
}
int cmp2(S a1, S a2) {
return a1.a==a2.a && a1.b==a2.b;
}
void put(S y) {
int a,b;
S x;
x=y;
a=cmp1(x,y);
b=cmp2(x,y);
printf("a=%d b=%d\n",a,b);
}
int main() {
S a;
a.a=1;
a.b=&a;
fs();
put(a);
return 0;
}
compiled for my linux x86_64 using the amd64 ABI (-march=athlon64) with gcc
3.4.4 prints "a=0 b=1"!
i have seen why and it is clear to me how a such result is produced.
I add below a commented assembly listing of the incriminated part.
i think that it is not a bug and that the structure can not be compared using
'memcmp'.
do you agree or it a bug ?
is it a bug or is it normal?
if it is a bug, must i open a bug track?
please comment.
regards
josé
First, the "put" function. After the obligatory initialisation code...
> .globl put
> .type put, @function
> put:
> .LFB8:
> pushq %rbp
> .LCFI8:
> movq %rsp, %rbp
> .LCFI9:
> subq $48, %rsp
> .LCFI10:
The parameter (y) was passed in edi:rsi. Here it is saved on the stack.
Presumably this is done to make debugging easier. 96 bits are copied.
> movl %edi, -16(%rbp)
> movq %rsi, -8(%rbp)
This makes a copy of the parameter on the stack. This is the translation
of the 'x=y' instruction. This time 128 bits are copied (why?) which
means that, if we called memcmp(&x,&y,sizeof(S)) right now, it would
return 0 (i.e. they are the same). But...
> movq -16(%rbp), %rax
> movq %rax, -48(%rbp)
> movq -8(%rbp), %rax
> movq %rax, -40(%rbp)
Here, cmp1 is called. As we already saw, only the meaningful part of the
structure is passed, in register (edx:rcx for one parameter, edi:rsi for
the other one). The result is saved on the stack (local var a)
> movl -16(%rbp), %edx
> movq -8(%rbp), %rcx
> movl -48(%rbp), %edi
> movq -40(%rbp), %rsi
> call cmp1
> movl %eax, -20(%rbp)
This time, cmp2 is called and the result is saved in b
> movl -16(%rbp), %edx
> movq -8(%rbp), %rcx
> movl -48(%rbp), %edi
> movq -40(%rbp), %rsi
> call cmp2
> movl %eax, -24(%rbp)
> movl -24(%rbp), %edx
> movl -20(%rbp), %esi
> movl $.LC0, %edi
> movl $0, %eax
> call printf
> leave
> ret
> .LFE8:
> .size put, .-put
Now it should be clear why cmp1 isn't working. Let's have a look
Entry code
> .globl cmp1
> .type cmp1, @function
> cmp1:
> .LFB6:
> pushq %rbp
> .LCFI3:
> movq %rsp, %rbp
> .LCFI4:
> subq $48, %rsp
save the parameters on the stack (one structure = 96 bits of data + 32
bits of junk)
> .LCFI5:
> movl %edi, -16(%rbp)
> movq %rsi, -8(%rbp)
> movl %edx, -32(%rbp)
> movq %rcx, -24(%rbp)
compare 128 bits of "data" on the stack. Obviously this won't work.
(I'll presume a call to memcmp was generated rather than rep cmpsq
because optimisations were turned off)
> leaq -32(%rbp), %rsi
> leaq -16(%rbp), %rdi
> movl $16, %edx
> call memcmp
> movl %eax, -36(%rbp)
> cmpl $0, -36(%rbp)
> sete %al
> movzbl %al, %eax
> movl %eax, -36(%rbp)
> movl -36(%rbp), %eax
> leave
> ret
> .LFE6:
> .size cmp1, .-cmp1
> .globl cmp2
> .type cmp2, @function
Obviously, cmp2 works because it only compares 96 bits of data
> cmp2:
> .LFB7:
> pushq %rbp
> .LCFI6:
> movq %rsp, %rbp
> .LCFI7:
> movl %edi, -16(%rbp)
> movq %rsi, -8(%rbp)
> movl %edx, -32(%rbp)
> movq %rcx, -24(%rbp)
> movl $0, -36(%rbp)
> movl -16(%rbp), %eax
> cmpl -32(%rbp), %eax
> jne .L7
> movq -8(%rbp), %rax
> cmpq -24(%rbp), %rax
> jne .L7
> movl $1, -36(%rbp)
> .L7:
> movl -36(%rbp), %eax
> leave
> ret
> .LFE7:
> .size cmp2, .-cmp2
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: AMD64 ABI and comparison of structures
2006-05-25 10:42 AMD64 ABI and comparison of structures José Bollo
@ 2006-05-25 10:53 ` Andrew Haley
0 siblings, 0 replies; 2+ messages in thread
From: Andrew Haley @ 2006-05-25 10:53 UTC (permalink / raw)
To: José Bollo; +Cc: gcc-help
José Bollo writes:
> hi all,
>
> I repost here a problem that I met using GCC 3.4.4 and ABI for AMD64
> (-march=athlon64).
>
> the following C code
>
> typedef struct {
> int32_t a;
> void *b;
> } S;
> void fs() {
> char t[255];
> int i;
> for(i=0;i<255;i++)
> t[i]=(char)(i+1);
> }
> int cmp1(S a1, S a2) {
> return !memcmp(&a1,&a2,sizeof(S));
> }
> int cmp2(S a1, S a2) {
> return a1.a==a2.a && a1.b==a2.b;
> }
> void put(S y) {
> int a,b;
> S x;
> x=y;
> a=cmp1(x,y);
> b=cmp2(x,y);
> printf("a=%d b=%d\n",a,b);
> }
> int main() {
> S a;
> a.a=1;
> a.b=&a;
> fs();
> put(a);
> return 0;
> }
>
> compiled for my linux x86_64 using the amd64 ABI (-march=athlon64) with gcc
> 3.4.4 prints "a=0 b=1"!
>
> i have seen why and it is clear to me how a such result is produced.
> I add below a commented assembly listing of the incriminated part.
>
> i think that it is not a bug and that the structure can not be compared using
> 'memcmp'.
That's right. It's a consequence of 6.7.2.1 Para 13: "There may be
unnamed padding within a structure object, but not at its beginning".
Andrew.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2006-05-25 10:53 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-05-25 10:42 AMD64 ABI and comparison of structures José Bollo
2006-05-25 10:53 ` Andrew Haley
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).