📄 except.c
字号:
return NULL_RTX; } /* These are saved for the exception table. */ push_rtl_perm (); entry->start_label = gen_label_rtx (); entry->end_label = gen_label_rtx (); entry->exception_handler_label = gen_label_rtx (); pop_rtl_from_perm (); LABEL_PRESERVE_P (entry->start_label) = 1; LABEL_PRESERVE_P (entry->end_label) = 1; LABEL_PRESERVE_P (entry->exception_handler_label) = 1; entry->finalization = NULL_TREE; entry->context = current_function_decl; node->entry = entry; node->chain = stack->top; stack->top = node; enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry)); return entry->start_label;}static struct ehEntry *pop_eh_entry (stack) struct ehStack *stack;{ struct ehNode *tempnode; struct ehEntry *tempentry; if (stack && (tempnode = stack->top)) { tempentry = tempnode->entry; stack->top = stack->top->chain; free (tempnode); return tempentry; } return NULL;}static struct ehEntry *copy_eh_entry (entry) struct ehEntry *entry;{ struct ehEntry *newentry; newentry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry)); memcpy ((void*)newentry, (void*)entry, sizeof (struct ehEntry)); return newentry;}static voidenqueue_eh_entry (queue, entry) struct ehQueue *queue; struct ehEntry *entry;{ struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode)); node->entry = entry; node->chain = NULL; if (queue->head == NULL) { queue->head = node; } else { queue->tail->chain = node; } queue->tail = node;}static struct ehEntry *dequeue_eh_entry (queue) struct ehQueue *queue;{ struct ehNode *tempnode; struct ehEntry *tempentry; if (queue->head == NULL) return NULL; tempnode = queue->head; queue->head = queue->head->chain; tempentry = tempnode->entry; free (tempnode); return tempentry;}static voidnew_eh_queue (queue) struct ehQueue *queue;{ queue->head = queue->tail = NULL;}static voidnew_eh_stack (stack) struct ehStack *stack;{ stack->top = NULL;}/* cheesyness to save some typing. returns the return value rtx */rtxdo_function_call (func, params, return_type) tree func, params, return_type;{ tree func_call; func_call = build_function_call (func, params); expand_call (func_call, NULL_RTX, 0); if (return_type != NULL_TREE) return hard_function_value (return_type, func_call); return NULL_RTX;}static voidexpand_internal_throw (pc) rtx pc;{ tree params; emit_move_insn (DECL_RTL (saved_pc), pc);#ifdef JUMP_TO_THROW emit_indirect_jump (gen_rtx (SYMBOL_REF, Pmode, "__throw"));#else do_function_call (Throw, NULL_TREE, NULL_TREE);#endif throw_used = 1;}/* ========================================================================= */voidlang_interim_eh (finalization) tree finalization;{ if (finalization) end_protect (finalization); else start_protect ();}extern tree auto_function PROTO((tree, tree, enum built_in_function));/* sets up all the global eh stuff that needs to be initialized at the start of compilation. This includes: - Setting up all the function call trees - Initializing the ehqueue - Initializing the eh_table_output_queue - Initializing the ehstack*/voidinit_exception_processing (){ extern tree define_function (); tree unexpected_fndecl, terminate_fndecl; tree set_unexpected_fndecl, set_terminate_fndecl; tree catch_match_fndecl; tree find_first_exception_match_fndecl; tree unwind_fndecl; tree declspecs; tree d; /* void (*)() */ tree PFV = build_pointer_type (build_function_type (void_type_node, void_list_node)); /* arg list for the build_function_type call for set_terminate () and set_unexpected () */ tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node); /* void (*pfvtype (void (*) ()))() */ tree pfvtype = build_function_type (PFV, pfvlist); /* void vtype () */ tree vtype = build_function_type (void_type_node, void_list_node); set_terminate_fndecl = auto_function (get_identifier ("set_terminate"), pfvtype, NOT_BUILT_IN); set_unexpected_fndecl = auto_function (get_identifier ("set_unexpected"), pfvtype, NOT_BUILT_IN); unexpected_fndecl = auto_function (get_identifier ("unexpected"), vtype, NOT_BUILT_IN); terminate_fndecl = auto_function (get_identifier ("terminate"), vtype, NOT_BUILT_IN); interim_eh_hook = lang_interim_eh; push_lang_context (lang_name_c); catch_match_fndecl = define_function (flag_rtti ? "__throw_type_match_rtti" : "__throw_type_match", build_function_type (ptr_type_node, tree_cons (NULL_TREE, ptr_type_node, tree_cons (NULL_TREE, ptr_type_node, tree_cons (NULL_TREE, ptr_type_node, void_list_node)))), NOT_BUILT_IN, pushdecl, 0); find_first_exception_match_fndecl = define_function ("__find_first_exception_table_match", build_function_type (ptr_type_node, tree_cons (NULL_TREE, ptr_type_node, void_list_node)), NOT_BUILT_IN, pushdecl, 0); unwind_fndecl = define_function ("__unwind_function", build_function_type (void_type_node, tree_cons (NULL_TREE, ptr_type_node, void_list_node)), NOT_BUILT_IN, pushdecl, 0); throw_fndecl = define_function ("__throw", build_function_type (void_type_node, void_list_node), NOT_BUILT_IN, pushdecl, 0); DECL_EXTERNAL (throw_fndecl) = 0; TREE_PUBLIC (throw_fndecl) = 0; Unexpected = default_conversion (unexpected_fndecl); Terminate = default_conversion (terminate_fndecl); SetTerminate = default_conversion (set_terminate_fndecl); SetUnexpected = default_conversion (set_unexpected_fndecl); CatchMatch = default_conversion (catch_match_fndecl); FirstExceptionMatch = default_conversion (find_first_exception_match_fndecl); Unwind = default_conversion (unwind_fndecl); Throw = default_conversion (throw_fndecl); BuiltinReturnAddress = default_conversion (builtin_return_address_fndecl); TerminateFunctionCall = build_function_call (Terminate, NULL_TREE); pop_lang_context (); new_eh_queue (&ehqueue); new_eh_queue (&eh_table_output_queue); new_eh_stack (&ehstack); declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE); d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_pc")); d = start_decl (d, declspecs, 0, NULL_TREE); DECL_COMMON (d) = 1; cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); saved_pc = lookup_name (get_identifier ("__eh_pc"), 0); declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE); d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_type")); d = start_decl (d, declspecs, 0, NULL_TREE); DECL_COMMON (d) = 1; cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); saved_throw_type = lookup_name (get_identifier ("__eh_type"), 0); declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE); d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_value")); d = start_decl (d, declspecs, 0, NULL_TREE); DECL_COMMON (d) = 1; cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); saved_throw_value = lookup_name (get_identifier ("__eh_value"), 0);}/* call this to begin a block of unwind protection (ie: when an object is constructed) */voidstart_protect (){ if (! doing_eh (0)) return; emit_label (push_eh_entry (&ehstack));} /* call this to end a block of unwind protection. the finalization tree is the finalization which needs to be run in order to cleanly unwind through this level of protection. (ie: call this when a scope is exited)*/voidend_protect (finalization) tree finalization;{ struct ehEntry *entry; if (! doing_eh (0)) return; entry = pop_eh_entry (&ehstack); emit_label (entry->end_label); /* Put in something that takes up space, as otherwise the end address for the EH region could have the exact same address as the outer region, causing us to miss the fact that resuming exception handling with this PC value would be inside the outer region. */ emit_insn (gen_nop ()); entry->finalization = finalization; enqueue_eh_entry (&ehqueue, entry);}/* call this on start of a try block. */voidexpand_start_try_stmts (){ if (! doing_eh (1)) return; start_protect ();}voidexpand_end_try_stmts (){ end_protect (integer_zero_node);}/* call this to start processing of all the catch blocks. */voidexpand_start_all_catch (){ struct ehEntry *entry; rtx label; if (! doing_eh (1)) return; emit_line_note (input_filename, lineno); label = gen_label_rtx (); /* The label for the exception handling block we will save. This is Lresume, in the documention. */ emit_label (label); /* Put in something that takes up space, as otherwise the end address for the EH region could have the exact same address as the outer region, causing us to miss the fact that resuming exception handling with this PC value would be inside the outer region. */ emit_insn (gen_nop ()); push_label_entry (&caught_return_label_stack, label); /* Start a new sequence for all the catch blocks. We will add this to the gloabl sequence catch_clauses, when we have completed all the handlers in this handler-seq. */ start_sequence (); while (1) { entry = dequeue_eh_entry (&ehqueue); emit_label (entry->exception_handler_label); expand_expr (entry->finalization, const0_rtx, VOIDmode, 0); /* When we get down to the matching entry, stop. */ if (entry->finalization == integer_zero_node) break; /* The below can be optimized away, and we could just fall into the next EH handler, if we are certain they are nested. */ /* Code to throw out to outer context, if we fall off end of the handler. */ expand_internal_throw (gen_rtx (LABEL_REF, Pmode, entry->end_label)); free (entry); }}/* call this to end processing of all the catch blocks. */voidexpand_end_all_catch (){ rtx new_catch_clause; if (! doing_eh (1)) return; /* Code to throw out to outer context, if we fall off end of catch handlers. This is rethrow (Lresume, same id, same obj); in the documentation. */ expand_internal_throw (gen_rtx (LABEL_REF, Pmode, top_label_entry (&caught_return_label_stack))); /* Now we have the complete catch sequence. */ new_catch_clause = get_insns (); end_sequence (); /* this level of catch blocks is done, so set up the successful catch jump label for the next layer of catch blocks. */ pop_label_entry (&caught_return_label_stack); /* Add the new sequence of catchs to the main one for this function. */ push_to_sequence (catch_clauses); emit_insns (new_catch_clause); catch_clauses = get_insns (); end_sequence (); /* Here we fall through into the continuation code. */}/* Build a type value for use at runtime for a type that is matched against by the exception handling system. */static tree
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -