From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27580 invoked by alias); 6 Feb 2012 01:17:11 -0000 Received: (qmail 27565 invoked by uid 22791); 6 Feb 2012 01:17:10 -0000 X-SWARE-Spam-Status: No, hits=-2.9 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from localhost (HELO gcc.gnu.org) (127.0.0.1) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 06 Feb 2012 01:16:52 +0000 From: "carrot at google dot com" To: gcc-bugs@gcc.gnu.org Subject: [Bug target/52129] New: wrong code to pass parameters to tail call function Date: Mon, 06 Feb 2012 01:17:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: target X-Bugzilla-Keywords: X-Bugzilla-Severity: major X-Bugzilla-Who: carrot at google dot com X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Changed-Fields: Message-ID: X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated Content-Type: text/plain; charset="UTF-8" MIME-Version: 1.0 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 X-SW-Source: 2012-02/txt/msg00558.txt.bz2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52129 Bug #: 52129 Summary: wrong code to pass parameters to tail call function Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: major Priority: P3 Component: target AssignedTo: unassigned@gcc.gnu.org ReportedBy: carrot@google.com Target: arm-unknown-linux-gnueabi Created attachment 26578 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=26578 test case The attached test case is simplified from llvm. Compile it with options -march=armv7-a -mthumb -O2 -finline-limit=64, GCC 4.7 generates: ... 61 add r2, sp, #44 62 add r3, r1, r3, lsl #2 // A 63 mov r0, r7 // B 64 add r1, r1, r4, lsl #2 65 str r1, [sp, #48] // C 66 ldmia r2, {r1, r2} // D 67 add sp, sp, #20 68 pop {r4, r5, r6, r7, lr} 69 add sp, sp, #8 70 b _ZN15ARMDAGToDAGISel19SelectAddrModeImm12E7SDValueRS0_S1_ Instructions ABCD pass parameters to a tail call function, instruction C pass one parameter through stack. Instruction D read out two words from [sp+44] and [sp+48], it is also the passed in parameter N of the function itself. the second word overlaps with instruction C, it is unexpected, so the read out value of N is actually garbage, and cause runtime error. The bug is introduced in expand pass ... (insn 69 68 70 6 (set (mem:SI (plus:SI (reg/f:SI 128 virtual-incoming-args) (const_int 8 [0x8])) [0 S4 A32]) (reg:SI 176)) ARMISelDAGToDAG2.ii:45 -1 (nil)) (insn 70 69 71 6 (set (reg:SI 0 r0) (reg/f:SI 152 [ this ])) ARMISelDAGToDAG2.ii:45 -1 (nil)) (insn 71 70 72 6 (set (reg:SI 177) (plus:SI (reg/f:SI 128 virtual-incoming-args) (const_int 4 [0x4]))) ARMISelDAGToDAG2.ii:45 -1 (nil)) (insn 72 71 73 6 (parallel [ (set (reg:SI 1 r1) (mem/c:SI (reg:SI 177) [4 N+0 S4 A32])) (set (reg:SI 2 r2) (mem/c:SI (plus:SI (reg:SI 177) (const_int 4 [0x4])) [4 N+4 S4 A32])) ]) ARMISelDAGToDAG2.ii:45 -1 (nil)) (insn 73 72 74 6 (set (reg:SI 3 r3) (reg:SI 170)) ARMISelDAGToDAG2.ii:45 -1 (nil)) (call_insn/j 74 73 75 6 (parallel [ (set (reg:SI 0 r0) (call (mem:SI (symbol_ref:SI ("_ZN15ARMDAGToDAGISel19SelectAddrModeImm12E7SDValueRS0_S1_") [flags 0x41] ) [0 SelectAddrModeImm12 S4 A32]) (const_int 4 [0x4]))) (return) (use (const_int 0 [0])) ]) ARMISelDAGToDAG2.ii:45 -1 (nil) (expr_list:REG_CFA_WINDOW_SAVE (use (reg:SI 3 r3)) (expr_list:REG_DEP_TRUE (use (reg:SI 2 r2)) (expr_list:REG_DEP_TRUE (use (reg:SI 1 r1)) (expr_list:REG_CFA_WINDOW_SAVE (use (reg:SI 0 r0)) (expr_list:REG_CFA_WINDOW_SAVE (use (mem/f:SI (plus:SI (reg/f:SI 128 virtual-incoming-args) (const_int 8 [0x8])) [0 S4 A32])) (nil))))))) ... insn 74 is a tail call, insns 69 to 73 are part of the parameter passing instructions. Because of large number of parameters, insn69 pass one parameter through stack. But this function itself contains some passed in parameters in the stack, and need to pass them again to the tail call function in insn 72. At this time the content of the stack has been overwritten by insn 69, so insn 72 read out wrong value, and will cause runtime error. The correct result should put insn 69 after insn 72 to avoid writing to the memory before using it. GCC 4.6 also contains this bug.