OSDN Git Service

More improvements to sparc VIS vec_init code generation.
[pf3gnuchains/gcc-fork.git] / gcc / ada / raise-gcc.c
index b7af4c5..0ced559 100644 (file)
@@ -6,24 +6,23 @@
  *                                                                          *
  *                          C Implementation File                           *
  *                                                                          *
- *             Copyright (C) 1992-2005, Free Software Foundation, Inc.      *
+ *             Copyright (C) 1992-2011, Free Software Foundation, Inc.      *
  *                                                                          *
  * GNAT is free software;  you can  redistribute it  and/or modify it under *
  * terms of the  GNU General Public License as published  by the Free Soft- *
- * ware  Foundation;  either version 2,  or (at your option) any later ver- *
+ * ware  Foundation;  either version 3,  or (at your option) any later ver- *
  * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
  * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License *
- * for  more details.  You should have  received  a copy of the GNU General *
- * Public License  distributed with GNAT;  see file COPYING.  If not, write *
- * to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, *
- * Boston, MA 02110-1301, USA.                                              *
+ * or FITNESS FOR A PARTICULAR PURPOSE.                                     *
  *                                                                          *
- * As a  special  exception,  if you  link  this file  with other  files to *
- * produce an executable,  this file does not by itself cause the resulting *
- * executable to be covered by the GNU General Public License. This except- *
- * ion does not  however invalidate  any other reasons  why the  executable *
- * file might be covered by the  GNU Public License.                        *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception,   *
+ * version 3.1, as published by the Free Software Foundation.               *
+ *                                                                          *
+ * You should have received a copy of the GNU General Public License and    *
+ * a copy of the GCC Runtime Library Exception along with this program;     *
+ * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    *
+ * <http://www.gnu.org/licenses/>.                                          *
  *                                                                          *
  * GNAT was originally developed  by the GNAT team at  New York University. *
  * Extensive contributions were provided by Ada Core Technologies Inc.      *
 
 #ifdef IN_RTS
 #include "tconfig.h"
-/* In the top-of-tree GCC, tconfig does not include tm.h, but in GCC 3.2
-   it does.  To avoid branching raise.c just for that purpose, we kludge by
-   looking for a symbol always defined by tm.h and if it's not defined,
-   we include it.  */
-#ifndef FIRST_PSEUDO_REGISTER
-#include "coretypes.h"
-#include "tm.h"
-#endif
 #include "tsystem.h"
 #include <sys/stat.h>
 #include <stdarg.h>
@@ -57,6 +48,14 @@ typedef char bool;
 #include "adaint.h"
 #include "raise.h"
 
+#ifdef __APPLE__
+/* On MacOS X, versions older than 10.5 don't export _Unwind_GetIPInfo.  */
+#undef HAVE_GETIPINFO
+#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
+#define HAVE_GETIPINFO 1
+#endif
+#endif
+
 /* The names of a couple of "standard" routines for unwinding/propagation
    actually vary depending on the underlying GCC scheme for exception handling
    (SJLJ or DWARF). We need a consistently named interface to import from
@@ -94,6 +93,7 @@ __gnat_Unwind_RaiseException (_Unwind_Exception *);
 _Unwind_Reason_Code
 __gnat_Unwind_ForcedUnwind (_Unwind_Exception *, void *, void *);
 
+extern void __gnat_setup_current_excep (_Unwind_Exception *);
 
 #ifdef IN_RTS   /* For eh personality routine */
 
@@ -101,6 +101,10 @@ __gnat_Unwind_ForcedUnwind (_Unwind_Exception *, void *, void *);
 #include "unwind-dw2-fde.h"
 #include "unwind-pe.h"
 
