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

📄 final.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* The final scan for one insn, INSN.   Args are same as in `final', except that INSN   is the insn being scanned.   Value returned is the next insn to be scanned.   NOPEEPHOLES is the flag to disallow peephole processing (currently   used for within delayed branch sequence output).  */rtxfinal_scan_insn (insn, file, optimize, prescan, nopeepholes)     rtx insn;     FILE *file;     int optimize;     int prescan;     int nopeepholes;{  register int i;  insn_counter++;  /* Ignore deleted insns.  These can occur when we split insns (due to a     template of "#") while not optimizing.  */  if (INSN_DELETED_P (insn))    return NEXT_INSN (insn);  switch (GET_CODE (insn))    {    case NOTE:      if (prescan > 0)	break;      /* Align the beginning of a loop, for higher speed	 on certain machines.  */      if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG && optimize > 0)	{#ifdef ASM_OUTPUT_LOOP_ALIGN	  rtx next = next_nonnote_insn (insn);	  if (next && GET_CODE (next) == CODE_LABEL)	    {	      ASM_OUTPUT_LOOP_ALIGN (asm_out_file);	    }#endif	  break;	}      if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)	break;      if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)	{#ifdef FUNCTION_END_PROLOGUE	  FUNCTION_END_PROLOGUE (file);#endif	  profile_after_prologue (file);	  break;	}#ifdef FUNCTION_BEGIN_EPILOGUE      if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)	{	  FUNCTION_BEGIN_EPILOGUE (file);	  break;	}#endif      if (write_symbols == NO_DEBUG)	break;      if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)	{#ifdef SDB_DEBUGGING_INFO	  if (write_symbols == SDB_DEBUG)	    sdbout_begin_function (last_linenum);#endif#ifdef XCOFF_DEBUGGING_INFO	  if (write_symbols == XCOFF_DEBUG)	    xcoffout_begin_function (file, last_linenum);#endif#ifdef DWARF_DEBUGGING_INFO	  if (write_symbols == DWARF_DEBUG)	    dwarfout_begin_function ();#endif	  break;	}      if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)	break;			/* An insn that was "deleted" */      if (app_on)	{	  fprintf (file, ASM_APP_OFF);	  app_on = 0;	}      if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG	  && (debug_info_level == DINFO_LEVEL_NORMAL	      || debug_info_level == DINFO_LEVEL_VERBOSE#ifdef DWARF_DEBUGGING_INFO	      || write_symbols == DWARF_DEBUG#endif	     )	 )	{	  /* Beginning of a symbol-block.  Assign it a sequence number	     and push the number onto the stack PENDING_BLOCKS.  */	  if (block_depth == max_block_depth)	    {	      /* PENDING_BLOCKS is full; make it longer.  */	      max_block_depth *= 2;	      pending_blocks		= (int *) xrealloc (pending_blocks,				    max_block_depth * sizeof (int));	    }	  pending_blocks[block_depth++] = next_block_index;	  /* Output debugging info about the symbol-block beginning.  */#ifdef SDB_DEBUGGING_INFO	  if (write_symbols == SDB_DEBUG)	    sdbout_begin_block (file, last_linenum, next_block_index);#endif#ifdef XCOFF_DEBUGGING_INFO	  if (write_symbols == XCOFF_DEBUG)	    xcoffout_begin_block (file, last_linenum, next_block_index);#endif#ifdef DBX_DEBUGGING_INFO	  if (write_symbols == DBX_DEBUG)	    ASM_OUTPUT_INTERNAL_LABEL (file, "LBB", next_block_index);#endif#ifdef DWARF_DEBUGGING_INFO	  if (write_symbols == DWARF_DEBUG && block_depth > 1)	    dwarfout_begin_block (next_block_index);#endif	  next_block_index++;	}      else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END	       && (debug_info_level == DINFO_LEVEL_NORMAL		   || debug_info_level == DINFO_LEVEL_VERBOSE#ifdef DWARF_DEBUGGING_INFO	           || write_symbols == DWARF_DEBUG#endif	          )	      )	{	  /* End of a symbol-block.  Pop its sequence number off	     PENDING_BLOCKS and output debugging info based on that.  */	  --block_depth;#ifdef XCOFF_DEBUGGING_INFO	  if (write_symbols == XCOFF_DEBUG && block_depth >= 0)	    xcoffout_end_block (file, last_linenum, pending_blocks[block_depth]);#endif#ifdef DBX_DEBUGGING_INFO	  if (write_symbols == DBX_DEBUG && block_depth >= 0)	    ASM_OUTPUT_INTERNAL_LABEL (file, "LBE",				       pending_blocks[block_depth]);#endif#ifdef SDB_DEBUGGING_INFO	  if (write_symbols == SDB_DEBUG && block_depth >= 0)	    sdbout_end_block (file, last_linenum);#endif#ifdef DWARF_DEBUGGING_INFO	  if (write_symbols == DWARF_DEBUG && block_depth >= 1)	    dwarfout_end_block (pending_blocks[block_depth]);#endif	}      else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL	       && (debug_info_level == DINFO_LEVEL_NORMAL		   || debug_info_level == DINFO_LEVEL_VERBOSE))	{#ifdef DWARF_DEBUGGING_INFO          if (write_symbols == DWARF_DEBUG)            dwarfout_label (insn);#endif	}      else if (NOTE_LINE_NUMBER (insn) > 0)	/* This note is a line-number.  */	{	  register rtx note;#if 0 /* This is what we used to do.  */	  output_source_line (file, insn);#endif	  int note_after = 0;	  /* If there is anything real after this note,	     output it.  If another line note follows, omit this one.  */	  for (note = NEXT_INSN (insn); note; note = NEXT_INSN (note))	    {	      if (GET_CODE (note) != NOTE && GET_CODE (note) != CODE_LABEL)		break;	      /* These types of notes can be significant		 so make sure the preceding line number stays.  */	      else if (GET_CODE (note) == NOTE		       && (NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_BEG			   || NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_END			   || NOTE_LINE_NUMBER (note) == NOTE_INSN_FUNCTION_BEG))  		break;	      else if (GET_CODE (note) == NOTE && NOTE_LINE_NUMBER (note) > 0)		{		  /* Another line note follows; we can delete this note		     if no intervening line numbers have notes elsewhere.  */		  int num;		  for (num = NOTE_LINE_NUMBER (insn) + 1;		       num < NOTE_LINE_NUMBER (note);		       num++)		    if (line_note_exists[num])		      break;		  if (num >= NOTE_LINE_NUMBER (note))		    note_after = 1;		  break;		}	    }	  /* Output this line note	     if it is the first or the last line note in a row.  */	  if (!note_after)	    output_source_line (file, insn);	}      break;    case BARRIER:#ifdef ASM_OUTPUT_ALIGN_CODE      /* Don't litter the assembler output with needless alignments.  A	 BARRIER will be placed at the end of every function if HAVE_epilogue	 is true.  */	       if (NEXT_INSN (insn))	ASM_OUTPUT_ALIGN_CODE (file);#endif      break;    case CODE_LABEL:      CC_STATUS_INIT;      if (prescan > 0)	break;      new_block = 1;#ifdef SDB_DEBUGGING_INFO      if (write_symbols == SDB_DEBUG && LABEL_NAME (insn))	sdbout_label (insn);#endif#ifdef DWARF_DEBUGGING_INFO      if (write_symbols == DWARF_DEBUG && LABEL_NAME (insn))	dwarfout_label (insn);#endif      if (app_on)	{	  fprintf (file, ASM_APP_OFF);	  app_on = 0;	}      if (NEXT_INSN (insn) != 0	  && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN)	{	  rtx nextbody = PATTERN (NEXT_INSN (insn));	  /* If this label is followed by a jump-table,	     make sure we put the label in the read-only section.  Also	     possibly write the label and jump table together.  */	  if (GET_CODE (nextbody) == ADDR_VEC	      || GET_CODE (nextbody) == ADDR_DIFF_VEC)	    {#ifndef JUMP_TABLES_IN_TEXT_SECTION	      readonly_data_section ();#ifdef READONLY_DATA_SECTION	      ASM_OUTPUT_ALIGN (file,				exact_log2 (BIGGEST_ALIGNMENT					    / BITS_PER_UNIT));#endif /* READONLY_DATA_SECTION */#else /* JUMP_TABLES_IN_TEXT_SECTION */	      text_section ();#endif /* JUMP_TABLES_IN_TEXT_SECTION */#ifdef ASM_OUTPUT_CASE_LABEL	      ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),				     NEXT_INSN (insn));#else	      ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));#endif	      break;	    }	}      ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));      break;    default:      {	register rtx body = PATTERN (insn);	int insn_code_number;	char *template;	rtx note;	/* An INSN, JUMP_INSN or CALL_INSN.	   First check for special kinds that recog doesn't recognize.  */	if (GET_CODE (body) == USE /* These are just declarations */	    || GET_CODE (body) == CLOBBER)	  break;#ifdef HAVE_cc0	/* If there is a REG_CC_SETTER note on this insn, it means that	   the setting of the condition code was done in the delay slot	   of the insn that branched here.  So recover the cc status	   from the insn that set it.  */	note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);	if (note)	  {	    NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0));	    cc_prev_status = cc_status;	  }#endif	/* Detect insns that are really jump-tables	   and output them as such.  */	if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)	  {	    register int vlen, idx;	    if (prescan > 0)	      break;	    if (app_on)	      {		fprintf (file, ASM_APP_OFF);		app_on = 0;	      }	    vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC);	    for (idx = 0; idx < vlen; idx++)	      {		if (GET_CODE (body) == ADDR_VEC)		  {#ifdef ASM_OUTPUT_ADDR_VEC_ELT		    ASM_OUTPUT_ADDR_VEC_ELT		      (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));#else		    abort ();#endif		  }		else		  {#ifdef ASM_OUTPUT_ADDR_DIFF_ELT		    ASM_OUTPUT_ADDR_DIFF_ELT		      (file,		       CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),		       CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0)));#else		    abort ();#endif		  }	      }#ifdef ASM_OUTPUT_CASE_END	    ASM_OUTPUT_CASE_END (file,				 CODE_LABEL_NUMBER (PREV_INSN (insn)),				 insn);#endif	    text_section ();	    break;	  }	/* Do basic-block profiling when we reach a new block.	   Done here to avoid jump tables.  */	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++;	  }	if (GET_CODE (body) == ASM_INPUT)	  {	    /* There's no telling what that did to the condition codes.  */	    CC_STATUS_INIT;	    if (prescan > 0)	      break;	    if (! app_on)	      {		fprintf (file, ASM_APP_ON);		app_on = 1;	      }	    fprintf (asm_out_file, "\t%s\n", XSTR (body, 0));	    break;	  }	/* Detect `asm' construct with operands.  */	if (asm_noperands (body) >= 0)	  {	    int noperands = asm_noperands (body);	    rtx *ops;	    char *string;	    /* There's no telling what that did to the condition codes.  */	    CC_STATUS_INIT;	    if (prescan > 0)	      break;	    /* alloca won't do here, since only return from `final'	       would free it.  */	    if (noperands > 0)	      ops = (rtx *) xmalloc (noperands * sizeof (rtx));	    if (! app_on)	      {		fprintf (file, ASM_APP_ON);		app_on = 1;	      }	    /* Get out the operand values.  */	    string = decode_asm_operands (body, ops, NULL_PTR,					  NULL_PTR, NULL_PTR);	    /* Inhibit aborts on what would otherwise be compiler bugs.  */	    insn_noperands = noperands;	    this_is_asm_operands = insn;	    /* Output the insn using them.  */	    output_asm_insn (string, ops);	    this_is_asm_operands = 0;	    if (noperands > 0)	      free (ops);	    break;	  }	if (prescan <= 0 && app_on)	  {	    fprintf (file, ASM_APP_OFF);	    app_on = 0;	  }	if (GET_CODE (body) == SEQUENCE)	  {	    /* A delayed-branch sequence */	    register int i;	    rtx next;	    if (prescan > 0)	      break;	    final_sequence = body;	    /* The first insn in this SEQUENCE might be a JUMP_INSN that will	       force the restoration of a comparison that was previously	       thought unnecessary.  If that happens, cancel this sequence	       and cause that insn to be restored.  */	    next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, prescan, 1);	    if (next != XVECEXP (body, 0, 1))	      {		final_sequence = 0;		return next;	      }	    for (i = 1; i < XVECLEN (body, 0); i++)	      final_scan_insn (XVECEXP (body, 0, i), file, 0, prescan, 1);#ifdef DBR_OUTPUT_SEQEND	    DBR_OUTPUT_SEQEND (file);#endif	    final_sequence = 0;	    /* If the insn requiring the delay slot was a CALL_INSN, the	       insns in the delay slot are actually executed before the	       called function.  Hence we don't preserve any CC-setting	       actions in these insns and the CC must be marked as being	       clobbered by the function.  */	    if (GET_CODE (XVECEXP (body, 0, 0)) == CALL_INSN)	      CC_STATUS_INIT;	    /* Following a conditional branch sequence, we have a new basic	       block.  */	    if (profile_block_flag)	      {		rtx insn = XVECEXP (body, 0, 0);		rtx body = PATTERN (insn);		if ((GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET		     && GET_CODE (SET_SRC (body)) != LABEL_REF)		    || (GET_CODE (insn) == JUMP_INSN

⌨️ 快捷键说明

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