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

📄 emit-rtl.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* Find out which word on the host machine this value is in and get     it from the constant.  */  val = (i / size_ratio == 0	 ? (GET_CODE (op) == CONST_INT ? INTVAL (op) : CONST_DOUBLE_LOW (op))	 : (GET_CODE (op) == CONST_INT	    ? (INTVAL (op) < 0 ? ~0 : 0) : CONST_DOUBLE_HIGH (op)));  /* If BITS_PER_WORD is smaller than an int, get the appropriate bits.  */  if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT)    val = ((val >> ((i % size_ratio) * BITS_PER_WORD))	   & (((HOST_WIDE_INT) 1	       << (BITS_PER_WORD % HOST_BITS_PER_WIDE_INT)) - 1));  return GEN_INT (val);}/* Similar to `operand_subword', but never return 0.  If we can't extract   the required subword, put OP into a register and try again.  If that fails,   abort.  We always validate the address in this case.  It is not valid   to call this function after reload; it is mostly meant for RTL   generation.    MODE is the mode of OP, in case it is CONST_INT.  */rtxoperand_subword_force (op, i, mode)     rtx op;     int i;     enum machine_mode mode;{  rtx result = operand_subword (op, i, 1, mode);  if (result)    return result;  if (mode != BLKmode && mode != VOIDmode)    op = force_reg (mode, op);  result = operand_subword (op, i, 1, mode);  if (result == 0)    abort ();  return result;}/* Given a compare instruction, swap the operands.   A test instruction is changed into a compare of 0 against the operand.  */voidreverse_comparison (insn)     rtx insn;{  rtx body = PATTERN (insn);  rtx comp;  if (GET_CODE (body) == SET)    comp = SET_SRC (body);  else    comp = SET_SRC (XVECEXP (body, 0, 0));  if (GET_CODE (comp) == COMPARE)    {      rtx op0 = XEXP (comp, 0);      rtx op1 = XEXP (comp, 1);      XEXP (comp, 0) = op1;      XEXP (comp, 1) = op0;    }  else    {      rtx new = gen_rtx (COMPARE, VOIDmode,			 CONST0_RTX (GET_MODE (comp)), comp);      if (GET_CODE (body) == SET)	SET_SRC (body) = new;      else	SET_SRC (XVECEXP (body, 0, 0)) = new;    }}/* Return a memory reference like MEMREF, but with its mode changed   to MODE and its address changed to ADDR.   (VOIDmode means don't change the mode.   NULL for ADDR means don't change the address.)  */rtxchange_address (memref, mode, addr)     rtx memref;     enum machine_mode mode;     rtx addr;{  rtx new;  if (GET_CODE (memref) != MEM)    abort ();  if (mode == VOIDmode)    mode = GET_MODE (memref);  if (addr == 0)    addr = XEXP (memref, 0);  /* If reload is in progress or has completed, ADDR must be valid.     Otherwise, we can call memory_address to make it valid.  */  if (reload_completed || reload_in_progress)    {      if (! memory_address_p (mode, addr))	abort ();    }  else    addr = memory_address (mode, addr);	  new = gen_rtx (MEM, mode, addr);  MEM_VOLATILE_P (new) = MEM_VOLATILE_P (memref);  RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (memref);  MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (memref);  return new;}/* Return a newly created CODE_LABEL rtx with a unique label number.  */rtxgen_label_rtx (){  register rtx label = gen_rtx (CODE_LABEL, VOIDmode, 0, 0, 0,				label_num++, NULL_PTR);  LABEL_NUSES (label) = 0;  return label;}/* For procedure integration.  *//* Return a newly created INLINE_HEADER rtx.  Should allocate this   from a permanent obstack when the opportunity arises.  */rtxgen_inline_header_rtx (first_insn, first_parm_insn, first_labelno,		       last_labelno, max_parm_regnum, max_regnum, args_size,		       pops_args, stack_slots, function_flags,		       outgoing_args_size, original_arg_vector,		       original_decl_initial)     rtx first_insn, first_parm_insn;     int first_labelno, last_labelno, max_parm_regnum, max_regnum, args_size;     int pops_args;     rtx stack_slots;     int function_flags;     int outgoing_args_size;     rtvec original_arg_vector;     rtx original_decl_initial;{  rtx header = gen_rtx (INLINE_HEADER, VOIDmode,			cur_insn_uid++, NULL_RTX,			first_insn, first_parm_insn,			first_labelno, last_labelno,			max_parm_regnum, max_regnum, args_size, pops_args,			stack_slots, function_flags, outgoing_args_size,			original_arg_vector, original_decl_initial);  return header;}/* Install new pointers to the first and last insns in the chain.   Used for an inline-procedure after copying the insn chain.  */voidset_new_first_and_last_insn (first, last)     rtx first, last;{  first_insn = first;  last_insn = last;}/* Set the range of label numbers found in the current function.   This is used when belatedly compiling an inline function.  */voidset_new_first_and_last_label_num (first, last)     int first, last;{  base_label_num = label_num;  first_label_num = first;  last_label_num = last;}/* Save all variables describing the current status into the structure *P.   This is used before starting a nested function.  */voidsave_emit_status (p)     struct function *p;{  p->reg_rtx_no = reg_rtx_no;  p->first_label_num = first_label_num;  p->first_insn = first_insn;  p->last_insn = last_insn;  p->sequence_stack = sequence_stack;  p->cur_insn_uid = cur_insn_uid;  p->last_linenum = last_linenum;  p->last_filename = last_filename;  p->regno_pointer_flag = regno_pointer_flag;  p->regno_pointer_flag_length = regno_pointer_flag_length;  p->regno_reg_rtx = regno_reg_rtx;}/* Restore all variables describing the current status from the structure *P.   This is used after a nested function.  */voidrestore_emit_status (p)     struct function *p;{  int i;  reg_rtx_no = p->reg_rtx_no;  first_label_num = p->first_label_num;  first_insn = p->first_insn;  last_insn = p->last_insn;  sequence_stack = p->sequence_stack;  cur_insn_uid = p->cur_insn_uid;  last_linenum = p->last_linenum;  last_filename = p->last_filename;  regno_pointer_flag = p->regno_pointer_flag;  regno_pointer_flag_length = p->regno_pointer_flag_length;  regno_reg_rtx = p->regno_reg_rtx;  /* Clear our cache of rtx expressions for start_sequence and gen_sequence. */  sequence_element_free_list = 0;  for (i = 0; i < SEQUENCE_RESULT_SIZE; i++)    sequence_result[i] = 0;}/* Go through all the RTL insn bodies and copy any invalid shared structure.   It does not work to do this twice, because the mark bits set here   are not cleared afterwards.  */voidunshare_all_rtl (insn)     register rtx insn;{  for (; insn; insn = NEXT_INSN (insn))    if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN	|| GET_CODE (insn) == CALL_INSN)      {	PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));	REG_NOTES (insn) = copy_rtx_if_shared (REG_NOTES (insn));	LOG_LINKS (insn) = copy_rtx_if_shared (LOG_LINKS (insn));      }  /* Make sure the addresses of stack slots found outside the insn chain     (such as, in DECL_RTL of a variable) are not shared     with the insn chain.     This special care is necessary when the stack slot MEM does not     actually appear in the insn chain.  If it does appear, its address     is unshared from all else at that point.  */  copy_rtx_if_shared (stack_slot_list);}/* Mark ORIG as in use, and return a copy of it if it was already in use.   Recursively does the same for subexpressions.  */rtxcopy_rtx_if_shared (orig)     rtx orig;{  register rtx x = orig;  register int i;  register enum rtx_code code;  register char *format_ptr;  int copied = 0;  if (x == 0)    return 0;  code = GET_CODE (x);  /* These types may be freely shared.  */  switch (code)    {    case REG:    case QUEUED:    case CONST_INT:    case CONST_DOUBLE:    case SYMBOL_REF:    case CODE_LABEL:    case PC:    case CC0:    case SCRATCH:      /* SCRATCH must be shared because they represent distinct values. */      return x;    case INSN:    case JUMP_INSN:    case CALL_INSN:    case NOTE:    case LABEL_REF:    case BARRIER:      /* The chain of insns is not being copied.  */      return x;    case MEM:      /* A MEM is allowed to be shared if its address is constant	 or is a constant plus one of the special registers.  */      if (CONSTANT_ADDRESS_P (XEXP (x, 0))	  || XEXP (x, 0) == virtual_stack_vars_rtx	  || XEXP (x, 0) == virtual_incoming_args_rtx)	return x;      if (GET_CODE (XEXP (x, 0)) == PLUS	  && (XEXP (XEXP (x, 0), 0) == virtual_stack_vars_rtx	      || XEXP (XEXP (x, 0), 0) == virtual_incoming_args_rtx)	  && CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1)))	{	  /* This MEM can appear in more than one place,	     but its address better not be shared with anything else.  */	  if (! x->used)	    XEXP (x, 0) = copy_rtx_if_shared (XEXP (x, 0));	  x->used = 1;	  return x;	}    }  /* This rtx may not be shared.  If it has already been seen,     replace it with a copy of itself.  */  if (x->used)    {      register rtx copy;      copy = rtx_alloc (code);      bcopy (x, copy, (sizeof (*copy) - sizeof (copy->fld)		       + sizeof (copy->fld[0]) * GET_RTX_LENGTH (code)));      x = copy;      copied = 1;    }  x->used = 1;  /* Now scan the subexpressions recursively.     We can store any replaced subexpressions directly into X     since we know X is not shared!  Any vectors in X     must be copied if X was copied.  */  format_ptr = GET_RTX_FORMAT (code);  for (i = 0; i < GET_RTX_LENGTH (code); i++)    {      switch (*format_ptr++)	{	case 'e':	  XEXP (x, i) = copy_rtx_if_shared (XEXP (x, i));	  break;	case 'E':	  if (XVEC (x, i) != NULL)	    {	      register int j;	      if (copied)		XVEC (x, i) = gen_rtvec_v (XVECLEN (x, i), &XVECEXP (x, i, 0));	      for (j = 0; j < XVECLEN (x, i); j++)		XVECEXP (x, i, j)		  = copy_rtx_if_shared (XVECEXP (x, i, j));	    }	  break;	}    }  return x;}/* Clear all the USED bits in X to allow copy_rtx_if_shared to be used   to look for shared sub-parts.  */voidreset_used_flags (x)     rtx x;{  register int i, j;  register enum rtx_code code;  register char *format_ptr;  int copied = 0;  if (x == 0)    return;  code = GET_CODE (x);  /* These types may be freely shared so we needn't do any reseting     for them.  */  switch (code)    {    case REG:    case QUEUED:    case CONST_INT:    case CONST_DOUBLE:    case SYMBOL_REF:    case CODE_LABEL:    case PC:    case CC0:      return;    case INSN:    case JUMP_INSN:    case CALL_INSN:    case NOTE:    case LABEL_REF:    case BARRIER:      /* The chain of insns is not being copied.  */      return;    }  x->used = 0;  format_ptr = GET_RTX_FORMAT (code);  for (i = 0; i < GET_RTX_LENGTH (code); i++)    {      switch (*format_ptr++)	{	case 'e':	  reset_used_flags (XEXP (x, i));	  break;	case 'E':	  for (j = 0; j < XVECLEN (x, i); j++)	    reset_used_flags (XVECEXP (x, i, j));	  break;	}    }}/* Copy X if necessary so that it won't be altered by changes in OTHER.   Return X or the rtx for the pseudo reg the value of X was copied into.   OTHER must be valid as a SET_DEST.  */rtxmake_safe_from (x, other)     rtx x, other;{  while (1)    switch (GET_CODE (other))      {      case SUBREG:	other = SUBREG_REG (other);	break;      case STRICT_LOW_PART:      case SIGN_EXTEND:      case ZERO_EXTEND:	other = XEXP (other, 0);	break;      default:	goto done;      } done:  if ((GET_CODE (other) == MEM       && ! CONSTANT_P (x)       && GET_CODE (x) != REG       && GET_CODE (x) != SUBREG)      || (GET_CODE (other) == REG	  && (REGNO (other) < FIRST_PSEUDO_REGISTER	      || reg_mentioned_p (other, x))))    {      rtx temp = gen_reg_rtx (GET_MODE (x));      emit_move_insn (temp, x);      return temp;    }  return x;}/* Emission of insns (adding them to the doubly-linked list).  *//* Return the first insn of the current sequence or current function.  */rtxget_insns (){  return first_insn;}/* Return the last insn emitted in current sequence or current function.  */rtxget_last_insn (){  return last_insn;}/* Specify a new insn as the last in the chain.  */voidset_last_insn (insn)     rtx insn;{

⌨️ 快捷键说明

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