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

📄 genattrtab.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
	    case SET_ATTR_ALTERNATIVE:	      value = convert_set_attr_alternative (value,						    id->num_alternatives,						    id->insn_code,						    id->insn_index);	      break;	    case SET_ATTR:	      value = convert_set_attr (value, id->num_alternatives,					id->insn_code, id->insn_index);	      break;	    default:	      fatal ("Invalid attribute code `%s' for pattern %d",		     GET_RTX_NAME (GET_CODE (value)), id->insn_index);	    }	  if ((attr = find_attr (XSTR (XEXP (value, 0), 0), 0)) == NULL)	    fatal ("Unknown attribute `%s' for pattern number %d",		   XSTR (XEXP (value, 0), 0), id->insn_index);	  XVECEXP (id->def, id->vec_idx, i) = value;	  XEXP (value, 1) = check_attr_value (XEXP (value, 1), attr);	}    }}/* Given a constant SYMBOL_REF expression, convert to a COND that   explicitly tests each enumerated value.  */static rtxconvert_const_symbol_ref (exp, attr)     rtx exp;     struct attr_desc *attr;{  rtx condexp;  struct attr_value *av;  int i;  int num_alt = 0;  for (av = attr->first_value; av; av = av->next)    num_alt++;  /* Make a COND with all tests but the last, and in the original order.     Select the last value via the default.  Note that the attr values     are constructed in reverse order.  */  condexp = rtx_alloc (COND);  XVEC (condexp, 0) = rtvec_alloc ((num_alt - 1) * 2);  av = attr->first_value;  XEXP (condexp, 1) = av->value;  for (i = num_alt - 2; av = av->next, i >= 0; i--)    {      char *p, *string;      rtx value;      string = p = (char *) oballoc (2				     + strlen (attr->name)				     + strlen (XSTR (av->value, 0)));      strcpy (p, attr->name);      strcat (p, "_");      strcat (p, XSTR (av->value, 0));      for (; *p != '\0'; p++)	if (*p >= 'a' && *p <= 'z')	  *p -= 'a' - 'A';      value = attr_rtx (SYMBOL_REF, string);      RTX_UNCHANGING_P (value) = 1;            XVECEXP (condexp, 0, 2 * i) = attr_rtx (EQ, exp, value);      XVECEXP (condexp, 0, 2 * i + 1) = av->value;    }  return condexp;}/* Given a valid expression for an attribute value, remove any IF_THEN_ELSE   expressions by converting them into a COND.  This removes cases from this   program.  Also, replace an attribute value of "*" with the default attribute   value.  */static rtxmake_canonical (attr, exp)     struct attr_desc *attr;     rtx exp;{  int i;  rtx newexp;  switch (GET_CODE (exp))    {    case CONST_INT:      exp = make_numeric_value (INTVAL (exp));      break;    case CONST_STRING:      if (! strcmp (XSTR (exp, 0), "*"))	{	  if (attr == 0 || attr->default_val == 0)	    fatal ("(attr_value \"*\") used in invalid context.");	  exp = attr->default_val->value;	}      break;    case SYMBOL_REF:      if (!attr->is_const || RTX_UNCHANGING_P (exp))	break;      /* The SYMBOL_REF is constant for a given run, so mark it as unchanging.	 This makes the COND something that won't be considered an arbitrary	 expression by walk_attr_value.  */      RTX_UNCHANGING_P (exp) = 1;      exp = convert_const_symbol_ref (exp, attr);      RTX_UNCHANGING_P (exp) = 1;      exp = check_attr_value (exp, attr);      /* Goto COND case since this is now a COND.  Note that while the         new expression is rescanned, all symbol_ref notes are mared as	 unchanging.  */      goto cond;    case IF_THEN_ELSE:      newexp = rtx_alloc (COND);      XVEC (newexp, 0) = rtvec_alloc (2);      XVECEXP (newexp, 0, 0) = XEXP (exp, 0);      XVECEXP (newexp, 0, 1) = XEXP (exp, 1);      XEXP (newexp, 1) = XEXP (exp, 2);      exp = newexp;      /* Fall through to COND case since this is now a COND.  */    case COND:    cond:      {	int allsame = 1;	rtx defval;	/* First, check for degenerate COND. */	if (XVECLEN (exp, 0) == 0)	  return make_canonical (attr, XEXP (exp, 1));	defval = XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1));	for (i = 0; i < XVECLEN (exp, 0); i += 2)	  {	    XVECEXP (exp, 0, i) = copy_boolean (XVECEXP (exp, 0, i));	    XVECEXP (exp, 0, i + 1)	      = make_canonical (attr, XVECEXP (exp, 0, i + 1));	    if (! rtx_equal_p (XVECEXP (exp, 0, i + 1), defval))	      allsame = 0;	  }	if (allsame)	  return defval;	break;      }    }  return exp;}static rtxcopy_boolean (exp)     rtx exp;{  if (GET_CODE (exp) == AND || GET_CODE (exp) == IOR)    return attr_rtx (GET_CODE (exp), copy_boolean (XEXP (exp, 0)),		     copy_boolean (XEXP (exp, 1)));  return exp;}/* Given a value and an attribute description, return a `struct attr_value *'   that represents that value.  This is either an existing structure, if the   value has been previously encountered, or a newly-created structure.   `insn_code' is the code of an insn whose attribute has the specified   value (-2 if not processing an insn).  We ensure that all insns for   a given value have the same number of alternatives if the value checks   alternatives.  */static struct attr_value *get_attr_value (value, attr, insn_code)     rtx value;     struct attr_desc *attr;     int insn_code;{  struct attr_value *av;  int num_alt = 0;  value = make_canonical (attr, value);  if (compares_alternatives_p (value))    {      if (insn_code < 0 || insn_alternatives == NULL)	fatal ("(eq_attr \"alternatives\" ...) used in non-insn context");      else	num_alt = insn_alternatives[insn_code];    }  for (av = attr->first_value; av; av = av->next)    if (rtx_equal_p (value, av->value)	&& (num_alt == 0 || av->first_insn == NULL	    || insn_alternatives[av->first_insn->insn_code]))      return av;  av = (struct attr_value *) oballoc (sizeof (struct attr_value));  av->value = value;  av->next = attr->first_value;  attr->first_value = av;  av->first_insn = NULL;  av->num_insns = 0;  av->has_asm_insn = 0;  return av;}/* After all DEFINE_DELAYs have been read in, create internal attributes   to generate the required routines.   First, we compute the number of delay slots for each insn (as a COND of   each of the test expressions in DEFINE_DELAYs).  Then, if more than one   delay type is specified, we compute a similar function giving the   DEFINE_DELAY ordinal for each insn.   Finally, for each [DEFINE_DELAY, slot #] pair, we compute an attribute that   tells whether a given insn can be in that delay slot.   Normal attribute filling and optimization expands these to contain the   information needed to handle delay slots.  */static voidexpand_delays (){  struct delay_desc *delay;  rtx condexp;  rtx newexp;  int i;  char *p;  /* First, generate data for `num_delay_slots' function.  */  condexp = rtx_alloc (COND);  XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);  XEXP (condexp, 1) = make_numeric_value (0);  for (i = 0, delay = delays; delay; i += 2, delay = delay->next)    {      XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);      XVECEXP (condexp, 0, i + 1)	= make_numeric_value (XVECLEN (delay->def, 1) / 3);    }  make_internal_attr ("*num_delay_slots", condexp, 0);  /* If more than one delay type, do the same for computing the delay type.  */  if (num_delays > 1)    {      condexp = rtx_alloc (COND);      XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);      XEXP (condexp, 1) = make_numeric_value (0);      for (i = 0, delay = delays; delay; i += 2, delay = delay->next)	{	  XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);	  XVECEXP (condexp, 0, i + 1) = make_numeric_value (delay->num);	}      make_internal_attr ("*delay_type", condexp, 1);    }  /* For each delay possibility and delay slot, compute an eligibility     attribute for non-annulled insns and for each type of annulled (annul     if true and annul if false).  */ for (delay = delays; delay; delay = delay->next)   {     for (i = 0; i < XVECLEN (delay->def, 1); i += 3)       {	 condexp = XVECEXP (delay->def, 1, i);	 if (condexp == 0) condexp = false_rtx;	 newexp = attr_rtx (IF_THEN_ELSE, condexp,			    make_numeric_value (1), make_numeric_value (0));	 p = attr_printf (sizeof ("*delay__") + MAX_DIGITS*2, "*delay_%d_%d",			  delay->num, i / 3);	 make_internal_attr (p, newexp, 1);	 if (have_annul_true)	   {	     condexp = XVECEXP (delay->def, 1, i + 1);	     if (condexp == 0) condexp = false_rtx;	     newexp = attr_rtx (IF_THEN_ELSE, condexp,				make_numeric_value (1),				make_numeric_value (0));	     p = attr_printf (sizeof ("*annul_true__") + MAX_DIGITS*2,			      "*annul_true_%d_%d", delay->num, i / 3);	     make_internal_attr (p, newexp, 1);	   }	 if (have_annul_false)	   {	     condexp = XVECEXP (delay->def, 1, i + 2);	     if (condexp == 0) condexp = false_rtx;	     newexp = attr_rtx (IF_THEN_ELSE, condexp,				make_numeric_value (1),				make_numeric_value (0));	     p = attr_printf (sizeof ("*annul_false__") + MAX_DIGITS*2,			      "*annul_false_%d_%d", delay->num, i / 3);	     make_internal_attr (p, newexp, 1);	   }       }   }}/* This function is given a left and right side expression and an operator.   Each side is a conditional expression, each alternative of which has a   numerical value.  The function returns another conditional expression   which, for every possible set of condition values, returns a value that is   the operator applied to the values of the two sides.   Since this is called early, it must also support IF_THEN_ELSE.  */static rtxoperate_exp (op, left, right)     enum operator op;     rtx left, right;{  int left_value, right_value;  rtx newexp;  int i;  /* If left is a string, apply operator to it and the right side.  */  if (GET_CODE (left) == CONST_STRING)    {      /* If right is also a string, just perform the operation.  */      if (GET_CODE (right) == CONST_STRING)	{	  left_value = atoi (XSTR (left, 0));	  right_value = atoi (XSTR (right, 0));	  switch (op)	    {	    case PLUS_OP:	      i = left_value + right_value;	      break;	    case MINUS_OP:	      i = left_value - right_value;	      break;	    case POS_MINUS_OP:  /* The positive part of LEFT - RIGHT.  */	      if (left_value > right_value)		i = left_value - right_value;	      else		i = 0;	      break;	    case OR_OP:	      i = left_value | right_value;	      break;	    case EQ_OP:	      i = left_value == right_value;	      break;	    case RANGE_OP:	      i = (left_value << (HOST_BITS_PER_INT / 2)) | right_value;	      break;	    case MAX_OP:	      if (left_value > right_value)		i = left_value;	      else		i = right_value;	      break;	    case MIN_OP:	      if (left_value < right_value)		i = left_value;	      else		i = right_value;	      break;	    default:	      abort ();	    }	  return make_numeric_value (i);	}      else if (GET_CODE (right) == IF_THEN_ELSE)	{	  /* Apply recursively to all values within.  */	  rtx newleft = operate_exp (op, left, XEXP (right, 1));	  rtx newright = operate_exp (op, left, XEXP (right, 2));	  if (rtx_equal_p (newleft, newright))	    return newleft;	  return attr_rtx (IF_THEN_ELSE, XEXP (right, 0), newleft, newright);	}      else if (GET_CODE (right) == COND)	{	  int allsame = 1;	  rtx defval;	  newexp = rtx_alloc (COND);	  XVEC (newexp, 0) = rtvec_alloc (XVECLEN (right, 0));	  defval = XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1));	  for (i = 0; i < XVECLEN (right, 0); i += 2)	    {	      XVECEXP (newexp, 0, i) = XVECEXP (right, 0, i);	      XVECEXP (newexp, 0, i + 1)		= operate_exp (op, left, XVECEXP (right, 0, i + 1));	      if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),				 defval))     		allsame = 0;	    }	  /* If the resulting cond is trivial (all alternatives	     give the same value), optimize it away.  */	  if (allsame)	    {	      obstack_free (rtl_obstack, newexp);	      return operate_exp (op, left, XEXP (right, 1));	    }

⌨️ 快捷键说明

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