+/* The known and handled exception classes.  */
+
+#define CXX_EXCEPTION_CLASS 0x474e5543432b2b00ULL
+#define GNAT_EXCEPTION_CLASS 0x474e552d41646100ULL
 
 /* --------------------------------------------------------------
    -- The DB stuff below is there for debugging purposes only. --
@@ -118,10 +122,10 @@ __gnat_Unwind_ForcedUnwind (_Unwind_Exception *, void *, void *);
 typedef struct
 {
   _Unwind_Action phase;
-  char * description;
+  const char * description;
 } phase_descriptor;
 
-static phase_descriptor phase_descriptors[]
+static const phase_descriptor phase_descriptors[]
   = {{ _UA_SEARCH_PHASE,  "SEARCH_PHASE" },
      { _UA_CLEANUP_PHASE, "CLEANUP_PHASE" },
      { _UA_HANDLER_FRAME, "HANDLER_FRAME" },
@@ -205,7 +209,7 @@ db (int db_code, char * msg_format, ...)
 static void
 db_phases (int phases)
 {
-  phase_descriptor *a = phase_descriptors;
+  const phase_descriptor *a = phase_descriptors;
 
   if (! (db_accepted_codes() & DB_PHASES))
     return;
@@ -362,7 +366,7 @@ db_phases (int phases)
    context stack and not the actual call chain.
 
    The ACTION and TTYPES tables remain unchanged, which allows to search them
-   during the propagation phase to determine wether or not the propagated
+   during the propagation phase to determine whether or not the propagated
    exception is handled somewhere. When it is, we only "jump" up once directly
    to the context where the handler will be found. Besides, this allows "break
    exception unhandled" to work also
@@ -400,7 +404,7 @@ db_phases (int phases)
    ===================================
 
    The major point of this unit is to provide an exception propagation
-   personality routine for Ada. This is __gnat_eh_personality.
+   personality routine for Ada. This is __gnat_personality_v0.
 
    It is provided with a pointer to the propagated exception, an unwind
    context describing a location the propagation is going through, and a
@@ -433,7 +437,7 @@ db_phases (int phases)
      |
      |   (Ada frame)
      |
-     +--> __gnat_eh_personality (context, exception)
+     +--> __gnat_personality_v0 (context, exception)
           |
           +--> get_region_descriptor_for (context)
           |
@@ -499,14 +503,38 @@ typedef struct
 
 } region_descriptor;
 
+/* Extract and adjust the IP (instruction pointer) from an exception
+   context.  */
+
+static _Unwind_Ptr
+get_ip_from_context (_Unwind_Context *uw_context)
+{
+  int ip_before_insn = 0;
+#ifdef HAVE_GETIPINFO
+  _Unwind_Ptr ip = _Unwind_GetIPInfo (uw_context, &ip_before_insn);
+#else
+  _Unwind_Ptr ip = _Unwind_GetIP (uw_context);
+#endif
+  /* Subtract 1 if necessary because GetIPInfo yields a call return address
+     in this case, while we are interested in information for the call point.
+     This does not always yield the exact call instruction address but always
+     brings the IP back within the corresponding region.  */
+  if (!ip_before_insn)
+    ip--;
+
+  return ip;
+}
+
 static void
 db_region_for (region_descriptor *region, _Unwind_Context *uw_context)
 {
-  _Unwind_Ptr ip = _Unwind_GetIP (uw_context) - 1;
+  _Unwind_Ptr ip;
 
   if (! (db_accepted_codes () & DB_REGIONS))
     return;
 
+  ip = get_ip_from_context (uw_context);
+
   db (DB_REGIONS, "For ip @ 0x%08x => ", ip);
 
   if (region->lsda)
@@ -608,7 +636,7 @@ typedef enum
 } action_kind;
 
 /* filter value for cleanup actions.  */
