⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 except.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 4 页
字号:
build_eh_type_type (type)     tree type;{  char *typestring;  tree exp;  if (type == error_mark_node)    return error_mark_node;  /* peel back references, so they match. */  if (TREE_CODE (type) == REFERENCE_TYPE)    type = TREE_TYPE (type);  /* Peel off cv qualifiers. */  type = TYPE_MAIN_VARIANT (type);  if (flag_rtti)    {      return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));    }  typestring = build_overload_name (type, 1, 1);  exp = combine_strings (build_string (strlen (typestring)+1, typestring));  return build1 (ADDR_EXPR, ptr_type_node, exp);}/* Build a type value for use at runtime for a exp that is thrown or   matched against by the exception handling system.  */static treebuild_eh_type (exp)     tree exp;{  if (flag_rtti)    {      exp = build_typeid (exp);      return build1 (ADDR_EXPR, ptr_type_node, exp);    }  return build_eh_type_type (TREE_TYPE (exp));}/* call this to start a catch block. Typename is the typename, and identifier   is the variable to place the object in or NULL if the variable doesn't   matter.  If typename is NULL, that means its a "catch (...)" or catch   everything.  In that case we don't need to do any type checking.   (ie: it ends up as the "else" clause rather than an "else if" clause) */voidexpand_start_catch_block (declspecs, declarator)     tree declspecs, declarator;{  rtx false_label_rtx;  rtx protect_label_rtx;  tree decl = NULL_TREE;  tree init;  if (! doing_eh (1))    return;  /* Create a binding level for the parm.  */  expand_start_bindings (0);  false_label_rtx = gen_label_rtx ();  /* This is saved for the exception table.  */  push_rtl_perm ();  protect_label_rtx = gen_label_rtx ();  pop_rtl_from_perm ();  push_label_entry (&false_label_stack, false_label_rtx);  push_label_entry (&false_label_stack, protect_label_rtx);  if (declspecs)    {      tree exp;      rtx call_rtx, return_value_rtx;      tree init_type;      decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1,			     NULL_TREE, NULL_TREE);      if (decl == NULL_TREE)	{	  error ("invalid catch parameter");	  return;	}      /* Figure out the type that the initializer is. */      init_type = TREE_TYPE (decl);      if (TREE_CODE (init_type) != REFERENCE_TYPE	  && TREE_CODE (init_type) != POINTER_TYPE)	init_type = build_reference_type (init_type);      exp = saved_throw_value;      exp = tree_cons (NULL_TREE,		       build_eh_type_type (TREE_TYPE (decl)),		       tree_cons (NULL_TREE,				  saved_throw_type,				  tree_cons (NULL_TREE, exp, NULL_TREE)));      exp = build_function_call (CatchMatch, exp);      call_rtx = expand_call (exp, NULL_RTX, 0);      assemble_external (TREE_OPERAND (CatchMatch, 0));      return_value_rtx = hard_function_value (ptr_type_node, exp);      /* did the throw type match function return TRUE? */      emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,		    GET_MODE (return_value_rtx), 0, 0);      /* if it returned FALSE, jump over the catch block, else fall into it */      emit_jump_insn (gen_beq (false_label_rtx));      init = convert_from_reference (save_expr (make_tree (init_type, call_rtx)));      /* Do we need the below two lines? */      /* Let `cp_finish_decl' know that this initializer is ok.  */      DECL_INITIAL (decl) = init;      decl = pushdecl (decl);      cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);    }  else    {      /* Fall into the catch all section. */    }  /* This is the starting of something to protect.  */  emit_label (protect_label_rtx);  emit_line_note (input_filename, lineno);}/* this is called from expand_exception_blocks and   expand_end_catch_block to expand the toplevel finalizations for a   function.  We return the first label emitted, if any, otherwise   return NULL_RTX.  */static rtxexpand_leftover_cleanups (){  struct ehEntry *entry;  rtx first_label = NULL_RTX;  while ((entry = dequeue_eh_entry (&ehqueue)) != 0)    {      if (! first_label)	first_label = entry->exception_handler_label;      emit_label (entry->exception_handler_label);      expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);      /* 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));      /* leftover try block, opps.  */      if (entry->finalization == integer_zero_node)	abort ();      free (entry);    }  return first_label;}/* Call this to end a catch block.  Its responsible for emitting the   code to handle jumping back to the correct place, and for emitting   the label to jump to if this catch block didn't match.  */void expand_end_catch_block (){  rtx start_protect_label_rtx;  rtx end_protect_label_rtx;  tree decls;  struct ehEntry entry;  if (! doing_eh (1))    return;  /* fall to outside the try statement when done executing handler and     we fall off end of handler.  This is jump Lresume in the     documentation.  */  emit_jump (top_label_entry (&caught_return_label_stack));  /* We end the rethrow protection region as soon as we hit a label. */  end_protect_label_rtx = expand_leftover_cleanups ();  /* Code to throw out to outer context, if we get a throw from within     our catch handler. */  /* These are saved for the exception table.  */  push_rtl_perm ();  entry.exception_handler_label = gen_label_rtx ();  pop_rtl_from_perm ();  /* This label is Lhandler in the documentation.  */  emit_label (entry.exception_handler_label);  expand_internal_throw (gen_rtx (LABEL_REF,				  Pmode,				  top_label_entry (&caught_return_label_stack)));  /* No associated finalization.  */  entry.finalization = NULL_TREE;  entry.context = current_function_decl;  if (end_protect_label_rtx == NULL_RTX)    end_protect_label_rtx = entry.exception_handler_label;  /* Because we are emitted out of line, we have to protect this. */  /* label for the start of the protection region.  */  start_protect_label_rtx = pop_label_entry (&false_label_stack);  /* Cleanup the EH parameter.  */  decls = getdecls ();  expand_end_bindings (decls, decls != NULL_TREE, 0);        /* label we emit to jump to if this catch block didn't match. */  /* This the closing } in the `if (eq) {' of the documentation.  */  emit_label (pop_label_entry (&false_label_stack));  /* Because we are reordered out of line, we have to protect this. */  entry.start_label = start_protect_label_rtx;  entry.end_label = end_protect_label_rtx;  LABEL_PRESERVE_P (entry.start_label) = 1;  LABEL_PRESERVE_P (entry.end_label) = 1;  LABEL_PRESERVE_P (entry.exception_handler_label) = 1;  /* These set up a call to throw the caught exception into the outer     context.  */  enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));}/* unwind the stack. */static voiddo_unwind (inner_throw_label)     rtx inner_throw_label;{#if defined(SPARC_STACK_ALIGN) /* was sparc */  tree fcall;  tree params;  rtx return_val_rtx;  rtx temp;  /* call to  __builtin_return_address () */  params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);  fcall = build_function_call (BuiltinReturnAddress, params);  return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);  /* In the return, the new pc is pc+8, as the value coming in is     really the address of the call insn, not the next insn.  */  temp = gen_reg_rtx (Pmode);  emit_move_insn (temp, inner_throw_label);  emit_move_insn (return_val_rtx, plus_constant (temp, -8));  easy_expand_asm ("ret");  easy_expand_asm ("restore");  emit_barrier ();#endif#if defined(ARM_FRAME_RTX)  /* was __arm */  if (flag_omit_frame_pointer)    sorry ("this implementation of exception handling requires a frame pointer");  emit_move_insn (stack_pointer_rtx,		  gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -8)));  emit_move_insn (hard_frame_pointer_rtx,		  gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -12)));#endif#if defined(TARGET_88000) /* was m88k */  rtx temp_frame = frame_pointer_rtx;  temp_frame = memory_address (Pmode, temp_frame);  temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));  /* hopefully this will successfully pop the frame! */  emit_move_insn (frame_pointer_rtx, temp_frame);  emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);  emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);  emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,						     (HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));#if 0  emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,						   -(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));  emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);  emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,						     (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));#endif#endif#if !defined(TARGET_88000) && !defined(ARM_FRAME_RTX) && !defined(SPARC_STACK_ALIGN)  tree fcall;  tree params;  rtx return_val_rtx;  /* call to  __builtin_return_address () */  params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);  fcall = build_function_call (BuiltinReturnAddress, params);  return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);#if 0  /* I would like to do this here, but doesn't seem to work. */  emit_move_insn (return_val_rtx, inner_throw_label);  /* So, for now, just pass throw label to stack unwinder. */#endif  params = tree_cons (NULL_TREE, make_tree (ptr_type_node,					    inner_throw_label), NULL_TREE);    do_function_call (Unwind, params, NULL_TREE);  assemble_external (TREE_OPERAND (Unwind, 0));  emit_barrier ();#endif}/* is called from expand_exception_blocks () to generate the code in a function   to "throw" if anything in the function needs to perform a throw.   expands "throw" as the following pseudo code:	throw:		eh = find_first_exception_match (saved_pc);	    if (!eh) goto gotta_rethrow_it;		goto eh;	gotta_rethrow_it:		saved_pc = __builtin_return_address (0);		pop_to_previous_level ();		goto throw; */voidexpand_builtin_throw (){  tree fcall;  tree params;  rtx return_val_rtx;  rtx gotta_rethrow_it;  rtx gotta_call_terminate;  rtx unwind_and_throw;  rtx goto_unwind_and_throw;  rtx top_of_loop;  rtx unwind_first;  tree t;  if (! doing_eh (0))    return;  if (! throw_used)    return;  params = void_list_node;  t = build_parse_node (CALL_EXPR, get_identifier ("__throw"), params, NULL_TREE);  start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),				  void_list_node),		  t, NULL_TREE, NULL_TREE, 0);  store_parm_decls ();  pushlevel (0);  clear_last_expr ();  push_momentary ();  expand_start_bindings (0);  gotta_rethrow_it = gen_label_rtx ();  gotta_call_terminate = gen_label_rtx ();  unwind_and_throw = gen_label_rtx ();  goto_unwind_and_throw = gen_label_rtx ();  top_of_loop = gen_label_rtx ();  unwind_first = gen_label_rtx ();  emit_jump (unwind_first);  emit_label (top_of_loop);  /* search for an exception handler for the saved_pc */  return_val_rtx = do_function_call (FirstExceptionMatch,				     tree_cons (NULL_TREE, saved_pc, NULL_TREE),				     ptr_type_node);  assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));  /* did we find one? */  emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,		 GET_MODE (return_val_rtx), 0, 0);  /* if not, jump to gotta_rethrow_it */  emit_jump_insn (gen_beq (gotta_rethrow_it));  /* we found it, so jump to it */  emit_indirect_jump (return_val_rtx);  /* code to deal with unwinding and looking for it again */  emit_label (gotta_rethrow_it);  /* call to  __builtin_return_address () */#if defined(ARM_FRAME_RTX)  /* was __arm *//* This replaces a 'call' to __builtin_return_address */  return_val_rtx = gen_reg_rtx (Pmode);  emit_move_insn (return_val_rtx, gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -4)));#else  params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);  fcall = build_function_call (BuiltinReturnAddress, params);  return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);#endif  /* did __builtin_return_address () return a valid address? */  emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,		 GET_MODE (return_val_rtx), 0, 0);  emit_jump_insn (gen_beq (gotta_call_terminate));#if defined(ARM_FRAME_RTX)  /* was __arm */  /* On the ARM, '__builtin_return_address',  must have 4     subtracted from it. */  emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-4)));  /* If we are generating code for an ARM2/ARM3 machine or for an ARM6 in 26 bit     mode, the condition codes must be masked out of the return value, or else     they will confuse BuiltinReturnAddress.  This does not apply to ARM6 and     later processors when running in 32 bit mode. */  if (!TARGET_6)    emit_insn (gen_rtx (SET, Pmode, return_val_rtx, gen_rtx (AND, Pmode, return_val_rtx, GEN_INT (0x03fffffc))));#else#if !defined(SPARC_STACK_ALIGN) /* was sparc */  /* On the SPARC, __builtin_return_address is already -8, no need to     subtract any more from it. */  return_val_rtx = plus_constant (return_val_rtx, -1);#endif#endif  /* yes it did */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -