📄 except.c
字号:
t = build_modify_expr (saved_pc, NOP_EXPR, make_tree (ptr_type_node, return_val_rtx)); expand_expr (t, const0_rtx, VOIDmode, 0); do_unwind (gen_rtx (LABEL_REF, Pmode, top_of_loop)); emit_jump (top_of_loop); /* no it didn't --> therefore we need to call terminate */ emit_label (gotta_call_terminate); do_function_call (Terminate, NULL_TREE, NULL_TREE); assemble_external (TREE_OPERAND (Terminate, 0)); { rtx ret_val, return_val_rtx; emit_label (unwind_first); ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS, 0, hard_frame_pointer_rtx); /* Set it up so that we continue inside, at the top of the loop. */ emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, top_of_loop));#ifdef NORMAL_RETURN_ADDR_OFFSET return_val_rtx = plus_constant (ret_val, -NORMAL_RETURN_ADDR_OFFSET); if (return_val_rtx != ret_val) emit_move_insn (ret_val, return_val_rtx);#endif /* Fall into epilogue to unwind prologue. */ } expand_end_bindings (getdecls(), 1, 0); poplevel (1, 0, 0); pop_momentary (); finish_function (lineno, 0, 0);}voidexpand_start_eh_spec (){ start_protect ();}voidexpand_end_eh_spec (raises) tree raises;{ tree expr, second_try; rtx check = gen_label_rtx (); rtx cont; rtx ret = gen_reg_rtx (Pmode); rtx flag = gen_reg_rtx (TYPE_MODE (integer_type_node)); rtx end = gen_label_rtx (); expr = make_node (RTL_EXPR); TREE_TYPE (expr) = void_type_node; RTL_EXPR_RTL (expr) = const0_rtx; TREE_SIDE_EFFECTS (expr) = 1; start_sequence_for_rtl_expr (expr); cont = gen_label_rtx (); emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont)); emit_jump (check); emit_label (cont); jumpif (make_tree (integer_type_node, flag), end); do_function_call (Terminate, NULL_TREE, NULL_TREE); assemble_external (TREE_OPERAND (Terminate, 0)); emit_barrier (); RTL_EXPR_SEQUENCE (expr) = get_insns (); end_sequence (); second_try = expr; expr = make_node (RTL_EXPR); TREE_TYPE (expr) = void_type_node; RTL_EXPR_RTL (expr) = const0_rtx; TREE_SIDE_EFFECTS (expr) = 1; start_sequence_for_rtl_expr (expr); cont = gen_label_rtx (); emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont)); emit_jump (check); emit_label (cont); jumpif (make_tree (integer_type_node, flag), end); start_protect (); do_function_call (Unexpected, NULL_TREE, NULL_TREE); assemble_external (TREE_OPERAND (Unexpected, 0)); emit_barrier (); end_protect (second_try); emit_label (check); emit_move_insn (flag, const1_rtx); cont = gen_label_rtx (); while (raises) { tree exp; tree match_type = TREE_VALUE (raises); if (match_type) { /* check TREE_VALUE (raises) here */ exp = saved_throw_value; exp = tree_cons (NULL_TREE, build_eh_type_type (match_type), tree_cons (NULL_TREE, saved_throw_type, tree_cons (NULL_TREE, exp, NULL_TREE))); exp = build_function_call (CatchMatch, exp); assemble_external (TREE_OPERAND (CatchMatch, 0)); jumpif (exp, cont); } raises = TREE_CHAIN (raises); } emit_move_insn (flag, const0_rtx); emit_label (cont); emit_indirect_jump (ret); emit_label (end); RTL_EXPR_SEQUENCE (expr) = get_insns (); end_sequence (); end_protect (expr);}/* This is called to expand all the toplevel exception handling finalization for a function. It should only be called once per function. */voidexpand_exception_blocks (){ static rtx funcend; rtx insns; start_sequence (); funcend = gen_label_rtx (); emit_jump (funcend); /* expand_null_return (); */ start_sequence (); /* Add all the catch clauses here. */ emit_insns (catch_clauses); catch_clauses = NULL_RTX; expand_leftover_cleanups (); insns = get_insns (); end_sequence (); /* Do this after we expand leftover cleanups, so that the end_protect that expand_end_eh_spec does will match the right start_protect, and make sure it comes out before the terminate protected region. */ if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl))) { expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl))); push_to_sequence (insns); /* Now expand any new ones. */ expand_leftover_cleanups (); insns = get_insns (); end_sequence (); } if (insns) { struct ehEntry entry; /* 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 (); entry.finalization = TerminateFunctionCall; entry.context = current_function_decl; assemble_external (TREE_OPERAND (Terminate, 0)); 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; emit_label (entry.start_label); emit_insns (insns); enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry)); emit_label (entry.exception_handler_label); expand_expr (entry.finalization, const0_rtx, VOIDmode, 0); emit_label (entry.end_label); emit_barrier (); } { /* Mark the end of the stack unwinder. */ rtx unwind_insns; start_sequence (); end_eh_unwinder (funcend); expand_leftover_cleanups (); unwind_insns = get_insns (); end_sequence (); if (unwind_insns) { insns = unwind_insns; emit_insns (insns); } } emit_label (funcend); /* Only if we had previous insns do we want to emit the jump around them. If there weren't any, then insns will remain NULL_RTX. */ if (insns) insns = get_insns (); end_sequence (); emit_insns (insns);}/* call this to expand a throw statement. This follows the following algorithm: 1. Allocate space to save the current PC onto the stack. 2. Generate and emit a label and save its address into the newly allocated stack space since we can't save the pc directly. 3. If this is the first call to throw in this function: generate a label for the throw block 4. jump to the throw block label. */voidexpand_throw (exp) tree exp;{ rtx label; if (! doing_eh (1)) return; /* This is the label that represents where in the code we were, when we got an exception. This needs to be updated when we rethrow an exception, so that the matching routine knows to search out. */ label = gen_label_rtx (); emit_label (label); if (exp) { tree throw_type; tree e; /* throw expression */ /* First, decay it. */ exp = decay_conversion (exp); if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE) { throw_type = build_eh_type (exp); exp = build_reinterpret_cast (ptr_type_node, exp); } else { /* Make a copy of the thrown object. WP 15.1.5 */ exp = build_new (NULL_TREE, TREE_TYPE (exp), build_tree_list (NULL_TREE, exp), 0); if (exp == error_mark_node) error (" in thrown expression"); throw_type = build_eh_type (build_indirect_ref (exp, NULL_PTR)); } e = build_modify_expr (saved_throw_type, NOP_EXPR, throw_type); expand_expr (e, const0_rtx, VOIDmode, 0); e = build_modify_expr (saved_throw_value, NOP_EXPR, exp); e = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (e), e); expand_expr (e, const0_rtx, VOIDmode, 0); } else { /* rethrow current exception */ /* This part is easy, as we don't have to do anything else. */ } expand_internal_throw (gen_rtx (LABEL_REF, Pmode, label));}voidend_protect_partials () { while (protect_list) { end_protect (TREE_VALUE (protect_list)); protect_list = TREE_CHAIN (protect_list); }}intmight_have_exceptions_p (){ if (eh_table_output_queue.head) return 1; return 0;}/* Output the exception table. Return the number of handlers. */voidemit_exception_table (){ int count = 0; extern FILE *asm_out_file; struct ehEntry *entry; tree eh_node_decl; if (! doing_eh (0)) return; exception_section (); /* Beginning marker for table. */ assemble_align (GET_MODE_ALIGNMENT (Pmode)); assemble_label ("__EXCEPTION_TABLE__"); output_exception_table_entry (asm_out_file, const0_rtx, const0_rtx, const0_rtx); while (entry = dequeue_eh_entry (&eh_table_output_queue)) { tree context = entry->context; if (context && ! TREE_ASM_WRITTEN (context)) continue; count++; output_exception_table_entry (asm_out_file, entry->start_label, entry->end_label, entry->exception_handler_label); } /* Ending marker for table. */ assemble_label ("__EXCEPTION_END__"); output_exception_table_entry (asm_out_file, constm1_rtx, constm1_rtx, constm1_rtx);}voidregister_exception_table (){ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__register_exceptions"), 0, VOIDmode, 1, gen_rtx (SYMBOL_REF, Pmode, "__EXCEPTION_TABLE__"), Pmode);}/* Build a throw expression. */treebuild_throw (e) tree e;{ if (e != error_mark_node) { e = build1 (THROW_EXPR, void_type_node, e); TREE_SIDE_EFFECTS (e) = 1; TREE_USED (e) = 1; } return e;}start_eh_unwinder (){ start_protect ();}end_eh_unwinder (end) rtx end;{ tree expr; rtx return_val_rtx, ret_val, label; if (! doing_eh (0)) return; expr = make_node (RTL_EXPR); TREE_TYPE (expr) = void_type_node; RTL_EXPR_RTL (expr) = const0_rtx; TREE_SIDE_EFFECTS (expr) = 1; start_sequence_for_rtl_expr (expr); ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS, 0, hard_frame_pointer_rtx); return_val_rtx = copy_to_reg (ret_val);#ifdef NORMAL_RETURN_ADDR_OFFSET return_val_rtx = plus_constant (return_val_rtx, NORMAL_RETURN_ADDR_OFFSET-1);#else return_val_rtx = plus_constant (return_val_rtx, -1);#endif emit_move_insn (DECL_RTL (saved_pc), return_val_rtx); #ifdef JUMP_TO_THROW emit_move_insn (ret_val, gen_rtx (SYMBOL_REF, Pmode, "__throw"));#else label = gen_label_rtx (); emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, label));#endif#ifdef NORMAL_RETURN_ADDR_OFFSET return_val_rtx = plus_constant (ret_val, -NORMAL_RETURN_ADDR_OFFSET); if (return_val_rtx != ret_val) emit_move_insn (ret_val, return_val_rtx);#endif emit_jump (end); #ifndef JUMP_TO_THROW emit_label (label); do_function_call (Throw, NULL_TREE, NULL_TREE);#endif RTL_EXPR_SEQUENCE (expr) = get_insns (); end_sequence (); end_protect (expr);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -