aboutsummaryrefslogtreecommitdiff
path: root/gcc/ch/except.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ch/except.c')
-rw-r--r--gcc/ch/except.c707
1 files changed, 0 insertions, 707 deletions
diff --git a/gcc/ch/except.c b/gcc/ch/except.c
deleted file mode 100644
index 1c8ef242231..00000000000
--- 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);
-}