From owner-freebsd-current@FreeBSD.ORG Tue Jan 8 09:22:21 2013 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id C6FD5956; Tue, 8 Jan 2013 09:22:21 +0000 (UTC) (envelope-from dim@FreeBSD.org) Received: from tensor.andric.com (cl-327.ede-01.nl.sixxs.net [IPv6:2001:7b8:2ff:146::2]) by mx1.freebsd.org (Postfix) with ESMTP id 752F1631; Tue, 8 Jan 2013 09:22:21 +0000 (UTC) Received: from [IPv6:2001:7b8:3a7:0:b8a6:2fee:dcd9:6bd9] (unknown [IPv6:2001:7b8:3a7:0:b8a6:2fee:dcd9:6bd9]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by tensor.andric.com (Postfix) with ESMTPSA id D2A9E5C37; Tue, 8 Jan 2013 10:22:18 +0100 (CET) Message-ID: <50EBE549.9070808@FreeBSD.org> Date: Tue, 08 Jan 2013 10:22:17 +0100 From: Dimitry Andric Organization: The FreeBSD Project User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20121128 Thunderbird/18.0 MIME-Version: 1.0 To: David Chisnall Subject: Re: clang 3.2 RC2 miscompiles libgcc? References: <20121227150724.GA1431@mole.fafoe.narf.at> <50DC65F5.6060004@freebsd.org> <50E0BD66.4070609@FreeBSD.org> <20130102135950.GA1464@mole.fafoe.narf.at> <20130104154940.GD1430@mole.fafoe.narf.at> <20130106141708.GA1418@mole.fafoe.narf.at> <50E9916F.3040500@FreeBSD.org> <20130106160331.GB1418@mole.fafoe.narf.at> <50EB5868.2050509@FreeBSD.org> <1D415F08-5FFC-41B5-9A0D-E03757800E0C@freebsd.org> In-Reply-To: <1D415F08-5FFC-41B5-9A0D-E03757800E0C@freebsd.org> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Cc: Stefan Farfeleder , Nathan Whitehorn , freebsd-current@freebsd.org X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 08 Jan 2013 09:22:21 -0000 On 2013-01-08 09:08, David Chisnall wrote: > On 7 Jan 2013, at 23:21, Dimitry Andric wrote: >> This is at least the direction I'm looking at. It seems that in some >> cases with __builtin_eh_return(), llvm does not see that registers can >> be clobbered, and it doesn't save and restore them. > Do you mean that some registers were clobbered by a prior call? __builtin_eh_return() doesn't return, so whether it clobbers anything or not isn't something that should matter. The preceding call is __builtin_frob_return_addr, which seems to be a no-op, so it shouldn't clobber any registers either... No, I mean that gcc seems to take great care in saving and restoring almost all important registers in a function, if that function contains a call to __builtin_eh_return. If you look at expand_eh_return() in contrib/gcc/except.c, you can see that it sets the special variable 'current_function_calls_eh_return'. This influences the code generation all over the place, and specifically the saving of registers in contrib/gcc/config/i386/i386.c: ====================================================================== /* Return 1 if we need to save REGNO. */ static int ix86_save_reg (unsigned int regno, int maybe_eh_return) { if (pic_offset_table_rtx && regno == REAL_PIC_OFFSET_TABLE_REGNUM && (regs_ever_live[REAL_PIC_OFFSET_TABLE_REGNUM] || current_function_profile || current_function_calls_eh_return || current_function_uses_const_pool)) { if (ix86_select_alt_pic_regnum () != INVALID_REGNUM) return 0; return 1; } if (current_function_calls_eh_return && maybe_eh_return) { unsigned i; for (i = 0; ; i++) { unsigned test = EH_RETURN_DATA_REGNO (i); if (test == INVALID_REGNUM) break; if (test == regno) return 1; } } [...] /* Emit code to save registers in the prologue. */ static void ix86_emit_save_regs (void) { unsigned int regno; rtx insn; for (regno = FIRST_PSEUDO_REGISTER; regno-- > 0; ) if (ix86_save_reg (regno, true)) { insn = emit_insn (gen_push (gen_rtx_REG (Pmode, regno))); RTX_FRAME_RELATED_P (insn) = 1; } } ====================================================================== On i386, most registers are touched anyway in _Unwind_Resume, so clang will already save and restore them. But on amd64, there are more registers than local variables, so clang only seems to save a few; not enough, in any case. This is why I added the asm statement which clobbers all those registers, forcing clang to save and restore them. This fixes most of the crashes I was able to reproduce. I think I still have another unrelated issue in libgcc with clang, but this only occurs when compiling the testcases with gcc 4.7, and very high optimization.