Patchwork [Ada] Rewrite CleanupUnwind_Handler to strictly follow ia64 ABI

login
register
mail settings
Submitter Arnaud Charlet
Date July 9, 2012, 1:05 p.m.
Message ID <20120709130528.GA16035@adacore.com>
Download mbox | patch
Permalink /patch/169816/
State New
Headers show

Comments

Arnaud Charlet - July 9, 2012, 1:05 p.m.
Required when the unwinder is not the libgcc one (eg: on HP-UX).
No functionnal change.

Tested on x86_64-pc-linux-gnu, committed on trunk

2012-07-09  Tristan Gingold  <gingold@adacore.com>

	* a-exexpr-gcc.adb (CleanupUnwind_Handler): Now imported from
	raise-gcc.c
	* raise-gcc.c (__gnat_cleanupunwind_handler): Defined.
	Strictly follow the ABI convention on ia64.

Patch

Index: a-exexpr-gcc.adb
===================================================================
--- a-exexpr-gcc.adb	(revision 189368)
+++ a-exexpr-gcc.adb	(working copy)
@@ -44,9 +44,7 @@ 
    ------------------------------------------------
 
    --  These come from "C++ ABI for Itanium: Exception handling", which is
-   --  the reference for GCC. They are used only when we are relying on
-   --  back-end tables for exception propagation, which in turn is currently
-   --  only the case for Zero_Cost_Exceptions in GNAT5.
+   --  the reference for GCC.
 
    --  Return codes from the GCC runtime functions used to propagate
    --  an exception.
@@ -63,7 +61,8 @@ 
       URC_CONTINUE_UNWIND);
 
    pragma Unreferenced
-     (URC_FOREIGN_EXCEPTION_CAUGHT,
+     (URC_NO_REASON,
+      URC_FOREIGN_EXCEPTION_CAUGHT,
       URC_PHASE2_ERROR,
       URC_PHASE1_ERROR,
       URC_NORMAL_STOP,
@@ -83,13 +82,14 @@ 
    UA_CLEANUP_PHASE : constant Unwind_Action := 2;
    UA_HANDLER_FRAME : constant Unwind_Action := 4;
    UA_FORCE_UNWIND  : constant Unwind_Action := 8;
-   UA_END_OF_STACK  : constant Unwind_Action := 16;  --  GCC extension ?
+   UA_END_OF_STACK  : constant Unwind_Action := 16;  --  GCC extension
 
    pragma Unreferenced
      (UA_SEARCH_PHASE,
       UA_CLEANUP_PHASE,
       UA_HANDLER_FRAME,
-      UA_FORCE_UNWIND);
+      UA_FORCE_UNWIND,
+      UA_END_OF_STACK);
 
    --  Mandatory common header for any exception object handled by the
    --  GCC unwinding runtime.
@@ -221,6 +221,8 @@ 
       UW_Exception : not null GCC_Exception_Access;
       UW_Context   : System.Address;
       UW_Argument  : System.Address) return Unwind_Reason_Code;
+   pragma Import (C, CleanupUnwind_Handler,
+                  "__gnat_cleanupunwind_handler");
    --  Hook called at each step of the forced unwinding we perform to
    --  trigger cleanups found during the propagation of an unhandled
    --  exception.
@@ -316,34 +318,6 @@ 
       Free (Copy);
    end GNAT_GCC_Exception_Cleanup;
 
-   ---------------------------
-   -- CleanupUnwind_Handler --
-   ---------------------------
-
-   function CleanupUnwind_Handler
-     (UW_Version   : Integer;
-      UW_Phases    : Unwind_Action;
-      UW_Eclass    : Exception_Class;
-      UW_Exception : not null GCC_Exception_Access;
-      UW_Context   : System.Address;
-      UW_Argument  : System.Address) return Unwind_Reason_Code
-   is
-      pragma Unreferenced (UW_Version, UW_Eclass, UW_Context, UW_Argument);
-
-   begin
-      --  Terminate when the end of the stack is reached
-
-      if UW_Phases >= UA_END_OF_STACK then
-         Unhandled_Except_Handler (UW_Exception);
-      end if;
-
-      --  We know there is at least one cleanup further up. Return so that it
-      --  is searched and entered, after which Unwind_Resume will be called
-      --  and this hook will gain control again.
-
-      return URC_NO_REASON;
-   end CleanupUnwind_Handler;
-
    -------------------------
    -- Setup_Current_Excep --
    -------------------------
Index: raise-gcc.c
===================================================================
--- raise-gcc.c	(revision 189369)
+++ raise-gcc.c	(working copy)
@@ -58,6 +58,7 @@ 
 #if defined (__hpux__) && defined (USE_LIBUNWIND_EXCEPTIONS)
 /* HP-UX B.11.31 ia64 libunwind doesn't have _Unwind_GetIPInfo. */
 #undef HAVE_GETIPINFO
+#define _UA_END_OF_STACK 0
 #endif
 
 /* The names of a couple of "standard" routines for unwinding/propagation
@@ -77,6 +78,7 @@ 
 __gnat_Unwind_ForcedUnwind (_Unwind_Exception *, void *, void *);
 
 extern void __gnat_setup_current_excep (_Unwind_Exception *);
+extern void __gnat_unhandled_except_handler (_Unwind_Exception *);
 
 #include "dwarf2.h"
 #include "unwind-dw2-fde.h"
@@ -1139,6 +1141,30 @@ 
   return _URC_INSTALL_CONTEXT;
 }
 
+_Unwind_Reason_Code
+__gnat_cleanupunwind_handler (int version,
+			      _Unwind_Action phases,
+			      _Unwind_Exception_Class eclass,
+			      struct _Unwind_Exception *exception,
+			      struct _Unwind_Context *context,
+			      void *arg)
+{
+  /* Terminate when the end of the stack is reached.  */
+  if ((phases & _UA_END_OF_STACK) != 0
+#ifdef __ia64__
+      /* Strictely follow the ia64 ABI: when end of stack is reached,
+	 the callback will be called with a NULL stack pointer.  */
+      || _Unwind_GetREG (context, 12) == 0
+#endif
+      )
+    __gnat_unhandled_except_handler (exception);
+
+  /* We know there is at least one cleanup further up. Return so that it
+     is searched and entered, after which Unwind_Resume will be called
+     and this hook will gain control again.  */
+  return _URC_NO_REASON;
+}
+
 /* Define the consistently named wrappers imported by Propagate_Exception.  */
 
 #ifdef __USING_SJLJ_EXCEPTIONS__