This is the mail archive of the gcc-patches@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]
Other format: [Raw text]

Re: [PATCH] Fix must-not-throw regions with SJLJ exception handling



On 21 Jan 2011, at 10:31, Richard Guenther wrote:


On Thu, Jan 20, 2011 at 8:27 PM, Ulrich Weigand <uweigand@de.ibm.com> wrote:
Hello,

a couple of exception related tests are failing on SPU:
FAIL: g++.dg/cpp0x/noexcept04.C execution test
FAIL: g++.dg/cpp0x/noexcept05.C scan-assembler LSDA
FAIL: g++.dg/eh/spec10.C execution test
FAIL: g++.dg/eh/spec11.C scan-assembler LSDA

These are related to must-not-throw regions.  To implement those,
we may have to register a personality function with empty LSDA.
This has been implemented for DWARF CFI exception handling, but
apparently not (fully?) for SJLJ exception handling.

As far as I can see, there's two problems:

- In sjlj_assign_call_site_values, the code sets the crtl- >uses_eh_lsda
to indicate an LSDA is needed. However this done by looping over all
*landing pads* in the function -- but must-not-throw regions do not
in fact have a landing pad, so they will be overlooked here.


To fix this, the patch below moves setting crtl->uses_eh_lsda into the
sjlj_mark_call_sites routine, which loops over all *insns*, just like
convert_to_eh_region_ranges does for DWARF CFI.


- Even so, if there are no landing pads at all, sjlj_mark_call_sites is
not even called (and no code to install the SJLJ handler is emitted).
But there can still be must-not-throw regions ...


 The patch below adds an extra check, if there are no landing pads,
 whether we still have must-not-throw regions (again by scanning the
 insns).  If so, it generates code to register a simplified version
 of the SJLJ data structure, which only contains the personality
 function and an (empty) LSDA, but no actual setjmp landing pad.

This seems to fix the problem for me; the tests above now pass.

Tested on spu-elf with no regressions.

OK for mainline?

Is there any primary or secondary target that uses SJLJ exceptions?

*-*-darwin* uses sjlj for ObjC* exceptions @m32 (i686-darwin is a secondary tgt).
If Ulrich cannot test on Darwin - perhaps Jack or Dominique would be willing?
(I cannot in the next few days - but will do so after the weekend if no-one else can).


Iain

If so please make sure we do not regress with your patch there.

Otherwise RTH should probably look at this patch.

Thanks,
Richard.

Bye,
Ulrich


ChangeLog:


* except.c (sjlj_assign_call_site_values): Move setting the
crtl->uses_eh_lsda flag to ...
(sjlj_mark_call_sites): ... here.
(sjlj_have_must_not_throw): New function.
(sjlj_emit_function_enter): Support NULL dispatch label.
(sjlj_build_landing_pads): In a function with no landing pads
that still has must-not-throw regions, generate code to register
a personality function with empty LSDA.



Index: gcc/except.c =================================================================== *** gcc/except.c (revision 168909) --- gcc/except.c (working copy) *************** sjlj_assign_call_site_values (void) *** 998,1005 ****

       /* First: build the action table.  */
       action = collect_one_action_chain (ar_hash, lp->region);
-       if (action != -1)
-         crtl->uses_eh_lsda = 1;

/* Next: assign call-site values. If dwarf2 terms, this would be
the region number assigned by convert_to_eh_region_ranges, but
--- 998,1003 ----
*************** sjlj_mark_call_sites (void)
*** 1065,1070 ****
--- 1063,1071 ----
this_call_site = 0;
}


+       if (this_call_site != -1)
+       crtl->uses_eh_lsda = 1;
+
       if (this_call_site == last_call_site)
       continue;

*************** sjlj_mark_call_sites (void)
*** 1085,1090 ****
--- 1086,1121 ----
     }
 }

+ /* Check whether any must-not-throw regions exist.  */
+
+ static bool
+ sjlj_have_must_not_throw (void)
+ {
+   rtx insn;
+
+   for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
+     {
+       eh_landing_pad lp;
+       eh_region r;
+       bool nothrow;
+
+       if (! INSN_P (insn))
+       continue;
+
+       nothrow = get_eh_region_and_lp_from_rtx (insn, &r, &lp);
+       if (nothrow)
+       continue;
+
+       if (r && r->type == ERT_MUST_NOT_THROW)
+       {
+         crtl->uses_eh_lsda = 1;
+         return true;
+       }
+     }
+
+   return false;
+ }
+
 /* Construct the SjLj_Function_Context.  */

 static void
