summaryrefslogtreecommitdiff
path: root/gcc/ada/raise-gcc.c
diff options
context:
space:
mode:
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2007-06-06 10:45:25 +0000
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2007-06-06 10:45:25 +0000
commitb0dfaab69bacf250d1d05b2ce80dba5bd9a60621 (patch)
treeef44fa305404ccceaabad62e91fb5c2f22b14927 /gcc/ada/raise-gcc.c
parent6946393c6a8baf8787aebbb8894929ba13e63610 (diff)
downloadgcc-b0dfaab69bacf250d1d05b2ce80dba5bd9a60621.tar.gz
2007-04-20 Olivier Hainque <hainque@adacore.com>
* raise-gcc.c (__gnat_eh_personality): Tweak the signature and add special code on ia64-vms to handle major incompatibilities between the GCC unwinding ABI and the VMS Condition Handling Facility, both calling this routine with a very different set of arguments and expectations on the return value. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@125455 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/raise-gcc.c')
-rw-r--r--gcc/ada/raise-gcc.c65
1 files changed, 61 insertions, 4 deletions
diff --git a/gcc/ada/raise-gcc.c b/gcc/ada/raise-gcc.c
index b7af4c54925..e6879f7a826 100644
--- a/gcc/ada/raise-gcc.c
+++ b/gcc/ada/raise-gcc.c
@@ -6,7 +6,7 @@
* *
* C Implementation File *
* *
- * Copyright (C) 1992-2005, Free Software Foundation, Inc. *
+ * Copyright (C) 1992-2007, 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- *
@@ -1004,20 +1004,77 @@ 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. */
+/* 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,
+__gnat_eh_personality (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;
+
_GNAT_Exception * gnat_exception = (_GNAT_Exception *) uw_exception;
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);