-const int cleanup_filter = 0;
+static const int cleanup_filter = 0;
 
 typedef struct
 {
@@ -632,7 +660,7 @@ typedef struct
 static void
 db_action_for (action_descriptor *action, _Unwind_Context *uw_context)
 {
-  _Unwind_Ptr ip = _Unwind_GetIP (uw_context) - 1;
+  _Unwind_Ptr ip = get_ip_from_context (uw_context);
 
   db (DB_ACTIONS, "For ip @ 0x%08x => ", ip);
 
@@ -663,16 +691,13 @@ db_action_for (action_descriptor *action, _Unwind_Context *uw_context)
   return;
 }
 
-
 /* Search the call_site_table of REGION for an entry appropriate for the
-   UW_CONTEXT's ip. If one is found, store the associated landing_pad and
-   action_table entry, and set the ACTION kind to unknown for further
-   analysis. Otherwise, set the ACTION kind to nothing.
+   UW_CONTEXT's IP.  If one is found, store the associated landing_pad
+   and action_table entry, and set the ACTION kind to unknown for further
+   analysis.  Otherwise, set the ACTION kind to nothing.
 
    There are two variants of this routine, depending on the underlying
-   mechanism (dwarf/sjlj), which account for differences in the tables
-   organization.
-*/
+   mechanism (DWARF/SJLJ), which account for differences in the tables.  */
 
 #ifdef __USING_SJLJ_EXCEPTIONS__
 
@@ -683,14 +708,12 @@ get_call_site_action_for (_Unwind_Context *uw_context,
                           region_descriptor *region,
                           action_descriptor *action)
 {
-  _Unwind_Ptr call_site
-    = _Unwind_GetIP (uw_context) - 1;
-  /* Subtract 1 because GetIP returns the actual call_site value + 1.  */
+  _Unwind_Ptr call_site = get_ip_from_context (uw_context);
 
   /* call_site is a direct index into the call-site table, with two special
-     values : -1 for no-action and 0 for "terminate". The latter should never
-     show up for Ada. To test for the former, beware that _Unwind_Ptr might be
-     unsigned.  */
+     values : -1 for no-action and 0 for "terminate".  The latter should never
+     show up for Ada.  To test for the former, beware that _Unwind_Ptr might
+     be unsigned.  */
 
   if ((int)call_site < 0)
     {
@@ -712,18 +735,17 @@ get_call_site_action_for (_Unwind_Context *uw_context,
       action->kind = unknown;
 
       /* We have a direct index into the call-site table, but this table is
-        made of leb128 values, the encoding length of which is variable. We
+        made of leb128 values, the encoding length of which is variable.  We
         can't merely compute an offset from the index, then, but have to read
         all the entries before the one of interest.  */
 
-      const unsigned char * p = region->call_site_table;
+      const unsigned char *p = region->call_site_table;
 
       do {
        p = read_uleb128 (p, &cs_lp);
        p = read_uleb128 (p, &cs_action);
       } while (--call_site);
 
-
       action->landing_pad = cs_lp + 1;
 
       if (cs_action)
@@ -735,29 +757,17 @@ get_call_site_action_for (_Unwind_Context *uw_context,
     }
 }
 
-#else
-/* ! __USING_SJLJ_EXCEPTIONS__ */
+#else /* !__USING_SJLJ_EXCEPTIONS__  */
 
 static void
 get_call_site_action_for (_Unwind_Context *uw_context,
                           region_descriptor *region,
                           action_descriptor *action)
 {
-  _Unwind_Ptr ip
-    = _Unwind_GetIP (uw_context) - 1;
-  /* Subtract 1 because GetIP yields a call return address while we are
-     interested in information for the call point. This does not always yield
-     the exact call instruction address but always brings the ip back within
-     the corresponding region.
-
-     ??? When unwinding up from a signal handler triggered by a trap on some
-     instruction, we usually have the faulting instruction address here and
-     subtracting 1 might get us into the wrong region.  */
+  const unsigned char *p = region->call_site_table;
+  _Unwind_Ptr ip = get_ip_from_context (uw_context);
 
-  const unsigned char * p
-    = region->call_site_table;
-
-  /* Unless we are able to determine otherwise ... */
+  /* Unless we are able to determine otherwise...  */
   action->kind = nothing;
 
   db (DB_CSITE, "\n");
@@ -778,7 +788,7 @@ get_call_site_action_for (_Unwind_Context *uw_context,
          region->base+cs_start, cs_start, cs_len,
          region->lp_base+cs_lp, cs_lp);
 
-      /* The table is sorted, so if we've passed the ip, stop.  */
+      /* The table is sorted, so if we've passed the IP, stop.  */
       if (ip < region->base + cs_start)
        break;
 
@@ -807,11 +817,11 @@ get_call_site_action_for (_Unwind_Context *uw_context,
   db (DB_CSITE, "---\n");
 }
 
-#endif
+#endif /* __USING_SJLJ_EXCEPTIONS__  */
 
 /* With CHOICE an exception choice representing an "exception - when"
    argument, and PROPAGATED_EXCEPTION a pointer to the currently propagated
-   occurrence, return true iif the latter matches the former, that is, if
+   occurrence, return true if the latter matches the former, that is, if
    PROPAGATED_EXCEPTION is caught by the handling code controlled by CHOICE.
    This takes care of the special Non_Ada_Error case on VMS.  */
 
@@ -819,7 +829,6 @@ get_call_site_action_for (_Unwind_Context *uw_context,
 #define Language_For          __gnat_language_for
 #define Import_Code_For       __gnat_import_code_for
 #define EID_For               __gnat_eid_for
-#define Adjust_N_Cleanups_For __gnat_adjust_n_cleanups_for
 
 extern bool Is_Handled_By_Others (_Unwind_Ptr eid);
 extern char Language_For (_Unwind_Ptr eid);
@@ -827,44 +836,55 @@ extern char Language_For (_Unwind_Ptr eid);
 extern Exception_Code Import_Code_For (_Unwind_Ptr eid);
 
 extern Exception_Id EID_For (_GNAT_Exception * e);
-extern void Adjust_N_Cleanups_For (_GNAT_Exception * e, int n);
 
 static int
 is_handled_by (_Unwind_Ptr choice, _GNAT_Exception * propagated_exception)
 {
-  /* Pointer to the GNAT exception data corresponding to the propagated
-     occurrence.  */
-  _Unwind_Ptr E = (_Unwind_Ptr) EID_For (propagated_exception);
-
-  /* Base matching rules: An exception data (id) matches itself, "when
-     all_others" matches anything and "when others" matches anything unless
-     explicitly stated otherwise in the propagated occurrence.  */
-
-  bool is_handled =
-    choice == E
-    || choice == GNAT_ALL_OTHERS
-    || (choice == GNAT_OTHERS && Is_Handled_By_Others (E));
-
-  /* In addition, on OpenVMS, Non_Ada_Error matches VMS exceptions, and we
-     may have different exception data pointers that should match for the
-     same condition code, if both an export and an import have been
-     registered.  The import code for both the choice and the propagated
-     occurrence are expected to have been masked off regarding severity
-     bits already (at registration time for the former and from within the
-     low level exception vector for the latter).  */
+  if (propagated_exception->common.exception_class == GNAT_EXCEPTION_CLASS)
+    {
+      /* Pointer to the GNAT exception data corresponding to the propagated
+         occurrence.  */
+      _Unwind_Ptr E = (_Unwind_Ptr) EID_For (propagated_exception);
+
+      /* Base matching rules: An exception data (id) matches itself, "when
+         all_others" matches anything and "when others" matches anything
+         unless explicitly stated otherwise in the propagated occurrence.  */
+
+      bool is_handled =
+        choice == E
+        || choice == GNAT_ALL_OTHERS
+        || (choice == GNAT_OTHERS && Is_Handled_By_Others (E));
+
+      /* In addition, on OpenVMS, Non_Ada_Error matches VMS exceptions, and we
+         may have different exception data pointers that should match for the
+         same condition code, if both an export and an import have been
+         registered.  The import code for both the choice and the propagated
+         occurrence are expected to have been masked off regarding severity
+         bits already (at registration time for the former and from within the
+         low level exception vector for the latter).  */
 #ifdef VMS
-  #define Non_Ada_Error system__aux_dec__non_ada_error
-  extern struct Exception_Data Non_Ada_Error;
-
-  is_handled |=
-    (Language_For (E) == 'V'
-     && choice != GNAT_OTHERS && choice != GNAT_ALL_OTHERS
-     && ((Language_For (choice) == 'V' && Import_Code_For (choice) != 0
-         && Import_Code_For (choice) == Import_Code_For (E))
-        || choice == (_Unwind_Ptr)&Non_Ada_Error));
+#     define Non_Ada_Error system__aux_dec__non_ada_error
+      extern struct Exception_Data Non_Ada_Error;
+
+      is_handled |=
+        (Language_For (E) == 'V'
+         && choice != GNAT_OTHERS && choice != GNAT_ALL_OTHERS
+         && ((Language_For (choice) == 'V' && Import_Code_For (choice) != 0
+              && Import_Code_For (choice) == Import_Code_For (E))
+             || choice == (_Unwind_Ptr)&Non_Ada_Error));
 #endif
 
-  return is_handled;
+      return is_handled;
+    }
+  else
+    {
+#     define Foreign_Exception system__exceptions__foreign_exception;
+      extern struct Exception_Data Foreign_Exception;
+
+      return choice == GNAT_ALL_OTHERS
+        || choice == GNAT_OTHERS
+        || choice == (_Unwind_Ptr)&Foreign_Exception;
+    }
 }
 
 /* Fill out the ACTION to be taken from propagating UW_EXCEPTION up to
@@ -873,6 +893,7 @@ is_handled_by (_Unwind_Ptr choice, _GNAT_Exception * propagated_exception)
 static void
 get_action_description_for (_Unwind_Context *uw_context,
                             _Unwind_Exception *uw_exception,
+                            _Unwind_Action uw_phase,
                             region_descriptor *region,
                             action_descriptor *action)
 {
@@ -937,17 +958,22 @@ get_action_description_for (_Unwind_Context *uw_context,
          /* Positive filters are for regular handlers.  */
          else if (ar_filter > 0)
            {
-             /* See if the filter we have is for an exception which matches
-                the one we are propagating.  */
-             _Unwind_Ptr choice = get_ttype_entry_for (region, ar_filter);
-
-             if (is_handled_by (choice, gnat_exception))
-               {
-                 action->kind = handler;
-                 action->ttype_filter = ar_filter;
-                 action->ttype_entry = choice;
-                 return;
-               }
+              /* Do not catch an exception if the _UA_FORCE_UNWIND flag is
+                 passed (to follow the ABI).  */
+              if (!(uw_phase & _UA_FORCE_UNWIND))
+                {
+                  /* See if the filter we have is for an exception which
+                     matches the one we are propagating.  */
+                  _Unwind_Ptr choice = get_ttype_entry_for (region, ar_filter);
+
+                  if (is_handled_by (choice, gnat_exception))
+                    {
+                      action->kind = handler;
+                      action->ttype_filter = ar_filter;
+                      action->ttype_entry = choice;
+                      return;
+                    }
+                }
            }
 
          /* Negative filter values are for C++ exception specifications.
@@ -973,11 +999,6 @@ setup_to_install (_Unwind_Context *uw_context,
                   _Unwind_Ptr uw_landing_pad,
                   int uw_filter)
 {
-#ifndef EH_RETURN_DATA_REGNO
-  /* We should not be called if the appropriate underlying support is not
-     there.  */
-  abort ();
-#else
   /* 1/ exception object pointer, which might be provided back to
      _Unwind_Resume (and thus to this personality routine) if we are jumping
      to a cleanup.  */
@@ -992,7 +1013,6 @@ setup_to_install (_Unwind_Context *uw_context,
   /* Setup the address we should jump at to reach the code where there is the
      "something" we found.  */
   _Unwind_SetIP (uw_context, uw_landing_pad);
-#endif
 }
 
 /* The following is defined from a-except.adb. Its purpose is to enable
@@ -1004,20 +1024,85 @@ extern void __gnat_notify_unhandled_exception (void);
 /* Below is the eh personality routine per se. We currently assume that only
    GNU-Ada exceptions are met.  */
 
+#ifdef __USING_SJLJ_EXCEPTIONS__
+#define PERSONALITY_FUNCTION    __gnat_personality_sj0
+#else
+#define PERSONALITY_FUNCTION    __gnat_personality_v0
+#endif
+
+/* Major tweak for ia64-vms : the CHF propagation phase calls this personality
+   routine with sigargs/mechargs arguments and has very specific expectations
+   on possible return values.
+
+   We handle this with a number of specific tricks:
+
+   1. We tweak the personality routine prototype to have the "version" and
+      "phases" two first arguments be void * instead of int and _Unwind_Action
+      as nominally expected in the GCC context.
+
+      This allows us to access the full range of bits passed in every case and
+      has no impact on the callers side since each argument remains assigned
+      the same single 64bit slot.
+
+   2. We retrieve the corresponding int and _Unwind_Action values within the
+      routine for regular use with truncating conversions. This is a noop when
+      called from the libgcc unwinder.
+
+   3. We assume we're called by the VMS CHF when unexpected bits are set in
+      both those values. The incoming arguments are then real sigargs and
+      mechargs pointers, which we then redirect to __gnat_handle_vms_condition
+      for proper processing.
+*/
+#if defined (VMS) && defined (__IA64)
+typedef void * version_arg_t;
+typedef void * phases_arg_t;
+#else
+typedef int version_arg_t;
+typedef _Unwind_Action phases_arg_t;
+#endif
+
 _Unwind_Reason_Code
-__gnat_eh_personality (int uw_version,
-                       _Unwind_Action uw_phases,
-                       _Unwind_Exception_Class uw_exception_class,
-                       _Unwind_Exception *uw_exception,
-                       _Unwind_Context *uw_context)
-{
-  _GNAT_Exception * gnat_exception = (_GNAT_Exception *) uw_exception;
+PERSONALITY_FUNCTION (version_arg_t, phases_arg_t,
+                      _Unwind_Exception_Class, _Unwind_Exception *,
+                      _Unwind_Context *);
 
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (version_arg_t version_arg,
+                      phases_arg_t phases_arg,
+                      _Unwind_Exception_Class uw_exception_class,
+                      _Unwind_Exception *uw_exception,
+                      _Unwind_Context *uw_context)
+{
+  /* Fetch the version and phases args with their nominal ABI types for later
+     use. This is a noop everywhere except on ia64-vms when called from the
+     Condition Handling Facility.  */
+  int uw_version = (int) version_arg;
+  _Unwind_Action uw_phases = (_Unwind_Action) phases_arg;
   region_descriptor region;
   action_descriptor action;
 
+  /* Check that we're called from the ABI context we expect, with a major
+     possible variation on VMS for IA64.  */
   if (uw_version != 1)
-    return _URC_FATAL_PHASE1_ERROR;
+    {
+#if defined (VMS) && defined (__IA64)
+
+      /* Assume we're called with sigargs/mechargs arguments if really
+        unexpected bits are set in our first two formals.  Redirect to the
+        GNAT condition handling code in this case.  */
+
+      extern long __gnat_handle_vms_condition (void *, void *);
+
+      unsigned int version_unexpected_bits_mask = 0xffffff00U;
+      unsigned int phases_unexpected_bits_mask  = 0xffffff00U;
+
+      if ((unsigned int)uw_version & version_unexpected_bits_mask
+         && (unsigned int)uw_phases & phases_unexpected_bits_mask)
+       return __gnat_handle_vms_condition (version_arg, phases_arg);
+#endif
+
+      return _URC_FATAL_PHASE1_ERROR;
+    }
 
   db_indent (DB_INDENT_RESET);
   db_phases (uw_phases);
@@ -1035,7 +1120,8 @@ __gnat_eh_personality (int uw_version,
 
   /* Search the call-site and action-record tables for the action associated
      with this IP.  */
-  get_action_description_for (uw_context, uw_exception, &region, &action);
+  get_action_description_for (uw_context, uw_exception, uw_phases,
+                              &region, &action);
   db_action_for (&action, uw_context);
 
   /* Whatever the phase, if there is nothing relevant in this frame,
@@ -1051,13 +1137,14 @@ __gnat_eh_personality (int uw_version,
     {
       if (action.kind == cleanup)
        {
-         Adjust_N_Cleanups_For (gnat_exception, 1);
          return _URC_CONTINUE_UNWIND;
        }
       else
        {
          /* Trigger the appropriate notification routines before the second
-            phase starts, which ensures the stack is still intact. */
+            phase starts, which ensures the stack is still intact.
+             First, setup the Ada occurrence.  */
+          __gnat_setup_current_excep (uw_exception);
          __gnat_notify_handled_exception ();
 
          return _URC_HANDLER_FOUND;
@@ -1069,17 +1156,12 @@ __gnat_eh_personality (int uw_version,
      occurrence (we are in a FORCED_UNWIND phase in this case). Install the
      context to get there.  */
 
-  /* If we are going to install a cleanup context, decrement the cleanup
-     count.  This is required in a FORCED_UNWINDing phase (for an unhandled
-     exception), as this is used from the forced unwinding handler in
-     Ada.Exceptions.Exception_Propagation to decide wether unwinding should
-     proceed further or Unhandled_Exception_Terminate should be called.  */
-  if (action.kind == cleanup)
-    Adjust_N_Cleanups_For (gnat_exception, -1);
-
   setup_to_install
     (uw_context, uw_exception, action.landing_pad, action.ttype_filter);
 
+  /* Write current exception, so that it can be retrieved from Ada.  */
+  __gnat_setup_current_excep (uw_exception);
+
   return _URC_INSTALL_CONTEXT;
 }