Yep.  I just committed a fix for this.  I'm not terribly happy
about the need to check for this invariant, but at least it's relatively
straightforward to watch out for.

Edward

Excerpts from Simon Marlow's message of Sun May 15 14:43:06 -0400 2011:
> Ah yes, strangely enough Simon and I talked about this recently.  We 
> noticed that foreign calls don't save caller-saves registers in the new 
> codegen, but decided that it was probably ok because we're generating 
> code like
> 
>     x = R1
>     y = R2
>     ...
>     unsafe f(..)
>     ,..
> 
> so R1 is not actually live across the foreign call.
> 
> However, your optimisation pass wants to inline x and y, which would 
> make R1/R2 live across the call.  But foreign calls destroy caller-saves 
> registers, sp your optimisation pass has to take this into account: the 
> unsafe call to f() must be treated as writing to R1/R2/etc. (at least, 
> those regs that are caller-saves).  Does that make sense?
> 
> Cheers,
>     Simon
> 
> On 14/05/11 22:22, Edward Z. Yang wrote:
> > Hello all,
> >
> > I've just pinned down a nasty bug in the new code generator (not my code,
> > whoo!) that was tickled by my aggressive optimization pass.  In the old
> > code generator (CgUtils.hs), we have the following section for caller saves:
> >
> >      callerSaves :: GlobalReg ->  Bool
> >
> >      #ifdef CALLER_SAVES_Base
> >      callerSaves BaseReg             = True
> >      #endif
> >      #ifdef CALLER_SAVES_R1
> >      callerSaves (VanillaReg 1 _)    = True
> >      #endif
> >      #ifdef CALLER_SAVES_R2
> >      callerSaves (VanillaReg 2 _)    = True
> >      #endif
> >      #ifdef CALLER_SAVES_R3
> >      callerSaves (VanillaReg 3 _)    = True
> >      #endif
> >
> > However, the checks for CALLER_SAVES_RX are conspicuously missing from
> > the new code generator (StgCmmUtils.hs, I believe it was added in
> > commit 176fa33f17dd78355cc572e006d2ab26898e2c69).  I'm pretty sure we
> > should be saving these registers in the new world order... (and indeed,
> > validate on the new code generator crashes because my inlining pass is
> > to aggressive when it comes to things like R3).
> >
> > But, I kind of suspect this is *not* actually where we want to do these 
> > caller
> > saves.  A result of arranging things this early is that the hack in
> > cmm/CmmOpt.hs which avoids inlining into calls for fear of interfering with 
> > the
> > native calling convention.  Since we're moving all of this machinery into
> > Hoopl-land, this hack will now have to infect loads and loads of other 
> > places;
> > in particular, I can no longer treat unsafe foreign calls as "fat machine
> > instructions".  I cannot safely do a call f(2,R3) on x86-64 since R3 will
> > get clobbered with 2 before I manage to assign the third argument register 
> > (R4).
> > This sucks, and leads to bugs like the one above.
> >
> > As the comment in cmm/CmmOpt.hs notes, to fix this we'll have to teach the
> > backends how to work around caller-saves (this is "more correct" anyway, 
> > since
> > caller saves varies from arch to arch), but I don't think I'd really trust
> > myself to get it right.  In the mean time, "unsafe foreign calls" are
> > just fat machine instruction is a myth myth myth. Be careful.
> >
> > Cheers,
> > Edward

_______________________________________________
Cvs-ghc mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/cvs-ghc

Reply via email to