This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: AIX exception-handling vs. builtin_return_address


On Friday 02 February 2001 19:42, Mark Mitchell wrote:
> I think I now know at least part of why AIX EH is broken, but not
> necessarily how to fix it.
>
> In libgcc2.c, __throw computes the PC of the caller like this:
>
>   pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
>
> The expansion of __builtin_return_address looks like:
>
>         lwz 9,504(31)
>
> which is fine, in that at the end of the prologue we had:
>
>         mflr 0
>         stw 0,504(31)
>
> Unfortunately, at this point the link register no longer contains the
> address of the caller.  Why?
>
> Because this is at the end of the prologue, and we have:
>
>         mflr 0
>         mfcr 12
>         bl ._savef14
>
> at the very top of the prologue.
>
> In the middle of the prologue we have:
>
>        stw 0,8(1)
>
> because we remember that we moved the link register into register 0.
>
> But, the emission of the second store is both redundant and wrong;
> we've already clobbered lr.  And, it's the second store that we use
> for __builtin_return_address.
>
> This is coming from rs6000_return_addr.  Curiously, on AIX we have
> flag_pic == 0, even though all code is position-independent:
>
>   if (flag_pic && (DEFAULT_ABI == ABI_AIX))
>     {
>       warning ("-f%s ignored for AIX (all code is position independent)",
>                (flag_pic > 1) ? "PIC" : "pic");
>       flag_pic = 0;
>     }
>
> I'm not sure that matters, but it's just curious to me.  I would have
> thought that in that case we would hard-wire flag_pic *on*, not *off*.
>
> Anyhow, this means that we fall into this code:
>
>   reg = cfun->machine->ra_rtx;
>   if (reg == NULL)
>     {
>       /* No rtx yet.  Invent one, and initialize it from LR in
>          the prologue.  */
>       reg = gen_reg_rtx (Pmode);
>       cfun->machine->ra_rtx = reg;
>       init = gen_rtx_SET (VOIDmode, reg,
>                           gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
>
>       /* Emit the insn to the prologue with the other argument copies.  */
>       push_topmost_sequence ();
>       emit_insn_after (init, get_insns ());
>       pop_topmost_sequence ();
>     }
>
> which is bogus, since we have already clobbered the link register by
> the point at which this code is inserted.  (Note that
> cfun->machine->ra_rtx is NULL, here.)
>
> I'm not sure quite what's going on here.  Perhaps simply setting
> cfun->machine->ra_rtx when we emit the prologue instructions is good
> enough?  Oh, I see we don't emit the prologue until later.  It looks
> like using the PIC code would work, then.  Or else rs6000_return_addr
> should just set ra_rtx, and the actual SET should be generated by the
> prologue-generating code, using the register to which the link
> register has already been copied?
>
> I would really appreciate it if someone else could help out here a
> bit.  I really would like to be working on other aspects of the
> release by now. :-(
>
> Attached please find libgcc2.i.  If you compile this with
>
>   -fpreprocessed libgcc2.i -quiet -dumpbase libgcc2.c -dA -g -version
>   -fexceptions -o libgcc2.s
>
> with an AIX compiler look at __throw.
>
> I get:
>
>   .__throw:
> 	  .stabx  "__throw:F-11",.__throw,142,0
> 	  .function .__throw,.__throw,16,044,FE..__throw-.__throw
>   LFB..25:
> 	  .bf     4098
> 	  .line   1
> 	  .extern ._savef14
> 	  .extern ._restf14
> 	   # basic block 0
> 	  mflr 0
> 	  mfcr 12
> 	  bl ._savef14
>   LCFI..131:
> 	  stw 13,-220(1)
>   LCFI..132:
> 	  stw 14,-216(1)
>           ...
>   LCFI..154:
>           mflr 0
>           stw 0,504(31)
>
> Please let me know if I am off-base in my analysis.

No, you are exactly right with your analysis, I stumbled over the exact same 
problem on powerpc-linux-gnu where _throw gets compiled with -fPIC. After 
some testing I decided that saving the LR register around the TOC setup is 
simply not worth it and forced a full stack frame for flag_pic!=0 in 
rs6000_return_addr instead. The fact that AIX doesn't set flag_pic wasn't 
present in my mind anymore :-(.

Please try the appended patch, it should fix your problem. I'll try to extend 
execute/20010122-1.c a bit to catch this problem.

Franz.

Index: gcc/config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.162
diff -u -p -r1.162 rs6000.c
--- gcc/config/rs6000/rs6000.c	2001/01/24 00:07:31	1.162
+++ gcc/config/rs6000/rs6000.c	2001/02/02 19:27:02
@@ -5057,7 +5057,10 @@ rs6000_return_addr (count, frame)
   /* Currently we don't optimize very well between prolog and body code and
      for PIC code the code can be actually quite bad, so don't try to be
      too clever here.  */
-  if (count != 0 || flag_pic != 0)
+  if (count != 0
+      || flag_pic != 0
+      || rs6000_current_abi == ABI_AIX
+      || rs6000_current_abi == ABI_AIX_NODESC)
     {
       cfun->machine->ra_needs_full_frame = 1;
       return

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]