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

📄 final.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
      max_uid = INSN_UID (insn);  max_uid++;  insn_lengths = (short *) oballoc (max_uid * sizeof (short));  insn_addresses = (int *) oballoc (max_uid * sizeof (int));  varying_length = (char *) oballoc (max_uid * sizeof (char));  /* Compute initial lengths, addresses, and varying flags for each insn.  */  for (insn_current_address = FIRST_INSN_ADDRESS, insn = first;       insn != 0;       insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn))    {      uid = INSN_UID (insn);      insn_addresses[uid] = insn_current_address;      insn_lengths[uid] = 0;      varying_length[uid] = 0;            if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER	  || GET_CODE (insn) == CODE_LABEL)	continue;      body = PATTERN (insn);      if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)	{	  /* This only takes room if read-only data goes into the text	     section.  */#if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION)	  int unitsize = GET_MODE_SIZE (GET_MODE (body));	  insn_lengths[uid] = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC)			       * GET_MODE_SIZE (GET_MODE (body)));	  /* Account for possible alignment.  */	  insn_lengths[uid]	    += unitsize - (insn_current_address & (unitsize - 1));#else	  ;#endif	}      else if (asm_noperands (body) >= 0)	insn_lengths[uid] = asm_insn_count (body) * insn_default_length (insn);      else if (GET_CODE (body) == SEQUENCE)	{	  int i;	  int const_delay_slots;#ifdef DELAY_SLOTS	  const_delay_slots = const_num_delay_slots (XVECEXP (body, 0, 0));#else	  const_delay_slots = 0;#endif	  /* Inside a delay slot sequence, we do not do any branch shortening	     if the shortening could change the number of delay slots	     of the branch. */	  for (i = 0; i < XVECLEN (body, 0); i++)	    {	      rtx inner_insn = XVECEXP (body, 0, i);	      int inner_uid = INSN_UID (inner_insn);	      int inner_length;	      if (asm_noperands (PATTERN (XVECEXP (body, 0, i))) >= 0)		inner_length = (asm_insn_count (PATTERN (inner_insn))				* insn_default_length (inner_insn));	      else		inner_length = insn_default_length (inner_insn);	      	      insn_lengths[inner_uid] = inner_length;	      if (const_delay_slots)		{		  if ((varying_length[inner_uid]		       = insn_variable_length_p (inner_insn)) != 0)		    varying_length[uid] = 1;		  insn_addresses[inner_uid] = (insn_current_address +					       insn_lengths[uid]);		}	      else		varying_length[inner_uid] = 0;	      insn_lengths[uid] += inner_length;	    }	}      else if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER)	{	  insn_lengths[uid] = insn_default_length (insn);	  varying_length[uid] = insn_variable_length_p (insn);	}      /* If needed, do any adjustment.  */#ifdef ADJUST_INSN_LENGTH      ADJUST_INSN_LENGTH (insn, insn_lengths[uid]);#endif    }  /* Now loop over all the insns finding varying length insns.  For each,     get the current insn length.  If it has changed, reflect the change.     When nothing changes for a full pass, we are done.  */  while (something_changed)    {      something_changed = 0;      for (insn_current_address = FIRST_INSN_ADDRESS, insn = first;	   insn != 0;	   insn = NEXT_INSN (insn))	{	  int new_length;	  uid = INSN_UID (insn);	  insn_addresses[uid] = insn_current_address;	  if (! varying_length[uid])	    {	      insn_current_address += insn_lengths[uid];	      continue;	    }	  if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)	    {	      int i;	      	      body = PATTERN (insn);	      new_length = 0;	      for (i = 0; i < XVECLEN (body, 0); i++)		{		  rtx inner_insn = XVECEXP (body, 0, i);		  int inner_uid = INSN_UID (inner_insn);		  int inner_length;		  insn_addresses[inner_uid] = insn_current_address;		  inner_length = insn_current_length (inner_insn);		  if (inner_length != insn_lengths[inner_uid])		    {		      insn_lengths[inner_uid] = inner_length;		      something_changed = 1;		    }		  insn_current_address += insn_lengths[inner_uid];		  new_length += inner_length;		}	    }	  else	    {	      new_length = insn_current_length (insn);	      insn_current_address += new_length;	    }	  if (new_length != insn_lengths[uid])	    {	      insn_lengths[uid] = new_length;	      something_changed = 1;	    }	}    }#endif /* HAVE_ATTR_length */}#ifdef HAVE_ATTR_length/* Given the body of an INSN known to be generated by an ASM statement, return   the number of machine instructions likely to be generated for this insn.   This is used to compute its length.  */static intasm_insn_count (body)     rtx body;{  char *template;  int count = 1;  for (template = decode_asm_operands (body, NULL_PTR, NULL_PTR,				       NULL_PTR, NULL_PTR);       *template; template++)    if (*template == ';' || *template == '\n')      count++;  return count;}#endif/* Output assembler code for the start of a function,   and initialize some of the variables in this file   for the new function.  The label for the function and associated   assembler pseudo-ops have already been output in `assemble_start_function'.   FIRST is the first insn of the rtl for the function being compiled.   FILE is the file to write assembler code to.   OPTIMIZE is nonzero if we should eliminate redundant     test and compare insns.  */voidfinal_start_function (first, file, optimize)     rtx first;     FILE *file;     int optimize;{  block_depth = 0;  this_is_asm_operands = 0;#ifdef NON_SAVING_SETJMP  /* A function that calls setjmp should save and restore all the     call-saved registers on a system where longjmp clobbers them.  */  if (NON_SAVING_SETJMP && current_function_calls_setjmp)    {      int i;      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)	if (!call_used_regs[i] && !call_fixed_regs[i])	  regs_ever_live[i] = 1;    }#endif    /* Initial line number is supposed to be output     before the function's prologue and label     so that the function's address will not appear to be     in the last statement of the preceding function.  */  if (NOTE_LINE_NUMBER (first) != NOTE_INSN_DELETED)    {      if (write_symbols == SDB_DEBUG)	/* For sdb, let's not, but say we did.	   We need to set last_linenum for sdbout_function_begin,	   but we can't have an actual line number before the .bf symbol.	   (sdb_begin_function_line is not set,	   and other compilers don't do it.)  */	last_linenum = NOTE_LINE_NUMBER (first);#ifdef XCOFF_DEBUGGING_INFO      else if (write_symbols == XCOFF_DEBUG)	{	  last_linenum = NOTE_LINE_NUMBER (first);	  xcoffout_output_first_source_line (file, last_linenum);	}#endif	        else	output_source_line (file, first);    }#ifdef LEAF_REG_REMAP  if (leaf_function)    leaf_renumber_regs (first);#endif  /* The Sun386i and perhaps other machines don't work right     if the profiling code comes after the prologue.  */#ifdef PROFILE_BEFORE_PROLOGUE  if (profile_flag)    profile_function (file);#endif /* PROFILE_BEFORE_PROLOGUE */#ifdef FUNCTION_PROLOGUE  /* First output the function prologue: code to set up the stack frame.  */  FUNCTION_PROLOGUE (file, get_frame_size ());#endif#if defined (SDB_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)  if (write_symbols == SDB_DEBUG || write_symbols == XCOFF_DEBUG)    next_block_index = 1;#endif  /* If the machine represents the prologue as RTL, the profiling code must     be emitted when NOTE_INSN_PROLOGUE_END is scanned.  */#ifdef HAVE_prologue  if (! HAVE_prologue)#endif    profile_after_prologue (file);  profile_label_no++;}static voidprofile_after_prologue (file)     FILE *file;{#ifdef FUNCTION_BLOCK_PROFILER  if (profile_block_flag)    {      FUNCTION_BLOCK_PROFILER (file, profile_label_no);    }#endif /* FUNCTION_BLOCK_PROFILER */#ifndef PROFILE_BEFORE_PROLOGUE  if (profile_flag)    profile_function (file);#endif /* not PROFILE_BEFORE_PROLOGUE */}voidprofile_function (file)     FILE *file;{  int align = MIN (BIGGEST_ALIGNMENT, INT_TYPE_SIZE);  int sval = current_function_returns_struct;  int cxt = current_function_needs_context;  data_section ();  ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));  ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no);  assemble_integer (const0_rtx, UNITS_PER_WORD, 1);  text_section ();#ifdef STRUCT_VALUE_INCOMING_REGNUM  if (sval)    ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_INCOMING_REGNUM);#else#ifdef STRUCT_VALUE_REGNUM  if (sval)    ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_REGNUM);#endif#endif#if 0#ifdef STATIC_CHAIN_INCOMING_REGNUM  if (cxt)    ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM);#else#ifdef STATIC_CHAIN_REGNUM  if (cxt)    ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM);#endif#endif#endif				/* 0 */  FUNCTION_PROFILER (file, profile_label_no);#if 0#ifdef STATIC_CHAIN_INCOMING_REGNUM  if (cxt)    ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM);#else#ifdef STATIC_CHAIN_REGNUM  if (cxt)    ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM);#endif#endif#endif				/* 0 */#ifdef STRUCT_VALUE_INCOMING_REGNUM  if (sval)    ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_INCOMING_REGNUM);#else#ifdef STRUCT_VALUE_REGNUM  if (sval)    ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_REGNUM);#endif#endif}/* Output assembler code for the end of a function.   For clarity, args are same as those of `final_start_function'   even though not all of them are needed.  */voidfinal_end_function (first, file, optimize)     rtx first;     FILE *file;     int optimize;{  if (app_on)    {      fprintf (file, ASM_APP_OFF);      app_on = 0;    }#ifdef SDB_DEBUGGING_INFO  if (write_symbols == SDB_DEBUG)    sdbout_end_function (last_linenum);#endif#ifdef DWARF_DEBUGGING_INFO  if (write_symbols == DWARF_DEBUG)    dwarfout_end_function ();#endif#ifdef XCOFF_DEBUGGING_INFO  if (write_symbols == XCOFF_DEBUG)    xcoffout_end_function (file, last_linenum);#endif#ifdef FUNCTION_EPILOGUE  /* Finally, output the function epilogue:     code to restore the stack frame and return to the caller.  */  FUNCTION_EPILOGUE (file, get_frame_size ());#endif#ifdef SDB_DEBUGGING_INFO  if (write_symbols == SDB_DEBUG)    sdbout_end_epilogue ();#endif#ifdef DWARF_DEBUGGING_INFO  if (write_symbols == DWARF_DEBUG)    dwarfout_end_epilogue ();#endif#ifdef XCOFF_DEBUGGING_INFO  if (write_symbols == XCOFF_DEBUG)    xcoffout_end_epilogue (file);#endif  /* If FUNCTION_EPILOGUE is not defined, then the function body     itself contains return instructions wherever needed.  */}/* Output assembler code for some insns: all or part of a function.   For description of args, see `final_start_function', above.   PRESCAN is 1 if we are not really outputting,     just scanning as if we were outputting.   Prescanning deletes and rearranges insns just like ordinary output.   PRESCAN is -2 if we are outputting after having prescanned.   In this case, don't try to delete or rearrange insns   because that has already been done.   Prescanning is done only on certain machines.  */voidfinal (first, file, optimize, prescan)     rtx first;     FILE *file;     int optimize;     int prescan;{  register rtx insn;  int max_line = 0;  last_ignored_compare = 0;  new_block = 1;  /* Make a map indicating which line numbers appear in this function.     When producing SDB debugging info, delete troublesome line number     notes from inlined functions in other files as well as duplicate     line number notes.  */#ifdef SDB_DEBUGGING_INFO  if (write_symbols == SDB_DEBUG)    {      rtx last = 0;      for (insn = first; insn; insn = NEXT_INSN (insn))	if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)	  {	    if ((RTX_INTEGRATED_P (insn)		 && strcmp (NOTE_SOURCE_FILE (insn), main_input_filename) != 0)		 || (last != 0		     && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last)		     && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last)))	      {		NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;		NOTE_SOURCE_FILE (insn) = 0;		continue;	      }	    last = insn;	    if (NOTE_LINE_NUMBER (insn) > max_line)	      max_line = NOTE_LINE_NUMBER (insn);	  }    }  else#endif    {      for (insn = first; insn; insn = NEXT_INSN (insn))	if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > max_line)	  max_line = NOTE_LINE_NUMBER (insn);    }  line_note_exists = (char *) oballoc (max_line + 1);  bzero (line_note_exists, max_line + 1);  for (insn = first; insn; insn = NEXT_INSN (insn))    if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)      line_note_exists[NOTE_LINE_NUMBER (insn)] = 1;  init_recog ();  CC_STATUS_INIT;  /* Output the insns.  */  for (insn = NEXT_INSN (first); insn;)    insn = final_scan_insn (insn, file, optimize, prescan, 0);  /* Do basic-block profiling here     if the last insn was a conditional branch.  */  if (profile_block_flag && new_block)    {      new_block = 0;      /* Enable the table of basic-block use counts	 to point at the code it applies to.  */      ASM_OUTPUT_INTERNAL_LABEL (file, "LPB", count_basic_blocks);      /* Before first insn of this basic block, increment the	 count of times it was entered.  */#ifdef BLOCK_PROFILER      BLOCK_PROFILER (file, count_basic_blocks);      CC_STATUS_INIT;#endif      count_basic_blocks++;    }}

⌨️ 快捷键说明

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