diff options
Diffstat (limited to 'gcc/ch/except.c')
-rw-r--r-- | gcc/ch/except.c | 707 |
1 files changed, 0 insertions, 707 deletions
diff --git a/gcc/ch/except.c b/gcc/ch/except.c deleted file mode 100644 index 1c8ef24..0000000 --- a/gcc/ch/except.c +++ /dev/null @@ -1,707 +0,0 @@ -/* Exception support for GNU CHILL. - WARNING: Only works for native (needs setjmp.h)! FIXME! - Copyright (C) 1992, 1993, 1994, 1998, 1999, 2000, 2001 - Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT 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 -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include "system.h" - -/* On Suns this can get you to the right definition if you - set the right value for TARGET. */ -#include <setjmp.h> -#ifdef sequent -/* Can you believe they forgot this? */ -#ifndef _JBLEN -#define _JBLEN 11 -#endif -#endif - -#ifndef _JBLEN -#define _JBLEN (sizeof(jmp_buf)/sizeof(int)) -#define _JBLEN_2 _JBLEN+20 -#else -/* if we use i.e. posix threads, this buffer must be longer */ -#define _JBLEN_2 _JBLEN+20 -#endif - -/* On Linux setjmp is __setjmp FIXME: what is for CROSS */ -#ifndef SETJMP_LIBRARY_NAME -#ifdef __linux__ -#define SETJMP_LIBRARY_NAME "__setjmp" -#else -#define SETJMP_LIBRARY_NAME "setjmp" -#endif -#endif - -#include "tree.h" -#include "ch-tree.h" -#include "rtl.h" -#include "toplev.h" - -extern int expand_exit_needed; - -static tree link_handler_decl; -static tree handler_link_pointer_type; -static tree unlink_handler_decl; -static int exceptions_initialized = 0; -static void emit_setup_handler PARAMS ((void)); -static void initialize_exceptions PARAMS ((void)); -static tree start_handler_array PARAMS ((void)); -static void finish_handler_array PARAMS ((void)); -static tree char_pointer_type_for_handler; - -/* If this is 1, operations to push and pop on the __exceptionStack - are inline. The default is is to use a function call, to - allow for a per-thread exception stack. */ -static int inline_exception_stack_ops = 0; - -struct handler_state -{ - struct handler_state *next; - - /* Starts at 0, then incremented for every <on-alternative>. */ - int prev_on_alternative; - - /* If > 0: handler number for ELSE handler. */ - int else_handler; - - int action_number; - - char do_pushlevel; - - tree on_alt_list; - tree setjmp_expr; - - /* A decl for the static handler array (used to map exception name to int).*/ - tree handler_array_decl; - - rtx end_label; - - /* Used to pass a tree from emit_setup_handler to chill_start_on. */ - tree handler_ref; - - tree unlink_cleanup; - - tree function; - - /* flag to indicate that we are currently compiling this handler. - is_handled will need this to determine an unhandled exception */ - int compiling; -}; - -/* This is incremented by one each time we start an action which - might have an ON-handler. It is reset between passes. */ -static int action_number = 0; - -int action_nesting_level = 0; - -/* The global_handler_list is constructed in pass 1. It is not sorted. - It contains one element for each action that actually had an ON-handler. - An element's ACTION_NUMBER matches the action_number - of that action. The global_handler_list is eaten up during pass 2. */ -#define ACTION_NUMBER(HANDLER) ((HANDLER)->action_number) -struct handler_state *global_handler_list = NULL; - -/* This is a stack of handlers, one for each nested ON-handler. */ -static struct handler_state *current_handler = NULL; - -static struct handler_state *free_handlers = NULL; /* freelist */ - -static tree handler_element_type; -static tree handler_link_type; -static tree BISJ; -static tree jbuf_ident, prev_ident, handlers_ident; -static tree exception_stack_decl = 0; - -/* Chain of cleanups associated with exception handlers. - The TREE_PURPOSE is an INTEGER_CST whose value is the - DECL_ACTION_NESTING_LEVEL (when the handled actions was entered). - The TREE_VALUE is an expression to expand when we exit that action. */ - -static tree cleanup_chain = NULL_TREE; - -#if 0 -/* Merge the current sequence onto the tail of the previous one. */ - -void -pop_sequence () -{ - rtx sequence_first = get_insns (); - - end_sequence (); - emit_insns (sequence_first); - -} -#endif - -/* Things we need to do at the beginning of pass 2. */ - -void -except_init_pass_2 () -{ - /* First sort the global_handler_list on ACTION_NUMBER. - This will already be in close to reverse order (the exception being - nested ON-handlers), so insertion sort should essentially linear. */ - - register struct handler_state *old_list = global_handler_list; - - /* First add a dummy final element. */ - if (free_handlers) - global_handler_list = free_handlers; - else - global_handler_list - = (struct handler_state*) permalloc (sizeof (struct handler_state)); - /* Make the final dummy "larger" than any other element. */ - ACTION_NUMBER (global_handler_list) = action_number + 1; - /* Now move all the elements in old_list over to global_handler_list. */ - while (old_list != NULL) - { - register struct handler_state **ptr = &global_handler_list; - /* Unlink from old_list. */ - register struct handler_state *current = old_list; - old_list = old_list->next; - - while (ACTION_NUMBER (current) > ACTION_NUMBER (*ptr)) - ptr = &(*ptr)->next; - /* Link into proper place in global_handler_list (new list). */ - current->next = *ptr; - *ptr = current; - } - - /* Don't forget to reset action_number. */ - action_number = 0; -} - -/* This function is called at the beginning of an action that might be - followed by an ON-handler. Chill syntax doesn't let us know if - we actually have an ON-handler until we see the ON, so we save - away during pass 1 that information for use during pass 2. */ - -void -push_handler () -{ - register struct handler_state *hstate; - - action_number++; - action_nesting_level++; - - if (pass == 1) - { - if (free_handlers) - { - hstate = free_handlers; - free_handlers = hstate->next; - } - else - { - hstate = - (struct handler_state*) permalloc (sizeof (struct handler_state)); - } - - hstate->next = current_handler; - current_handler = hstate; - hstate->prev_on_alternative = 0; - hstate->else_handler = 0; - hstate->on_alt_list = NULL_TREE; - hstate->compiling = 0; - - ACTION_NUMBER (hstate) = action_number; - return; - } - - if (ACTION_NUMBER (global_handler_list) != action_number) - return; - - /* OK. This action actually has an ON-handler. - Pop it from global_handler_list, and use it. */ - - hstate = global_handler_list; - global_handler_list = hstate->next; - - /* Since this is pass 2, let's generate prologue code for that. */ - - hstate->next = current_handler; - current_handler = hstate; - - hstate->prev_on_alternative = 0; - hstate->function = current_function_decl; - - emit_setup_handler (); -} - -static tree -start_handler_array () -{ - tree handler_array_type, decl; - - push_obstacks_nochange (); - end_temporary_allocation (); - handler_array_type = build_array_type (handler_element_type, NULL_TREE); - decl = build_lang_decl (VAR_DECL, - get_unique_identifier ("handler_table"), - handler_array_type); - -/* TREE_TYPE (decl) = handler_array_type;*/ - TREE_READONLY (decl) = 1; - TREE_STATIC (decl) = 1; - DECL_INITIAL (decl) = error_mark_node; - - pushdecl (decl); - make_decl_rtl (decl, NULL_PTR, 0); - current_handler->handler_array_decl = decl; - return decl; -} - -static void -finish_handler_array () -{ - tree decl = current_handler->handler_array_decl; - tree t; - tree handler_array_init = NULL_TREE; - int handlers_count = 1; - int nelts; - - /* Build the table mapping exceptions to handler(-number)s. - This is done in reverse order. */ - - /* First push the end of the list. This is either the ELSE - handler (current_handler->else_handler>0) or NULL handler to indicate - the end of the list (if current_handler->else-handler == 0). - The following works either way. */ - handler_array_init = build_tree_list - (NULL_TREE, chill_expand_tuple - (handler_element_type, - build_nt (CONSTRUCTOR, NULL_TREE, - tree_cons (NULL_TREE, - null_pointer_node, - build_tree_list (NULL_TREE, - build_int_2 (current_handler->else_handler, - 0)))))); - - for (t = current_handler->on_alt_list; t != NULL_TREE; t = TREE_CHAIN (t)) - { tree handler_number = TREE_PURPOSE(t); - tree elist = TREE_VALUE (t); - for ( ; elist != NULL_TREE; elist = TREE_CHAIN (elist)) - { - tree ex_decl = - build_chill_exception_decl (IDENTIFIER_POINTER(TREE_VALUE(elist))); - tree ex_addr = build1 (ADDR_EXPR, - char_pointer_type_for_handler, - ex_decl); - tree el = build_nt (CONSTRUCTOR, NULL_TREE, - tree_cons (NULL_TREE, - ex_addr, - build_tree_list (NULL_TREE, - handler_number))); - mark_addressable (ex_decl); - TREE_CONSTANT (ex_addr) = 1; - handler_array_init = - tree_cons (NULL_TREE, - chill_expand_tuple (handler_element_type, el), - handler_array_init); - handlers_count++; - } - } - -#if 1 - nelts = list_length (handler_array_init); - TYPE_DOMAIN (TREE_TYPE (decl)) - = build_index_type (build_int_2 (nelts - 1, - (nelts == 0))); - layout_type (TREE_TYPE (decl)); - DECL_INITIAL (decl) - = convert (TREE_TYPE (decl), - build_nt (CONSTRUCTOR, NULL_TREE, handler_array_init)); - - /* Pop back to the obstack that is current for this binding level. - This is because MAXINDEX, rtl, etc. to be made below - must go in the permanent obstack. But don't discard the - temporary data yet. */ - pop_obstacks (); - layout_decl (decl, 0); - /* To prevent make_decl_rtl (called indiectly by rest_of_decl_compilation) - throwing the existing RTL (which has already been used). */ - PUT_MODE (DECL_RTL (decl), DECL_MODE (decl)); - rest_of_decl_compilation (decl, (char*)0, 0, 0); - expand_decl_init (decl); -#else - /* To prevent make_decl_rtl (called indirectly by finish_decl) - altering the existing RTL. */ - GET_MODE (DECL_RTL (current_handler->handler_array_decl)) = - DECL_MODE (current_handler->handler_array_decl); - - finish_decl (current_handler->handler_array_decl, - build_nt (CONSTRUCTOR, NULL_TREE, handler_array_init), - NULL_TREE); -#endif -} - - -void -pop_handler (used) - int used; -{ - action_nesting_level--; - if (pass == 1) - { - struct handler_state *old = current_handler; - - if (old == NULL) - abort (); - current_handler = old->next; - - if (used) - { /* Push unto global_handler_list. */ - old->next = global_handler_list; - global_handler_list = old; - } - else - { - /* Push onto free_handlers free list. */ - old->next = free_handlers; - free_handlers = old; - } - } - else if (used) - { - current_handler = current_handler->next; - } -} - -/* Emit code before an action that has an ON-handler. */ - -static void -emit_setup_handler () -{ - tree handler_decl, handler_addr, t; - - /* Field references. */ - tree jbuf_ref, handlers_ref,prev_ref; - if (!exceptions_initialized) - { - /* We temporarily reset the maximum_field_alignment to zero so the - compiler's exception data structures can be compatible with the - run-time system, even when we're compiling with -fpack. */ - unsigned int save_maximum_field_alignment = maximum_field_alignment; - maximum_field_alignment = 0; - push_obstacks_nochange (); - end_temporary_allocation (); - initialize_exceptions (); - pop_obstacks (); - maximum_field_alignment = save_maximum_field_alignment; - } - - push_momentary (); - - handler_decl = build_lang_decl (VAR_DECL, - get_unique_identifier ("handler"), - handler_link_type); - push_obstacks_nochange (); - pushdecl(handler_decl); - expand_decl (handler_decl); - finish_decl (handler_decl); - - jbuf_ref = build_component_ref (handler_decl, jbuf_ident); - jbuf_ref = build_chill_arrow_expr (jbuf_ref, 1); - handlers_ref = build_component_ref (handler_decl, handlers_ident); - prev_ref = build_component_ref (handler_decl, prev_ident); - - /* Emit code to link in handler in __exceptionStack chain. */ - mark_addressable (handler_decl); - handler_addr = build1 (ADDR_EXPR, handler_link_pointer_type, handler_decl); - if (inline_exception_stack_ops) - { - expand_expr_stmt (build_chill_modify_expr (prev_ref, - exception_stack_decl)); - expand_expr_stmt (build_chill_modify_expr (exception_stack_decl, - handler_addr)); - current_handler->handler_ref = prev_ref; - } - else - { - expand_expr_stmt (build_chill_function_call (link_handler_decl, - build_tree_list (NULL_TREE, - handler_addr))); - current_handler->handler_ref = handler_addr; - } - - /* Expand: handler->__handlers = { <<array mapping names to ints } */ - t = build1 (NOP_EXPR, build_pointer_type (handler_element_type), - build_chill_arrow_expr (start_handler_array (), 1)); - expand_expr_stmt (build_chill_modify_expr (handlers_ref, t)); - - /* Emit code to unlink handler. */ - if (inline_exception_stack_ops) - current_handler->unlink_cleanup - = build_chill_modify_expr (exception_stack_decl, - current_handler->handler_ref); - else - current_handler->unlink_cleanup - = build_chill_function_call (unlink_handler_decl, - build_tree_list(NULL_TREE, - current_handler->handler_ref)); - cleanup_chain = tree_cons (build_int_2 (action_nesting_level, 0), - current_handler->unlink_cleanup, - cleanup_chain); - - /* Emit code for setjmp. */ - - current_handler->setjmp_expr = - build_chill_function_call (BISJ, build_tree_list (NULL_TREE, jbuf_ref)); - expand_start_case (1, current_handler->setjmp_expr, - integer_type_node, "on handler"); - - chill_handle_case_label (integer_zero_node, current_handler->setjmp_expr); -} - -/* Start emitting code for: <actions> ON <handlers> END. - Assume we've parsed <actions>, and the setup needed for it. */ - -void -chill_start_on () -{ - expand_expr_stmt (current_handler->unlink_cleanup); - - /* Emit code to jump past the handlers. */ - current_handler->end_label = gen_label_rtx (); - current_handler->compiling = 1; - emit_jump (current_handler->end_label); -} - -void -chill_finish_on () -{ - expand_end_case (current_handler->setjmp_expr); - - finish_handler_array (); - - emit_label (current_handler->end_label); - - pop_momentary (); - - cleanup_chain = TREE_CHAIN (cleanup_chain); -} - -void -chill_handle_on_labels (labels) - tree labels; -{ - unsigned int alternative = ++current_handler->prev_on_alternative; - if (pass == 1) - { - tree handler_number = build_int_2 (alternative, 0); - current_handler->on_alt_list = - tree_cons (handler_number, labels, current_handler->on_alt_list); - } - else - { - /* Find handler_number saved in pass 1. */ - tree tmp; - - for (tmp = current_handler->on_alt_list; - compare_tree_int (TREE_PURPOSE (tmp), alternative) != 0; - tmp = TREE_CHAIN (tmp)) - ; - - if (expand_exit_needed) - expand_exit_something (), expand_exit_needed = 0; - chill_handle_case_label (TREE_PURPOSE (tmp), - current_handler->setjmp_expr); - } -} - -void -chill_start_default_handler () -{ - current_handler->else_handler = ++current_handler->prev_on_alternative; - if (!ignoring) - { - chill_handle_case_default (); - } -} - -void -chill_check_no_handlers () -{ - if (current_handler != NULL) - abort (); -} - -static void -initialize_exceptions () -{ - tree jmp_buf_type = build_array_type (integer_type_node, - build_index_type (build_int_2 (_JBLEN_2-1, 0))); - tree setjmp_fndecl, link_ftype; - tree parmtypes - = tree_cons (NULL_TREE, build_pointer_type (jmp_buf_type), void_list_node); - - setjmp_fndecl = builtin_function ("setjmp", - build_function_type (integer_type_node, - parmtypes), - 0, NOT_BUILT_IN, - SETJMP_LIBRARY_NAME); - BISJ = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (setjmp_fndecl)), - setjmp_fndecl); - - char_pointer_type_for_handler - = build_pointer_type (build_type_variant (char_type_node, 1, 0)); - handler_element_type = - build_chill_struct_type (chainon - (build_decl (FIELD_DECL, - get_identifier("__exceptid"), - char_pointer_type_for_handler), - build_decl (FIELD_DECL, - get_identifier("__handlerno"), - integer_type_node))); - - jbuf_ident = get_identifier("__jbuf"); - prev_ident = get_identifier("__prev"); - handlers_ident = get_identifier("__handlers"); - - handler_link_type = - build_chill_struct_type - (chainon - (build_decl (FIELD_DECL, prev_ident, ptr_type_node), - chainon - (build_decl (FIELD_DECL, handlers_ident, - build_pointer_type (handler_element_type)), - build_decl (FIELD_DECL, jbuf_ident, jmp_buf_type)))); - - handler_link_pointer_type = build_pointer_type (handler_link_type); - - if (inline_exception_stack_ops) - { - exception_stack_decl = - build_lang_decl (VAR_DECL, - get_identifier("__exceptionStack"), - handler_link_pointer_type); - TREE_STATIC (exception_stack_decl) = 1; - TREE_PUBLIC (exception_stack_decl) = 1; - DECL_EXTERNAL (exception_stack_decl) = 1; - push_obstacks_nochange (); - pushdecl(exception_stack_decl); - make_decl_rtl (exception_stack_decl, NULL_PTR, 1); - finish_decl (exception_stack_decl); - } - - link_ftype = build_function_type (void_type_node, - tree_cons (NULL_TREE, - handler_link_pointer_type, - void_list_node)); - link_handler_decl = builtin_function ("__ch_link_handler", link_ftype, - 0, NOT_BUILT_IN, NULL_PTR); - unlink_handler_decl = builtin_function ("__ch_unlink_handler", link_ftype, - 0, NOT_BUILT_IN, NULL_PTR); - - exceptions_initialized = 1; -} - -/* Do the cleanup(s) needed for a GOTO label. - We only need to do the last of the cleanups. */ - -void -expand_goto_except_cleanup (label_level) - int label_level; -{ - tree list = cleanup_chain; - tree last = NULL_TREE; - for ( ; list != NULL_TREE; list = TREE_CHAIN (list)) - { - if (compare_tree_int (TREE_PURPOSE (list), label_level) > 0) - last = list; - else - break; - } - if (last) - expand_expr_stmt (TREE_VALUE (last)); -} - -/* Returns true if there is a valid handler for EXCEPT_NAME - in the current static scope. - 0 ... no handler found - 1 ... local handler available - 2 ... function may propagate this exception -*/ - -int -is_handled (except_name) - tree except_name; -{ - tree t; - struct handler_state *h = current_handler; - - /* if we are are currently compiling this handler - we have to start at the next level */ - if (h && h->compiling) - h = h->next; - while (h != NULL) - { - if (h->function != current_function_decl) - break; - if (h->else_handler > 0) - return 1; - for (t = h->on_alt_list; t != NULL_TREE; t = TREE_CHAIN (t)) - { - if (value_member (except_name, TREE_VALUE (t))) - return 1; - } - h = h->next; - } - - t = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)); - - if (value_member (except_name, t)) - return 2; - return 0; -} - -/* function generates code to reraise exceptions - for PROC's propagating exceptions. */ - -void -chill_reraise_exceptions (exceptions) - tree exceptions; -{ - tree wrk; - - if (exceptions == NULL_TREE) - return; /* just in case */ - - if (pass == 1) - { - for (wrk = exceptions; wrk != NULL_TREE; wrk = TREE_CHAIN (wrk)) - chill_handle_on_labels (build_tree_list (NULL_TREE, TREE_VALUE (wrk))); - } - else /* pass == 2 */ - { - chill_start_on (); - expand_exit_needed = 0; - - for (wrk = exceptions; wrk != NULL_TREE; wrk = TREE_CHAIN (wrk)) - { - chill_handle_on_labels (TREE_VALUE (wrk)); - /* do a CAUSE exception */ - expand_expr_stmt (build_cause_exception (TREE_VALUE (wrk), 0)); - expand_exit_needed = 1; - } - chill_finish_on (); - } - pop_handler (1); -} |