📄 except.c
字号:
voidpop_handler (used) int used;{ action_nesting_level--; if (pass == 1) { struct handler_state *old = current_handler; if (old == NULL) fatal ("internal error: on stack out of sync"); 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 voidemit_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. */ extern int maximum_field_alignment; 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. */voidchill_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);}voidchill_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);}voidchill_handle_on_labels (labels) tree labels;{ 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 = current_handler->on_alt_list; while (TREE_INT_CST_LOW (TREE_PURPOSE (tmp)) != alternative) 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); }}voidchill_start_default_handler (){ current_handler->else_handler = ++current_handler->prev_on_alternative; if (!ignoring) { chill_handle_case_default (); }}voidchill_check_no_handlers (){ if (current_handler != NULL) fatal ("internal error: on stack not empty when done");}static voidinitialize_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), 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, NOT_BUILT_IN, NULL_PTR); unlink_handler_decl = builtin_function ("__ch_unlink_handler", link_ftype, 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. */voidexpand_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 (TREE_INT_CST_LOW (TREE_PURPOSE (list)) > label_level) 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*/intis_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. */voidchill_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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -