public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Exception problems
@ 1997-10-13  2:19 Andreas Schwab
  1997-11-01 21:50 ` Jeffrey A Law
  0 siblings, 1 reply; 3+ messages in thread
From: Andreas Schwab @ 1997-10-13  2:19 UTC (permalink / raw)
  To: egcs

Why doesn't this work?  I think it should.

$ ./try2
C number 3
C number 2
throwing 3
C number 1
throwing 2
C number 0
throwing 1
caught 1
Aborted (core dumped)
$ cat try2.cc
#include <stdio.h>

class C
{
public:
  C ();
  ~C ();
private:
  int id;
  static int count;
};

int C::count = 3;

int
main ()
{
  C c;
  return 0;
}

C::C () : id (count--)
{
  printf ("C number %d\n", id);
}

C::~C ()
{
  try
    {
      if (id > 0)
	{
	  C c;
	  printf ("throwing %d\n", id);
	  throw id;
	}
    }
  catch (int x)
    {
      printf ("caught %d\n", x);
    }
}
$ 

The problem is that when the exception is rethrown after the cleanup for
the try block is executed the values of __eh_type and __eh_value has been
clobbered by the exception inside C::~C.  There should be a way to
preserve these variables around a cleanup block, between the points that
are marked with (1) and (2) below:

destruct c(2)
C::~C:
  construct c(1)
  set __eh_value, __eh_type, __eh_cleanup, __eh_pc
  throw exception
  execute cleanup block				<---(1)
    destruct c(1)
    C::~C:
      construct c(0)
      set __eh_value, __eh_type, __eh_cleanup, __eh_pc
      throw exception
      destruct c(0)
      set __eh_pc
      rethrow exception
      set __eh_in_catch
      execute catch block
      call __eh_cleanup (deletes __eh_value)
      clear __eh_type, __eh_in_catch
  end of cleanup block				<---(2)
  set __eh_pc
  rethrow exception
    __eh_type is NULL -> terminate


-- 
Andreas Schwab                                      "And now for something
schwab@issan.informatik.uni-dortmund.de              completely different"

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Exception problems
  1997-10-13  2:19 Exception problems Andreas Schwab
@ 1997-11-01 21:50 ` Jeffrey A Law
  0 siblings, 0 replies; 3+ messages in thread
From: Jeffrey A Law @ 1997-11-01 21:50 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: egcs

  In message <vyzyb3y2f87.fsf@issan.informatik.uni-dortmund.de>you write:
  > Why doesn't this work?  I think it should.
  > 
  > $ ./try2
  > C number 3
  > C number 2
  > throwing 3
  > C number 1
  > throwing 2
  > C number 0
  > throwing 1
  > caught 1
  > Aborted (core dumped)
[ ... ]
It works for me using the latest sources on my x86 linux box.

You should give it another try once I make the next snapshot.

jeff

^ permalink raw reply	[flat|nested] 3+ messages in thread

* exception problems
@ 1997-09-07  7:53 John Carr
  0 siblings, 0 replies; 3+ messages in thread
From: John Carr @ 1997-09-07  7:53 UTC (permalink / raw)
  To: egcs

The file appended below shows some problems with g++ exceptions.  There is
only one function in it, a constructor with 4 lines of executable code
including a throw.

1. Compiled -fno-sjlj-exceptions on a SPARC, the compiler aborts because
the exception region notes are not nested.  These are the *INSN_EH* notes
in the order they appear:

	(note 22 21 23 5 NOTE_INSN_EH_REGION_BEG)
	(note 39 38 40 8 NOTE_INSN_EH_REGION_BEG)
	(note 95 58 96 8 NOTE_INSN_EH_REGION_END)
	(note 103 102 12 21 NOTE_INSN_EH_REGION_BEG)
	(note 12 103 13 3 NOTE_INSN_EH_REGION_BEG)
	(note 186 185 187 21 NOTE_INSN_EH_REGION_END)
	(note 193 192 194 5 NOTE_INSN_EH_REGION_END)
	(note 330 206 331 3 NOTE_INSN_EH_REGION_END)

2. Compiled with sjlj exceptions, the code is unacceptably large: 652
instructions on a SPARC with optimization (compared with 83 instructions
plus 60 bytes of exception tables for the Sun compiler).  There are a few
contributing factors.

2a. There is a 40K array on the stack so spills need an offset of 40K from
the stack pointer.  Reload doesn't think SPARC permits reg+reg addressing
(it only wants offsettable reg+reg modes).  Here is a pair of stack accesses:

	sethi %hi(-40220),%o3
	or %o3,%lo(-40220),%o3
	add %o3,%fp,%o3
	st %o0,[%o3]
	sethi %hi(-40220),%o4
	or %o4,%lo(-40220),%o4
	add %o4,%fp,%o4
	ld [%o4],%o4

