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

📄 final.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
	  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 5);	  for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++)	    assemble_integer (GEN_INT (ptr->line_num), UNITS_PER_WORD, 1);	  for ( ; i < count_basic_blocks; i++)	    assemble_integer (const0_rtx, UNITS_PER_WORD, 1);	  /* Output the table of file names.  */	  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 6);	  for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++)	    {	      if (ptr->file_label_num >= 0)		{		  ASM_GENERATE_INTERNAL_LABEL (name, "LPBC", ptr->file_label_num);		  assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name),				    UNITS_PER_WORD, 1);		}	      else		assemble_integer (const0_rtx, UNITS_PER_WORD, 1);	    }	  for ( ; i < count_basic_blocks; i++)	    assemble_integer (const0_rtx, UNITS_PER_WORD, 1);	}      /* End with the address of the table of addresses,	 so we can find it easily, as the last word in the file's text.  */      ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3);      assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);    }}/* Enable APP processing of subsequent output.   Used before the output from an `asm' statement.  */voidapp_enable (){  if (! app_on)    {      fprintf (asm_out_file, ASM_APP_ON);      app_on = 1;    }}/* Disable APP processing of subsequent output.   Called from varasm.c before most kinds of output.  */voidapp_disable (){  if (app_on)    {      fprintf (asm_out_file, ASM_APP_OFF);      app_on = 0;    }}/* Return the number of slots filled in the current    delayed branch sequence (we don't count the insn needing the   delay slot).   Zero if not in a delayed branch sequence.  */#ifdef DELAY_SLOTSintdbr_sequence_length (){  if (final_sequence != 0)    return XVECLEN (final_sequence, 0) - 1;  else    return 0;}#endif/* The next two pages contain routines used to compute the length of an insn   and to shorten branches.  *//* Arrays for insn lengths, and addresses.  The latter is referenced by   `insn_current_length'.  */static short *insn_lengths;int *insn_addresses;/* Address of insn being processed.  Used by `insn_current_length'.  */int insn_current_address;/* Indicate that branch shortening hasn't yet been done.  */voidinit_insn_lengths (){  insn_lengths = 0;}/* Obtain the current length of an insn.  If branch shortening has been done,   get its actual length.  Otherwise, get its maximum length.  */intget_attr_length (insn)     rtx insn;{#ifdef HAVE_ATTR_length  rtx body;  int i;  int length = 0;  if (insn_lengths)    return insn_lengths[INSN_UID (insn)];  else    switch (GET_CODE (insn))      {      case NOTE:      case BARRIER:      case CODE_LABEL:	return 0;      case CALL_INSN:	length = insn_default_length (insn);	break;      case JUMP_INSN:	body = PATTERN (insn);        if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)	  {	    /* This only takes room if jump tables go into the text section.  */#if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION)	    length = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC)		      * GET_MODE_SIZE (GET_MODE (body)));	    /* Be pessimistic and assume worst-case alignment.  */	    length += (GET_MODE_SIZE (GET_MODE (body)) - 1);#else	    return 0;#endif	  }	else	  length = insn_default_length (insn);	break;      case INSN:	body = PATTERN (insn);	if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER)	  return 0;	else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)	  length = asm_insn_count (body) * insn_default_length (insn);	else if (GET_CODE (body) == SEQUENCE)	  for (i = 0; i < XVECLEN (body, 0); i++)	    length += get_attr_length (XVECEXP (body, 0, i));	else	  length = insn_default_length (insn);      }#ifdef ADJUST_INSN_LENGTH  ADJUST_INSN_LENGTH (insn, length);#endif  return length;#else /* not HAVE_ATTR_length */  return 0;#endif /* not HAVE_ATTR_length */}/* Make a pass over all insns and compute their actual lengths by shortening   any branches of variable length if possible.  *//* Give a default value for the lowest address in a function.  */#ifndef FIRST_INSN_ADDRESS#define FIRST_INSN_ADDRESS 0#endifvoidshorten_branches (first)     rtx first;{#ifdef HAVE_ATTR_length  rtx insn;  int something_changed = 1;  int max_uid = 0;  char *varying_length;  rtx body;  int uid;  /* Compute maximum UID and allocate arrays.  */  for (insn = first; insn; insn = NEXT_INSN (insn))    if (INSN_UID (insn) > max_uid)      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;	  int tmp_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;		  /* insn_current_length returns 0 for insns with a		     non-varying length.  */		  if (! varying_length[inner_uid])		    inner_length = insn_lengths[inner_uid];		  else		    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;	    }#ifdef SHORTEN_WITH_ADJUST_INSN_LENGTH#ifdef ADJUST_INSN_LENGTH	  /* If needed, do any adjustment.  */	  tmp_length = new_length;	  ADJUST_INSN_LENGTH (insn, new_length);	  insn_current_address += (new_length - tmp_length);#endif#endif	  if (new_length != insn_lengths[uid])	    {	      insn_lengths[uid] = new_length;	      something_changed = 1;	    }	}      /* For a non-optimizing compile, do only a single pass.  */      if (!optimize)	break;    }#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;  if (GET_CODE (body) == ASM_INPUT)    template = XSTR (body, 0);  else    template = decode_asm_operands (body, NULL_PTR, NULL_PTR,				    NULL_PTR, NULL_PTR);  for ( ; *template; template++)    if (IS_ASM_LOGICAL_LINE_SEPARATOR(*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)    last_linenum = high_block_linenum = high_function_linenum      = NOTE_LINE_NUMBER (first);  /* For SDB and XCOFF, the function beginning must be marked between     the function label and the prologue.  We always need this, even when     -g1 was used.  Defer on MIPS systems so that parameter descriptions     follow function entry. */#if defined(SDB_DEBUGGING_INFO) && !defined(MIPS_DEBUGGING_INFO)  if (write_symbols == SDB_DEBUG)    sdbout_begin_function (last_linenum);  else#endif#ifdef XCOFF_DEBUGGING_INFO    if (write_symbols == XCOFF_DEBUG)      xcoffout_begin_function (file, last_linenum);    else#endif	        /* But only output line number for other debug info types if -g2	 or better.  */      if (NOTE_LINE_NUMBER (first) != NOTE_INSN_DELETED)	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);

⌨️ 快捷键说明

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