From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4416 invoked by alias); 30 Nov 2014 08:55:04 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 4009 invoked by uid 48); 30 Nov 2014 08:54:57 -0000 From: "adam at consulting dot net.nz" To: gcc-bugs@gcc.gnu.org Subject: [Bug inline-asm/64119] asm triggers local register variable data corruption Date: Sun, 30 Nov 2014 08:55:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: inline-asm X-Bugzilla-Version: unknown X-Bugzilla-Keywords: X-Bugzilla-Severity: major X-Bugzilla-Who: adam at consulting dot net.nz X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_status resolution Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-SW-Source: 2014-11/txt/msg03419.txt.bz2 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64119 Adam Warner changed: What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |UNCONFIRMED Resolution|INVALID |--- --- Comment #3 from Adam Warner --- Seriously Andrew? Here's an opportunity to reconsider your closing of the bug report. //asm triggers local register variable data corruption #include __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 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 ... 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 ... 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 ... 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?