ia64 unwind thoughts

Richard Henderson rth@redhat.com
Thu Feb 22 18:55:00 GMT 2001


[ Re HP's c++ language specific data proposal, now cc'd to the
  mailing lists as there's no particular reason to keep this
  private and maybe other c++ folks have thoughts.  ]

In general I like the unwind action number thing.  If I 
understand things correctly, it means that 

	struct A { ~A(); };

	A a2;
	try {
	  A a1;

	  try {
	    f1 ();
	  } catch (X) {
	    c1_x ();
	  } catch (Y) {
	    c1_y ();
	  }

	  f2 ();
	} catch (X) {
	  c2_x ();
	} catch (Y) {
	  c2_y ();
	} catch (Z) {
	  c2_z ();
	}

can be implemented (ignoring the runtime library calls the
compiler will insert for proper exception bookkeeping) either
with two landing pads:

	  f1 ();		// L1 landing pad
	R1: 
	  f2 ();		// L2 landing pad
	  a1.~A();
	R2:
	  a2.~A();
	  return;
	L1:
	  switch (selector)
	  {
	  case 1:		// X
	    c1_x ();
	    goto R1;
	  case 2:		// Y
	    c1_y ();
	    goto R1;
	  }
	  goto L2;
	L2:
	  a1.~A();
	  switch (selector)
	  {
	  case 1:		// X
	    c2_x ();
	    goto R2;
	  case 2:		// Y
	    c2_y ();
	    goto R2;
	  case 3:		// Z
	    c2_z ();
	    goto R2;
	  }
	  a1.~A();
	  _Unwind_Resume (...);

or with one:

	  f1 ();		// L1 landing pad
	R1: 
	  f2 ();		// L1 landing pad
	  a1.~A();
	R2:
	  a2.~A();
	  return;
	L1:
	  switch (selector)
	  {
	  case 1:		// X region 1
	    c1_x ();
	    goto R1;
	  case 2:		// Y region 1
	    c1_y ();
	    goto R1;
	  }
	  a1.~A();
	  switch (selector)
	  {
	  case 3:		// X region 2
	    c2_x ();
	    goto R2;
	  case 4:		// Y region 2
	    c2_y ();
	    goto R2;
	  case 5:		// Z region 2
	    c2_z ();
	    goto R2;
	  }
	  a1.~A();
	  _Unwind_Resume (...);

The former would be preferred with a proper unwind mechanism,
since it reduces the size of the type tables.  The later would
almost certainly be preferred for sjlj, since the cost to set
up a landing pad there is very high.  We'd now be able to have
one landing pad for the entire function in the sjlj case, which
is likely to vastly reduce code bloat.

---

One concern I have is that you can't tell the difference in the
action table between a pure cleanup and a catch(...).  If I read
things properly, both have a call-site record with a non-zero
action, and an action record with a filter of zero.

Given that this whole two-pass EH scheme is set up such that we
could potentially cancel unwinding (not done in c++), and that
we're supposed to be integrating as well as possible with other
languages, it seems a dangerous oversight.

Not to mention the fact that the IA-64 unwind info record for a
function is set up to pre-filter for pass1 vs pass2, meaning that
an out-of-line function with a cleanup would be passed over in
pass1, properly treating its handlers as cleanup only.  If that
same function were inlined into a function that really had try
blocks (and so the enclosing function is processed in pass1) then
those cleanups suddenly become (...) handlers.

One possible solution here is to use a filter value of zero for
cleanups only, and represent (...) with a null type table entry.

We also might want to think about how to annotate a dwarf2 fde
with pass1 vs pass2 indicators.  I suspect that quite a lot of
c++ functions that do exception handling at all are for cleanup
only, and do not have catch handlers.



r~



More information about the Gcc mailing list