Date: Tue, 08 Jan 2013 10:22:17 +0100 From: Dimitry Andric <dim@FreeBSD.org> To: David Chisnall <theraven@freebsd.org> Cc: Stefan Farfeleder <stefanf@freebsd.org>, Nathan Whitehorn <nwhitehorn@freebsd.org>, freebsd-current@freebsd.org Subject: Re: clang 3.2 RC2 miscompiles libgcc? Message-ID: <50EBE549.9070808@FreeBSD.org> In-Reply-To: <1D415F08-5FFC-41B5-9A0D-E03757800E0C@freebsd.org> 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>
next in thread | previous in thread | raw e-mail | index | archive | help
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.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?50EBE549.9070808>