197403Sobrien// -*- C++ -*- Exception handling routines for throwing.
2117397Skan// Copyright (C) 2001, 2003 Free Software Foundation, Inc.
397403Sobrien//
4132720Skan// This file is part of GCC.
597403Sobrien//
6132720Skan// GCC is free software; you can redistribute it and/or modify
797403Sobrien// it under the terms of the GNU General Public License as published by
897403Sobrien// the Free Software Foundation; either version 2, or (at your option)
997403Sobrien// any later version.
1097403Sobrien//
11132720Skan// GCC is distributed in the hope that it will be useful,
1297403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1397403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1497403Sobrien// GNU General Public License for more details.
1597403Sobrien//
1697403Sobrien// You should have received a copy of the GNU General Public License
17132720Skan// along with GCC; see the file COPYING.  If not, write to
18169691Skan// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19169691Skan// Boston, MA 02110-1301, USA.
2097403Sobrien
2197403Sobrien// As a special exception, you may use this file as part of a free software
2297403Sobrien// library without restriction.  Specifically, if other files instantiate
2397403Sobrien// templates or use macros or inline functions from this file, or you compile
2497403Sobrien// this file and link it with other files to produce an executable, this
2597403Sobrien// file does not by itself cause the resulting executable to be covered by
2697403Sobrien// the GNU General Public License.  This exception does not however
2797403Sobrien// invalidate any other reasons why the executable file might be covered by
2897403Sobrien// the GNU General Public License.
2997403Sobrien
3097403Sobrien#include <bits/c++config.h>
3197403Sobrien#include "unwind-cxx.h"
3297403Sobrien
3397403Sobrienusing namespace __cxxabiv1;
3497403Sobrien
3597403Sobrien
3697403Sobrienstatic void
3797403Sobrien__gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc)
3897403Sobrien{
3997403Sobrien  __cxa_exception *header = __get_exception_header_from_ue (exc);
4097403Sobrien
4197403Sobrien  // If we haven't been caught by a foreign handler, then this is
4297403Sobrien  // some sort of unwind error.  In that case just die immediately.
43117397Skan  // _Unwind_DeleteException in the HP-UX IA64 libunwind library
44117397Skan  //  returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT
45117397Skan  // like the GCC _Unwind_DeleteException function does.
46117397Skan  if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
4797403Sobrien    __terminate (header->terminateHandler);
4897403Sobrien
4997403Sobrien  if (header->exceptionDestructor)
5097403Sobrien    header->exceptionDestructor (header + 1);
5197403Sobrien
5297403Sobrien  __cxa_free_exception (header + 1);
5397403Sobrien}
5497403Sobrien
5597403Sobrien
5697403Sobrienextern "C" void
57169691Skan__cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo,
58169691Skan			 void (*dest) (void *))
5997403Sobrien{
6097403Sobrien  __cxa_exception *header = __get_exception_header_from_obj (obj);
6197403Sobrien  header->exceptionType = tinfo;
6297403Sobrien  header->exceptionDestructor = dest;
6397403Sobrien  header->unexpectedHandler = __unexpected_handler;
6497403Sobrien  header->terminateHandler = __terminate_handler;
65169691Skan  __GXX_INIT_EXCEPTION_CLASS(header->unwindHeader.exception_class);
6697403Sobrien  header->unwindHeader.exception_cleanup = __gxx_exception_cleanup;
6797403Sobrien
68132720Skan#ifdef _GLIBCXX_SJLJ_EXCEPTIONS
6997403Sobrien  _Unwind_SjLj_RaiseException (&header->unwindHeader);
7097403Sobrien#else
7197403Sobrien  _Unwind_RaiseException (&header->unwindHeader);
7297403Sobrien#endif
7397403Sobrien
7497403Sobrien  // Some sort of unwinding error.  Note that terminate is a handler.
7597403Sobrien  __cxa_begin_catch (&header->unwindHeader);
7697403Sobrien  std::terminate ();
7797403Sobrien}
7897403Sobrien
7997403Sobrienextern "C" void
80169691Skan__cxxabiv1::__cxa_rethrow ()
8197403Sobrien{
8297403Sobrien  __cxa_eh_globals *globals = __cxa_get_globals ();
8397403Sobrien  __cxa_exception *header = globals->caughtExceptions;
8497403Sobrien
85169691Skan  globals->uncaughtExceptions += 1;
86169691Skan
8797403Sobrien  // Watch for luser rethrowing with no active exception.
8897403Sobrien  if (header)
8997403Sobrien    {
9097403Sobrien      // Tell __cxa_end_catch this is a rethrow.
91169691Skan      if (!__is_gxx_exception_class(header->unwindHeader.exception_class))
92117397Skan	globals->caughtExceptions = 0;
93117397Skan      else
94117397Skan	header->handlerCount = -header->handlerCount;
9597403Sobrien
96132720Skan#ifdef _GLIBCXX_SJLJ_EXCEPTIONS
97117397Skan      _Unwind_SjLj_Resume_or_Rethrow (&header->unwindHeader);
9897403Sobrien#else
99169691Skan#if defined(_LIBUNWIND_STD_ABI)
10097403Sobrien      _Unwind_RaiseException (&header->unwindHeader);
101117397Skan#else
102117397Skan      _Unwind_Resume_or_Rethrow (&header->unwindHeader);
10397403Sobrien#endif
104117397Skan#endif
10597403Sobrien
10697403Sobrien      // Some sort of unwinding error.  Note that terminate is a handler.
10797403Sobrien      __cxa_begin_catch (&header->unwindHeader);
10897403Sobrien    }
10997403Sobrien  std::terminate ();
11097403Sobrien}
111