This is a store and a load to the same address so the load should have
been eliminated.  (This is actually a nontrivial concern on UltraSPARC
because the load has to wait about 8 cycles for the store to complete.)
If the load had not been eliminated the calculation of the address for the
load should have been eliminated.  And in any case the SPARC reg+reg
addressing mode is suitable here and should have been used.  The 8
instructions should have been 4:

	sethi %hi(-40220),%o3
	or %o3,%lo(-40220),%o3
	st %o0,[%o3+%fp]
	mov %o0,%o4


2b. There are 16 calls to __get_dynamic_handler_chain and a lot of
code around them.  Most of the spills mentioned above are storing the
results of these calls.

The current implementation of __get_dynamic_handler_chain returns the
address of a global variable.  This could be expanded as inline rtl to
make much better code.  There is support for an alternate definition
of this function (EH_TABLE_LOOKUP), but no targets use it and even if
some did the function call should only be generated for those targets.

2c.  I think these calls are pushing and popping a cleanup stack.
There are no local variables which need destruction, so why all the
complexity?

2d. It would be nice if g++/gcc were smart enough not to generate this code
sequence:

	.LL32:
		call __terminate,0
		nop
	.LL36:
		call __terminate,0
		nop
	.LL46:
		call __terminate,0
		nop

There should only be one terminate block just like there is only one
function return label in C code.


Here is the preprocessed source.  Configure sparc-sun-solaris2.5.1 (or
equivalent) and compile -O1 or -O2.


extern "C" {
typedef void *__va_list;
typedef unsigned int	size_t;
typedef long	fpos_t;
typedef struct	 
{
	int		_cnt;	 
	unsigned char	*_ptr;	 
	unsigned char	*_base;	 
	unsigned char	_flag;	 
	unsigned char	_file;	 
} FILE;
typedef long	uid_t;
typedef __wchar_t wchar_t;

extern int errno;

}

class istream; class ostream;
 
struct StrRep                      
{
  unsigned short    len;          
  unsigned short    sz;           
  char              s[1];         
};
class String;
class SubString;

class String
{
protected:
  StrRep*           rep;    
public:
                    String();
                    String(const String& x);
                    String(const char* t);
                    String(const char* t, int len);
                    String(char c);
                    ~String();
};
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef short int16;
typedef int int32;
struct ostream;
enum pdu_type
{
  PDU_A_ASSOCIATE_RQ = 0x01,
  PDU_A_ASSOCIATE_AC = 0x02,
  PDU_A_ASSOCIATE_RJ = 0x03,
  PDU_P_DATA_TF = 0x04,
  PDU_A_RELEASE_RQ = 0x05,
  PDU_A_RELEASE_RP = 0x06,
  PDU_A_ABORT = 0x07
};
const unsigned int PDU_DATA_N_PDV = 32;
struct pdu_pdv
{
  unsigned short length;
  unsigned int flags : 7;
  bool allocated : 1;
  unsigned char presentation_context_id;
  char *string;
  pdu_pdv();
  pdu_pdv(const String &str);
  pdu_pdv(const char *_string);
  ~pdu_pdv();
  void reference(const pdu_pdv &r);
  void set(const char *_string, unsigned short _length, bool allocate = false);
  operator char *();
  operator unsigned char *();
  void operator=(const pdu_pdv &src);
};
struct pdu
{
  pdu_type type;
  const char *type_name() const;
  uint32 data_length;
  char *data;
  enum source { USER = 0, SERVICE_PROVIDER = 1, SERVICE_USER = 2 };
  static pdu *read(int) throw(int);	 
  virtual int send(int) throw() = 0;	 
  virtual ~pdu() throw();
  char *string(bool = false) const;
  virtual ostream &print(ostream &, bool = false) const throw() = 0;
  static const char *strerror(int);
protected:
  void read_data(int, unsigned int) throw(int);
  static int write(int, const void *, unsigned int);
  static int read(int, void *, unsigned int);
  pdu(pdu_type) throw();
  pdu(const pdu&) throw();		 
};

struct pdu_data : pdu
{
  unsigned int npdv;
  struct pdu_pdv pdv[PDU_DATA_N_PDV];
  ostream &print(ostream &, bool = false) const throw();
  int send(int fd) throw();
  pdu_data();
  pdu_data(int fd, unsigned int length) throw(int);
  void decode(const unsigned char *, unsigned int) throw();
};
pdu_data::pdu_data(int fd, unsigned int length) throw(int)
  : pdu(PDU_P_DATA_TF), npdv(0)
{
  unsigned char buf[40000];
  int error;
  if (error = read(fd, buf, length))
    throw error;
  decode(buf, length);
}


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~1997-11-01 21:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-10-13  2:19 Exception problems Andreas Schwab
1997-11-01 21:50 ` Jeffrey A Law
  -- strict thread matches above, loose matches on Subject: below --
1997-09-07  7:53 exception problems John Carr

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).