https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64119

Adam Warner <adam at consulting dot net.nz> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |UNCONFIRMED
         Resolution|INVALID                     |---

--- Comment #3 from Adam Warner <adam at consulting dot net.nz> ---
Seriously Andrew? Here's an opportunity to reconsider your closing of the bug
report.

//asm triggers local register variable data corruption
#include <stdio.h>

__attribute__((noinline)) void fn(int inputa, int inputb, int inputc) {
  register int a asm ("rax");
  register int b asm ("rbx");
  register int c asm ("rcx");

  a = inputa; b = inputb; c = inputc;
  printf("The values of a, b and c are %d, %d and %d respectively\n", a, b, c);

  a = inputa; b = inputb; c = inputc;
  printf("The values of a, b and c are %d, %d and %d respectively\n", a, b, c);

  a = inputa; b = inputb; c = inputc;
  asm volatile ("mov %0, %0; mov %1, %1; mov %2, %2" : "+r" (a), "+r" (b), "+r"
(c));
  printf("The values of a, b and c are %d, %d and %d respectively\n", a, b, c);

  a = inputa; b = inputb; c = inputc;
  printf("The values of a, b and c are %d, %d and %d respectively\n", a, b, c);
}

int main(void) {
  fn(1, 2, 3);
  return 0;
}

$ clang-3.6 -O3 gcc-asm-reg-var-data-corruption_b.c && ./a.out 
The values of a, b and c are 1, 2 and 3 respectively
The values of a, b and c are 1, 2 and 3 respectively
The values of a, b and c are 1, 2 and 3 respectively
The values of a, b and c are 1, 2 and 3 respectively

$ gcc-4.9 -O3 gcc-asm-reg-var-data-corruption_b.c && ./a.out 
The values of a, b and c are 1, 2 and 3 respectively
The values of a, b and c are 1, 2 and 3 respectively
The values of a, b and c are 53, 2 and 39 respectively
The values of a, b and c are 1, 2 and 3 respectively

Do you claim that one may not assign values to explicit register variables?
(which clearly appears to be happening when a, b and c are again set to a =
inputa; b = inputb; c = inputc; as evidenced by the output of the fourth printf
statement)

GCC is ignoring the variable assignments in the presence of a harmless asm
statement.

At this stage I cannot accept your justification for the compiler output. What
is your computational model?

Let's look at the relevant portions of clang's compiler output:

  400537:       41 89 d6                mov    %edx,%r14d
  40053a:       41 89 f7                mov    %esi,%r15d
  40053d:       89 fd                   mov    %edi,%ebp

... the input variables are saved in ebp, r14d and r15d.

  400562:       e8 99 fe ff ff          callq  400400 <printf@plt>
  400567:       89 e8                   mov    %ebp,%eax
  400569:       44 89 fb                mov    %r15d,%ebx
  40056c:       44 89 f1                mov    %r14d,%ecx

... eax, ebx and ecx are set to the input values as per the variable
assignments
    (this is a requirement of the asm input constraints)

  40056f:       48 89 c0                mov    %rax,%rax
  400572:       48 89 db                mov    %rbx,%rbx
  400575:       48 89 c9                mov    %rcx,%rcx

... the harmless inline asm is output

  400578:       48 89 c2                mov    %rax,%rdx
  40057b:       bf 54 06 40 00          mov    $0x400654,%edi
  400580:       31 c0                   xor    %eax,%eax
  400582:       89 d6                   mov    %edx,%esi
  400584:       89 da                   mov    %ebx,%edx
  400586:       e8 75 fe ff ff          callq  400400 <printf@plt>

... and the register variables moved into the ABI registers for the printf.


Let's look at gcc's compiler output around the asm statement:

  400534:       41 89 d5                mov    %edx,%r13d
  400537:       55                      push   %rbp
  400538:       53                      push   %rbx
  400539:       41 89 fc                mov    %edi,%r12d
  40053c:       89 f5                   mov    %esi,%ebp

... the input variables are saved in ebp, r12d and r13d.

  400565:       e8 76 fe ff ff          callq  4003e0 <printf@plt>

... The code a = inputa; b = inputb; c = inputc; has been completely thrown
away.
    eax, ebx and ecx have not been set with the correct values to satisfy the
input
    constraints of the inline asm:

  40056a:       89 c0                   mov    %eax,%eax
  40056c:       89 db                   mov    %ebx,%ebx
  40056e:       89 c9                   mov    %ecx,%ecx

... eax, ebx and ecx have not been primed with the correct values so copying
    incorrect values achieves nothing.

  400570:       bf 28 06 40 00          mov    $0x400628,%edi
  400575:       89 da                   mov    %ebx,%edx
  400577:       89 c6                   mov    %eax,%esi
  400579:       31 c0                   xor    %eax,%eax
  40057b:       e8 60 fe ff ff          callq  4003e0 <printf@plt>

... thus garbage is printed.

I've only used features supported by both gcc and clang. clang's output is
sensible and fits my mental model of the C virtual machine. gcc's output is
really surprising and I've had a lot of experience manipulating gcc via inline
asm. Are you sure gcc's output is justified?

Reply via email to