*************** sjlj_emit_function_enter (rtx dispatch_l
*** 1119,1145 ****
   else
     emit_move_insn (mem, const0_rtx);

#ifdef DONT_USE_BUILTIN_SETJMP
! {
! rtx x, last;
! x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_RETURNS_TWICE,
! TYPE_MODE (integer_type_node), 1,
! plus_constant (XEXP (fc, 0),
! sjlj_fc_jbuf_ofs), Pmode);
!
! emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
! TYPE_MODE (integer_type_node), 0, dispatch_label);
! last = get_last_insn ();
! if (JUMP_P (last) && any_condjump_p (last))
! {
! gcc_assert (!find_reg_note (last, REG_BR_PROB, 0));
! add_reg_note (last, REG_BR_PROB, GEN_INT (REG_BR_PROB_BASE / 100));
! }
! }
! #else
! expand_builtin_setjmp_setup (plus_constant (XEXP (fc, 0), sjlj_fc_jbuf_ofs),
dispatch_label);
#endif


emit_library_call (unwind_sjlj_register_libfunc, LCT_NORMAL, VOIDmode,
1, XEXP (fc, 0), Pmode);
--- 1150,1179 ----
else
emit_move_insn (mem, const0_rtx);


+ if (dispatch_label)
+ {
#ifdef DONT_USE_BUILTIN_SETJMP
! rtx x, last;
! x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_RETURNS_TWICE,
! TYPE_MODE (integer_type_node), 1,
! plus_constant (XEXP (fc, 0),
! sjlj_fc_jbuf_ofs), Pmode);
!
! emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
! TYPE_MODE (integer_type_node), 0,
dispatch_label);
+ last = get_last_insn ();
+ if (JUMP_P (last) && any_condjump_p (last))
+ {
+ gcc_assert (!find_reg_note (last, REG_BR_PROB, 0));
+ add_reg_note (last, REG_BR_PROB, GEN_INT (REG_BR_PROB_BASE / 100));
+ }
+ #else
+ expand_builtin_setjmp_setup (plus_constant (XEXP (fc, 0),
+ sjlj_fc_jbuf_ofs),
+ dispatch_label);
#endif
+ }


emit_library_call (unwind_sjlj_register_libfunc, LCT_NORMAL, VOIDmode,
1, XEXP (fc, 0), Pmode);
*************** sjlj_build_landing_pads (void)
*** 1363,1368 ****
--- 1397,1418 ----
sjlj_emit_function_exit ();
}


+ /* If we do not have any landing pads, we may still need to register a
+ personality routine and (empty) LSDA to handle must-not- throw regions. */
+ else if (sjlj_have_must_not_throw ())
+ {
+ int align = STACK_SLOT_ALIGNMENT (sjlj_fc_type_node,
+ TYPE_MODE (sjlj_fc_type_node),
+ TYPE_ALIGN (sjlj_fc_type_node));
+ crtl->eh.sjlj_fc
+ = assign_stack_local (TYPE_MODE (sjlj_fc_type_node),
+ int_size_in_bytes (sjlj_fc_type_node),
+ align);
+
+ sjlj_emit_function_enter (NULL_RTX);
+ sjlj_emit_function_exit ();
+ }
+
VEC_free (int, heap, sjlj_lp_call_site_index);
}


--
 Dr. Ulrich Weigand
 GNU Toolchain for Linux on System z and Cell BE
 Ulrich.Weigand@de.ibm.com



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