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

📄 function.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
   maintain this list in case two operands of an insn were required to match;   in that case we must ensure we use the same replacement.  */struct fixup_replacement{  rtx old;  rtx new;  struct fixup_replacement *next;};   /* Forward declarations.  */static struct temp_slot *find_temp_slot_from_address  PROTO((rtx));static void put_reg_into_stack	PROTO((struct function *, rtx, tree,				       enum machine_mode, enum machine_mode,				       int, int));static void fixup_var_refs	PROTO((rtx, enum machine_mode, int));static struct fixup_replacement  *find_fixup_replacement	PROTO((struct fixup_replacement **, rtx));static void fixup_var_refs_insns PROTO((rtx, enum machine_mode, int,					rtx, int));static void fixup_var_refs_1	PROTO((rtx, enum machine_mode, rtx *, rtx,				       struct fixup_replacement **));static rtx fixup_memory_subreg	PROTO((rtx, rtx, int));static rtx walk_fixup_memory_subreg  PROTO((rtx, rtx, int));static rtx fixup_stack_1	PROTO((rtx, rtx));static void optimize_bit_field	PROTO((rtx, rtx, rtx *));static void instantiate_decls	PROTO((tree, int));static void instantiate_decls_1	PROTO((tree, int));static void instantiate_decl	PROTO((rtx, int, int));static int instantiate_virtual_regs_1 PROTO((rtx *, rtx, int));static void delete_handlers	PROTO((void));static void pad_to_arg_alignment PROTO((struct args_size *, int));static void pad_below		PROTO((struct args_size *, enum  machine_mode,				       tree));static tree round_down		PROTO((tree, int));static rtx round_trampoline_addr PROTO((rtx));static tree blocks_nreverse	PROTO((tree));static int all_blocks		PROTO((tree, tree *));static int *record_insns	PROTO((rtx));static int contains		PROTO((rtx, int *));static void put_addressof_into_stack PROTO((rtx));static void purge_addressof_1	PROTO((rtx *, rtx, int));/* Pointer to chain of `struct function' for containing functions.  */struct function *outer_function_chain;/* Given a function decl for a containing function,   return the `struct function' for it.  */struct function *find_function_data (decl)     tree decl;{  struct function *p;  for (p = outer_function_chain; p; p = p->next)    if (p->decl == decl)      return p;  abort ();}/* Save the current context for compilation of a nested function.   This is called from language-specific code.   The caller is responsible for saving any language-specific status,   since this function knows only about language-independent variables.  */voidpush_function_context_to (context)     tree context;{  struct function *p = (struct function *) xmalloc (sizeof (struct function));  p->next = outer_function_chain;  outer_function_chain = p;  p->name = current_function_name;  p->decl = current_function_decl;  p->pops_args = current_function_pops_args;  p->returns_struct = current_function_returns_struct;  p->returns_pcc_struct = current_function_returns_pcc_struct;  p->returns_pointer = current_function_returns_pointer;  p->needs_context = current_function_needs_context;  p->calls_setjmp = current_function_calls_setjmp;  p->calls_longjmp = current_function_calls_longjmp;  p->calls_alloca = current_function_calls_alloca;  p->has_nonlocal_label = current_function_has_nonlocal_label;  p->has_nonlocal_goto = current_function_has_nonlocal_goto;  p->contains_functions = current_function_contains_functions;  p->is_thunk = current_function_is_thunk;  p->args_size = current_function_args_size;  p->pretend_args_size = current_function_pretend_args_size;  p->arg_offset_rtx = current_function_arg_offset_rtx;  p->varargs = current_function_varargs;  p->stdarg = current_function_stdarg;  p->uses_const_pool = current_function_uses_const_pool;  p->uses_pic_offset_table = current_function_uses_pic_offset_table;  p->internal_arg_pointer = current_function_internal_arg_pointer;  p->max_parm_reg = max_parm_reg;  p->parm_reg_stack_loc = parm_reg_stack_loc;  p->outgoing_args_size = current_function_outgoing_args_size;  p->return_rtx = current_function_return_rtx;  p->nonlocal_goto_handler_slot = nonlocal_goto_handler_slot;  p->nonlocal_goto_stack_level = nonlocal_goto_stack_level;  p->nonlocal_labels = nonlocal_labels;  p->cleanup_label = cleanup_label;  p->return_label = return_label;  p->save_expr_regs = save_expr_regs;  p->stack_slot_list = stack_slot_list;  p->parm_birth_insn = parm_birth_insn;  p->frame_offset = frame_offset;  p->tail_recursion_label = tail_recursion_label;  p->tail_recursion_reentry = tail_recursion_reentry;  p->arg_pointer_save_area = arg_pointer_save_area;  p->rtl_expr_chain = rtl_expr_chain;  p->last_parm_insn = last_parm_insn;  p->context_display = context_display;  p->trampoline_list = trampoline_list;  p->function_call_count = function_call_count;  p->temp_slots = temp_slots;  p->temp_slot_level = temp_slot_level;  p->fixup_var_refs_queue = 0;  p->epilogue_delay_list = current_function_epilogue_delay_list;  p->args_info = current_function_args_info;  save_tree_status (p, context);  save_storage_status (p);  save_emit_status (p);  init_emit ();  save_expr_status (p);  save_stmt_status (p);  save_varasm_status (p, context);  if (save_machine_status)    (*save_machine_status) (p);}voidpush_function_context (){  push_function_context_to (current_function_decl);}/* Restore the last saved context, at the end of a nested function.   This function is called from language-specific code.  */voidpop_function_context_from (context)     tree context;{  struct function *p = outer_function_chain;  outer_function_chain = p->next;  current_function_contains_functions    = p->contains_functions || p->inline_obstacks      || context == current_function_decl;  current_function_name = p->name;  current_function_decl = p->decl;  current_function_pops_args = p->pops_args;  current_function_returns_struct = p->returns_struct;  current_function_returns_pcc_struct = p->returns_pcc_struct;  current_function_returns_pointer = p->returns_pointer;  current_function_needs_context = p->needs_context;  current_function_calls_setjmp = p->calls_setjmp;  current_function_calls_longjmp = p->calls_longjmp;  current_function_calls_alloca = p->calls_alloca;  current_function_has_nonlocal_label = p->has_nonlocal_label;  current_function_has_nonlocal_goto = p->has_nonlocal_goto;  current_function_is_thunk = p->is_thunk;  current_function_args_size = p->args_size;  current_function_pretend_args_size = p->pretend_args_size;  current_function_arg_offset_rtx = p->arg_offset_rtx;  current_function_varargs = p->varargs;  current_function_stdarg = p->stdarg;  current_function_uses_const_pool = p->uses_const_pool;  current_function_uses_pic_offset_table = p->uses_pic_offset_table;  current_function_internal_arg_pointer = p->internal_arg_pointer;  max_parm_reg = p->max_parm_reg;  parm_reg_stack_loc = p->parm_reg_stack_loc;  current_function_outgoing_args_size = p->outgoing_args_size;  current_function_return_rtx = p->return_rtx;  nonlocal_goto_handler_slot = p->nonlocal_goto_handler_slot;  nonlocal_goto_stack_level = p->nonlocal_goto_stack_level;  nonlocal_labels = p->nonlocal_labels;  cleanup_label = p->cleanup_label;  return_label = p->return_label;  save_expr_regs = p->save_expr_regs;  stack_slot_list = p->stack_slot_list;  parm_birth_insn = p->parm_birth_insn;  frame_offset = p->frame_offset;  tail_recursion_label = p->tail_recursion_label;  tail_recursion_reentry = p->tail_recursion_reentry;  arg_pointer_save_area = p->arg_pointer_save_area;  rtl_expr_chain = p->rtl_expr_chain;  last_parm_insn = p->last_parm_insn;  context_display = p->context_display;  trampoline_list = p->trampoline_list;  function_call_count = p->function_call_count;  temp_slots = p->temp_slots;  temp_slot_level = p->temp_slot_level;  current_function_epilogue_delay_list = p->epilogue_delay_list;  reg_renumber = 0;  current_function_args_info = p->args_info;  restore_tree_status (p, context);  restore_storage_status (p);  restore_expr_status (p);  restore_emit_status (p);  restore_stmt_status (p);  restore_varasm_status (p);  if (restore_machine_status)    (*restore_machine_status) (p);  /* Finish doing put_var_into_stack for any of our variables     which became addressable during the nested function.  */  {    struct var_refs_queue *queue = p->fixup_var_refs_queue;    for (; queue; queue = queue->next)      fixup_var_refs (queue->modified, queue->promoted_mode, queue->unsignedp);  }  free (p);  /* Reset variables that have known state during rtx generation.  */  rtx_equal_function_value_matters = 1;  virtuals_instantiated = 0;}void pop_function_context (){  pop_function_context_from (current_function_decl);}/* Allocate fixed slots in the stack frame of the current function.  *//* Return size needed for stack frame based on slots so far allocated.   This size counts from zero.  It is not rounded to STACK_BOUNDARY;   the caller may have to do that.  */HOST_WIDE_INTget_frame_size (){#ifdef FRAME_GROWS_DOWNWARD  return -frame_offset;#else  return frame_offset;#endif}/* Allocate a stack slot of SIZE bytes and return a MEM rtx for it   with machine mode MODE.      ALIGN controls the amount of alignment for the address of the slot:   0 means according to MODE,   -1 means use BIGGEST_ALIGNMENT and round size to multiple of that,   positive specifies alignment boundary in bits.   We do not round to stack_boundary here.  */rtxassign_stack_local (mode, size, align)     enum machine_mode mode;     int size;     int align;{  register rtx x, addr;  int bigend_correction = 0;  int alignment;  if (align == 0)    {      alignment = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;      if (mode == BLKmode)	alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;    }  else if (align == -1)    {      alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;      size = CEIL_ROUND (size, alignment);    }  else    alignment = align / BITS_PER_UNIT;  /* Round frame offset to that alignment.     We must be careful here, since FRAME_OFFSET might be negative and     division with a negative dividend isn't as well defined as we might     like.  So we instead assume that ALIGNMENT is a power of two and     use logical operations which are unambiguous.  */#ifdef FRAME_GROWS_DOWNWARD  frame_offset = FLOOR_ROUND (frame_offset, alignment);#else  frame_offset = CEIL_ROUND (frame_offset, alignment);#endif  /* On a big-endian machine, if we are allocating more space than we will use,     use the least significant bytes of those that are allocated.  */  if (BYTES_BIG_ENDIAN && mode != BLKmode)    bigend_correction = size - GET_MODE_SIZE (mode);#ifdef FRAME_GROWS_DOWNWARD  frame_offset -= size;#endif  /* If we have already instantiated virtual registers, return the actual     address relative to the frame pointer.  */  if (virtuals_instantiated)    addr = plus_constant (frame_pointer_rtx,			  (frame_offset + bigend_correction			   + STARTING_FRAME_OFFSET));  else    addr = plus_constant (virtual_stack_vars_rtx,			  frame_offset + bigend_correction);#ifndef FRAME_GROWS_DOWNWARD  frame_offset += size;#endif  x = gen_rtx (MEM, mode, addr);  stack_slot_list = gen_rtx (EXPR_LIST, VOIDmode, x, stack_slot_list);  return x;}/* Assign a stack slot in a containing function.   First three arguments are same as in preceding function.   The last argument specifies the function to allocate in.  */rtxassign_outer_stack_local (mode, size, align, function)     enum machine_mode mode;     int size;     int align;     struct function *function;{  register rtx x, addr;  int bigend_correction = 0;  int alignment;  /* Allocate in the memory associated with the function in whose frame     we are assigning.  */  push_obstacks (function->function_obstack,		 function->function_maybepermanent_obstack);  if (align == 0)    {      alignment = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;      if (mode == BLKmode)	alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;    }  else if (align == -1)    {      alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;      size = CEIL_ROUND (size, alignment);    }  else    alignment = align / BITS_PER_UNIT;  /* Round frame offset to that alignment.  */#ifdef FRAME_GROWS_DOWNWARD  function->frame_offset = FLOOR_ROUND (function->frame_offset, alignment);#else  function->frame_offset = CEIL_ROUND (function->frame_offset, alignment);#endif  /* On a big-endian machine, if we are allocating more space than we will use,     use the least significant bytes of those that are allocated.  */  if (BYTES_BIG_ENDIAN && mode != BLKmode)    bigend_correction = size - GET_MODE_SIZE (mode);#ifdef FRAME_GROWS_DOWNWARD  function->frame_offset -= size;#endif  addr = plus_constant (virtual_stack_vars_rtx,			function->frame_offset + bigend_correction);#ifndef FRAME_GROWS_DOWNWARD  function->frame_offset += size;#endif  x = gen_rtx (MEM, mode, addr);  function->stack_slot_list    = gen_rtx (EXPR_LIST, VOIDmode, x, function->stack_slot_list);  pop_obstacks ();  return x;}/* Allocate a temporary stack slot and record it for possible later   reuse.   MODE is the machine mode to be given to the returned rtx.   SIZE is the size in units of the space required.  We do no rounding here   since assign_stack_local will do any required rounding.   KEEP is 1 if this slot is to be retained after a call to   free_temp_slots.  Automatic variables for a block are allocated   with this flag.  KEEP is 2, if we allocate a longer term temporary,   whose lifetime is controlled by CLEANUP_POINT_EXPRs.  */rtxassign_stack_temp (mode, size, keep)     enum machine_mode mode;     int size;     int keep;{  struct temp_slot *p, *best_p = 0;

⌨️ 快捷键说明

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