diff options
Diffstat (limited to 'gcc/ada/init.c')
-rw-r--r-- | gcc/ada/init.c | 317 |
1 files changed, 174 insertions, 143 deletions
diff --git a/gcc/ada/init.c b/gcc/ada/init.c index 8a28bf68ab5..37c403b803e 100644 --- a/gcc/ada/init.c +++ b/gcc/ada/init.c @@ -38,10 +38,6 @@ installed by this file are used to catch the resulting signals that come from these probes failing (i.e. touching protected pages). */ -#ifdef __cplusplus -extern "C" { -#endif - /* This file should be kept synchronized with 2sinit.ads, 2sinit.adb, s-init-ae653-cert.adb and s-init-xi-sparc.adb. All these files implement the required functionality for different targets. */ @@ -71,6 +67,10 @@ extern "C" { #include "adaint.h" #include "raise.h" +#ifdef __cplusplus +extern "C" { +#endif + extern void __gnat_raise_program_error (const char *, int); /* Addresses of exception data blocks for predefined exceptions. Tasking_Error @@ -821,34 +821,46 @@ int __gnat_features_set = 0; #endif /* Define macro symbols for the VMS conditions that become Ada exceptions. - Most of these are also defined in the header file ssdef.h which has not - yet been converted to be recognized by GNU C. */ + It would be better to just include <ssdef.h> */ -/* Defining these as macros, as opposed to external addresses, allows - them to be used in a case statement below. */ #define SS$_ACCVIO 12 #define SS$_HPARITH 1284 +#define SS$_INTDIV 1156 #define SS$_STKOVF 1364 #define SS$_RESIGNAL 2328 +#define MTH$_FLOOVEMAT 1475268 /* Some ACVC_21 CXA tests */ + +/* The following codes must be resignalled, and not handled here. */ + /* These codes are in standard message libraries. */ extern int C$_SIGKILL; extern int SS$_DEBUG; extern int LIB$_KEYNOTFOU; extern int LIB$_ACTIMAGE; -#define CMA$_EXIT_THREAD 4227492 -#define MTH$_FLOOVEMAT 1475268 /* Some ACVC_21 CXA tests */ -#define SS$_INTDIV 1156 /* These codes are non standard, which is to say the author is not sure if they are defined in the standard message libraries so keep them as macros for now. */ #define RDB$_STREAM_EOF 20480426 #define FDL$_UNPRIKW 11829410 +#define CMA$_EXIT_THREAD 4227492 + +struct cond_sigargs { + unsigned int sigarg; + unsigned int sigargval; +}; + +struct cond_subtests { + unsigned int num; + const struct cond_sigargs sigargs[]; +}; struct cond_except { unsigned int cond; const struct Exception_Data *except; + unsigned int needs_adjust; /* 1 = adjust PC, 0 = no adjust */ + const struct cond_subtests *subtests; }; struct descriptor_s { @@ -928,53 +940,72 @@ extern Exception_Code Base_Code_In (Exception_Code); /* DEC Ada specific conditions. */ static const struct cond_except dec_ada_cond_except_table [] = { - {ADA$_PROGRAM_ERROR, &program_error}, - {ADA$_USE_ERROR, &Use_Error}, - {ADA$_KEYSIZERR, &program_error}, - {ADA$_STAOVF, &storage_error}, - {ADA$_CONSTRAINT_ERRO, &constraint_error}, - {ADA$_IOSYSFAILED, &Device_Error}, - {ADA$_LAYOUT_ERROR, &Layout_Error}, - {ADA$_STORAGE_ERROR, &storage_error}, - {ADA$_DATA_ERROR, &Data_Error}, - {ADA$_DEVICE_ERROR, &Device_Error}, - {ADA$_END_ERROR, &End_Error}, - {ADA$_MODE_ERROR, &Mode_Error}, - {ADA$_NAME_ERROR, &Name_Error}, - {ADA$_STATUS_ERROR, &Status_Error}, - {ADA$_NOT_OPEN, &Use_Error}, - {ADA$_ALREADY_OPEN, &Use_Error}, - {ADA$_USE_ERROR, &Use_Error}, - {ADA$_UNSUPPORTED, &Use_Error}, - {ADA$_FAC_MODE_MISMAT, &Use_Error}, - {ADA$_ORG_MISMATCH, &Use_Error}, - {ADA$_RFM_MISMATCH, &Use_Error}, - {ADA$_RAT_MISMATCH, &Use_Error}, - {ADA$_MRS_MISMATCH, &Use_Error}, - {ADA$_MRN_MISMATCH, &Use_Error}, - {ADA$_KEY_MISMATCH, &Use_Error}, - {ADA$_MAXLINEXC, &constraint_error}, - {ADA$_LINEXCMRS, &constraint_error}, + {ADA$_PROGRAM_ERROR, &program_error, 0, 0}, + {ADA$_USE_ERROR, &Use_Error, 0, 0}, + {ADA$_KEYSIZERR, &program_error, 0, 0}, + {ADA$_STAOVF, &storage_error, 0, 0}, + {ADA$_CONSTRAINT_ERRO, &constraint_error, 0, 0}, + {ADA$_IOSYSFAILED, &Device_Error, 0, 0}, + {ADA$_LAYOUT_ERROR, &Layout_Error, 0, 0}, + {ADA$_STORAGE_ERROR, &storage_error, 0, 0}, + {ADA$_DATA_ERROR, &Data_Error, 0, 0}, + {ADA$_DEVICE_ERROR, &Device_Error, 0, 0}, + {ADA$_END_ERROR, &End_Error, 0, 0}, + {ADA$_MODE_ERROR, &Mode_Error, 0, 0}, + {ADA$_NAME_ERROR, &Name_Error, 0, 0}, + {ADA$_STATUS_ERROR, &Status_Error, 0, 0}, + {ADA$_NOT_OPEN, &Use_Error, 0, 0}, + {ADA$_ALREADY_OPEN, &Use_Error, 0, 0}, + {ADA$_USE_ERROR, &Use_Error, 0, 0}, + {ADA$_UNSUPPORTED, &Use_Error, 0, 0}, + {ADA$_FAC_MODE_MISMAT, &Use_Error, 0, 0}, + {ADA$_ORG_MISMATCH, &Use_Error, 0, 0}, + {ADA$_RFM_MISMATCH, &Use_Error, 0, 0}, + {ADA$_RAT_MISMATCH, &Use_Error, 0, 0}, + {ADA$_MRS_MISMATCH, &Use_Error, 0, 0}, + {ADA$_MRN_MISMATCH, &Use_Error, 0, 0}, + {ADA$_KEY_MISMATCH, &Use_Error, 0, 0}, + {ADA$_MAXLINEXC, &constraint_error, 0, 0}, + {ADA$_LINEXCMRS, &constraint_error, 0, 0}, #if 0 /* Already handled by a pragma Import_Exception in Aux_IO_Exceptions */ - {ADA$_LOCK_ERROR, &Lock_Error}, - {ADA$_EXISTENCE_ERROR, &Existence_Error}, - {ADA$_KEY_ERROR, &Key_Error}, + {ADA$_LOCK_ERROR, &Lock_Error, 0, 0}, + {ADA$_EXISTENCE_ERROR, &Existence_Error, 0, 0}, + {ADA$_KEY_ERROR, &Key_Error, 0, 0}, #endif - {0, 0} + {0, 0, 0, 0} }; #endif /* IN_RTS */ -/* Non-DEC Ada specific conditions. We could probably also put - SS$_HPARITH here and possibly SS$_ACCVIO, SS$_STKOVF. */ -static const struct cond_except cond_except_table [] = { - {MTH$_FLOOVEMAT, &constraint_error}, - {SS$_INTDIV, &constraint_error}, - {0, 0} +/* Non-DEC Ada specific conditions that map to Ada exceptions. */ + +/* Subtest for ACCVIO Constraint_Error, kept for compatibility, + in hindsight should have just made ACCVIO == Storage_Error. */ +#define ACCVIO_VIRTUAL_ADDR 3 +static const struct cond_subtests accvio_c_e = + {1, /* number of subtests below */ + { + {ACCVIO_VIRTUAL_ADDR, 0} + } + }; + +/* Macro flag to adjust PC which gets off by one for some conditions, + not sure if this is reliably true, PC could be off by more for + HPARITH for example, unless a trapb is inserted. */ +#define NEEDS_ADJUST 1 + +static const struct cond_except system_cond_except_table [] = { + {MTH$_FLOOVEMAT, &constraint_error, 0, 0}, + {SS$_INTDIV, &constraint_error, 0, 0}, + {SS$_HPARITH, &constraint_error, NEEDS_ADJUST, 0}, + {SS$_ACCVIO, &constraint_error, NEEDS_ADJUST, &accvio_c_e}, + {SS$_ACCVIO, &storage_error, NEEDS_ADJUST, 0}, + {SS$_STKOVF, &storage_error, NEEDS_ADJUST, 0}, + {0, 0, 0, 0} }; /* To deal with VMS conditions and their mapping to Ada exceptions, @@ -1039,7 +1070,7 @@ __gnat_default_resignal_p (int code) for (i = 0, iexcept = 0; cond_resignal_table [i] - && !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i])); + && !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i])); i++); return iexcept; @@ -1092,10 +1123,62 @@ copy_msg (struct descriptor_s *msgdesc, char *message) return 0; } +/* Scan TABLE for a match for the condition contained in SIGARGS, + and return the entry, or the empty entry if no match found. */ + +static const struct cond_except * + scan_conditions ( int *sigargs, const struct cond_except *table []) +{ + int i; + struct cond_except entry; + + /* Scan the exception condition table for a match and fetch + the associated GNAT exception pointer. */ + for (i = 0; (*table) [i].cond; i++) + { + unsigned int match = LIB$MATCH_COND (&sigargs [1], &(*table) [i].cond); + const struct cond_subtests *subtests = (*table) [i].subtests; + + if (match) + { + if (!subtests) + { + return &(*table) [i]; + } + else + { + unsigned int ii; + int num = (*subtests).num; + + /* Perform subtests to differentiate exception. */ + for (ii = 0; ii < num; ii++) + { + unsigned int arg = (*subtests).sigargs [ii].sigarg; + unsigned int argval = (*subtests).sigargs [ii].sigargval; + + if (sigargs [arg] != argval) + { + num = 0; + break; + } + } + + /* All subtests passed. */ + if (num == (*subtests).num) + return &(*table) [i]; + } + } + } + + /* No match, return the null terminating entry. */ + return &(*table) [i]; +} + long __gnat_handle_vms_condition (int *sigargs, void *mechargs) { struct Exception_Data *exception = 0; + unsigned int needs_adjust = 0; Exception_Code base_code; struct descriptor_s gnat_facility = {4, 0, "GNAT"}; char message [Default_Exception_Msg_Max_Length]; @@ -1106,112 +1189,60 @@ __gnat_handle_vms_condition (int *sigargs, void *mechargs) Import_Exception. */ if (__gnat_resignal_p (sigargs [1])) return SS$_RESIGNAL; +#ifndef IN_RTS + /* toplev.c handles this for compiler. */ + if (sigargs [1] == SS$_HPARITH) + return SS$_RESIGNAL; +#endif #ifdef IN_RTS /* See if it's an imported exception. Beware that registered exceptions are bound to their base code, with the severity bits masked off. */ base_code = Base_Code_In ((Exception_Code) sigargs[1]); exception = Coded_Exception (base_code); - - if (exception) - { - message[0] = 0; - - /* Subtract PC & PSL fields which messes with PUTMSG. */ - sigargs[0] -= 2; - SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message); - sigargs[0] += 2; - msg = message; - - exception->Name_Length = 19; - /* ??? The full name really should be get SYS$GETMSG returns. */ - exception->Full_Name = "IMPORTED_EXCEPTION"; - exception->Import_Code = base_code; - -#ifdef __IA64 - /* Do not adjust the program counter as already points to the next - instruction (just after the call to LIB$STOP). */ - Raise_From_Signal_Handler (exception, msg); -#endif - } #endif if (exception == 0) - switch (sigargs[1]) - { - case SS$_ACCVIO: - if (sigargs[3] == 0) - { - exception = &constraint_error; - msg = "access zero"; - } - else - { - exception = &storage_error; - msg = "stack overflow or erroneous memory access"; - } - __gnat_adjust_context_for_raise (SS$_ACCVIO, (void *)mechargs); - break; - - case SS$_STKOVF: - exception = &storage_error; - msg = "stack overflow"; - __gnat_adjust_context_for_raise (SS$_STKOVF, (void *)mechargs); - break; - - case SS$_HPARITH: -#ifndef IN_RTS - return SS$_RESIGNAL; /* toplev.c handles for compiler */ -#else - exception = &constraint_error; - msg = "arithmetic error"; - __gnat_adjust_context_for_raise (SS$_HPARITH, (void *)mechargs); -#endif - break; - - default: #ifdef IN_RTS + { + int i; + struct cond_except cond; + const struct cond_except *cond_table; + const struct cond_except *cond_tables [] = {dec_ada_cond_except_table, + system_cond_except_table, + 0}; + + i = 0; + while ((cond_table = cond_tables[i++]) && !exception) { - int i; - - /* Scan the DEC Ada exception condition table for a match and fetch - the associated GNAT exception pointer. */ - for (i = 0; - dec_ada_cond_except_table [i].cond && - !LIB$MATCH_COND (&sigargs [1], - &dec_ada_cond_except_table [i].cond); - i++); - exception = (struct Exception_Data *) - dec_ada_cond_except_table [i].except; - - if (!exception) - { - /* Scan the VMS standard condition table for a match and fetch - the associated GNAT exception pointer. */ - for (i = 0; - cond_except_table[i].cond && - !LIB$MATCH_COND (&sigargs[1], &cond_except_table[i].cond); - i++); - exception = (struct Exception_Data *) - cond_except_table [i].except; - - if (!exception) - /* User programs expect Non_Ada_Error to be raised, reference - DEC Ada test CXCONDHAN. */ - exception = &Non_Ada_Error; - } + cond = *scan_conditions (sigargs, &cond_table); + exception = (struct Exception_Data *) cond.except; } + + if (exception) + needs_adjust = cond.needs_adjust; + else + /* User programs expect Non_Ada_Error to be raised if no match, + reference DEC Ada test CXCONDHAN. */ + exception = &Non_Ada_Error; + } #else - exception = &program_error; + { + /* Pretty much everything is just a program error in the compiler */ + exception = &program_error; + } #endif - message[0] = 0; - /* Subtract PC & PSL fields which messes with PUTMSG. */ - sigargs[0] -= 2; - SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message); - sigargs[0] += 2; - msg = message; - break; - } + + message[0] = 0; + /* Subtract PC & PSL fields as per ABI for SYS$PUTMSG. */ + sigargs[0] -= 2; + SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message); + /* Add back PC & PSL fields as per ABI for SYS$PUTMSG. */ + sigargs[0] += 2; + msg = message; + + if (needs_adjust) + __gnat_adjust_context_for_raise (sigargs [1], (void *)mechargs); Raise_From_Signal_Handler (exception, msg); } @@ -1244,11 +1275,11 @@ __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext) if (signo == SS$_HPARITH) { /* Sub one to the address of the instruction signaling the condition, - located in the sigargs array. */ + located in the sigargs array. */ CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext; CHF$SIGNAL_ARRAY * sigargs - = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr; + = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr; int vcount = sigargs->chf$is_sig_args; int * pc_slot = & (&sigargs->chf$l_sig_name)[vcount-2]; |