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

📄 genrecog.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 4 页
字号:
      if (add == 0)	continue;      /* Otherwise, find the best place to insert ADD.  Normally this is	 BEST_POSITION.  However, if we went all the way to the top of	 the list, it might be better to insert at the top.  */      if (best_position == 0)	abort ();      if (old == 0	  && position_merit (NULL_PTR, add_mode, add->code) < best_merit)	{	  add->prev = 0;	  add->next = oldh.first;	  oldh.first->prev = add;	  oldh.first = add;	}      else	{	  add->prev = best_position;	  add->next = best_position->next;	  best_position->next = add;	  if (best_position == oldh.last)	    oldh.last = add;	  else	    add->next->prev = add;	}    }  return oldh;}/* Count the number of subnodes of HEAD.  If the number is high enough,   make the first node in HEAD start a separate subroutine in the C code   that is generated.   TYPE gives the type of routine we are writing.   INITIAL is non-zero if this is the highest-level node.  We never write   it out here.  */static intbreak_out_subroutines (head, type, initial)     struct decision_head head;     enum routine_type type;     int initial;{  int size = 0;  struct decision *sub;  for (sub = head.first; sub; sub = sub->next)    size += 1 + break_out_subroutines (sub->success, type, 0);  if (size > SUBROUTINE_THRESHOLD && ! initial)    {      head.first->subroutine_number = ++next_subroutine_number;      write_subroutine (head.first, type);      size = 1;    }  return size;}/* Write out a subroutine of type TYPE to do comparisons starting at node   TREE.  */static voidwrite_subroutine (tree, type)     struct decision *tree;     enum routine_type type;{  int i;  if (type == SPLIT)    printf ("rtx\nsplit");  else    printf ("int\nrecog");  if (tree != 0 && tree->subroutine_number > 0)    printf ("_%d", tree->subroutine_number);  else if (type == SPLIT)    printf ("_insns");  printf (" (x0, insn");  if (type == RECOG)    printf (", pnum_clobbers");  printf (")\n");  printf ("     register rtx x0;\n     rtx insn;\n");  if (type == RECOG)    printf ("     int *pnum_clobbers;\n");  printf ("{\n");  printf ("  register rtx *ro = &recog_operand[0];\n");  printf ("  register rtx ");  for (i = 1; i < max_depth; i++)    printf ("x%d, ", i);  printf ("x%d;\n", max_depth);  printf ("  %s tem;\n", type == SPLIT ? "rtx" : "int");  write_tree (tree, "", NULL_PTR, 1, type);  printf (" ret0: return %d;\n}\n\n", type == SPLIT ? 0 : -1);}/* This table is used to indent the recog_* functions when we are inside   conditions or switch statements.  We only support small indentations   and always indent at least two spaces.  */static char *indents[]  = {"  ", "  ", "  ", "   ", "    ", "     ", "      ", "       ",     "\t", "\t ", "\t  ", "\t   ", "\t    ", "\t     ", "\t      ",     "\t\t", "\t\t ", "\t\t  ", "\t\t   ", "\t\t    ", "\t\t     "};/* Write out C code to perform the decisions in TREE for a subroutine of   type TYPE.  If all of the choices fail, branch to node AFTERWARD, if   non-zero, otherwise return.  PREVPOS is the position of the node that   branched to this test.   When we merged all alternatives, we tried to set up a convenient order.   Specifically, tests involving the same mode are all grouped together,   followed by a group that does not contain a mode test.  Within each group   of the same mode, we also group tests with the same code, followed by a   group that does not test a code.   Occasionally, we cannot arbitrarily reorder the tests so that multiple   sequence of groups as described above are present.   We generate two nested switch statements, the outer statement for   testing modes, and the inner switch for testing RTX codes.  It is   not worth optimizing cases when only a small number of modes or    codes is tested, since the compiler can do that when compiling the   resulting function.   We do check for when every test is the same mode   or code.  */static voidwrite_tree_1 (tree, prevpos, afterward, type)     struct decision *tree;     char *prevpos;     struct decision *afterward;     enum routine_type type;{  register struct decision *p, *p1;  register int depth = tree ? strlen (tree->position) : 0;  enum machine_mode switch_mode = VOIDmode;  RTX_CODE switch_code = UNKNOWN;  int uncond = 0;  char modemap[NUM_MACHINE_MODES];  char codemap[NUM_RTX_CODE];  int indent = 2;  int i;  /* One tricky area is what is the exact state when we branch to a     node's label.  There are two cases where we branch: when looking at     successors to a node, or when a set of tests fails.     In the former case, we are always branching to the first node in a     decision list and we want all required tests to be performed.  We     put the labels for such nodes in front of any switch or test statements.     These branches are done without updating the position to that of the     target node.     In the latter case, we are branching to a node that is not the first     node in a decision list.  We have already checked that it is possible     for both the node we originally tested at this level and the node we     are branching to to be both match some pattern.  That means that they     usually will be testing the same mode and code.  So it is normally safe     for such labels to be inside switch statements, since the tests done     by virtue of arriving at that label will usually already have been     done.  The exception is a branch from a node that does not test a     mode or code to one that does.  In such cases, we set the `retest_mode'     or `retest_code' flags.  That will ensure that we start a new switch     at that position and put the label before the switch.      The branches in the latter case must set the position to that of the     target node.  */  printf ("\n");  if (tree && tree->subroutine_number == 0)    {      printf ("  L%d:\n", tree->number);      tree->label_needed = 0;    }  if (tree)    {      change_state (prevpos, tree->position, 2);      prevpos = tree->position;    }  for (p = tree; p; p = p->next)    {      enum machine_mode mode = p->enforce_mode ? p->mode : VOIDmode;      int need_bracket;      int wrote_bracket = 0;      int inner_indent;      if (p->success.first == 0 && p->insn_code_number < 0)	abort ();      /* Find the next alternative to p that might be true when p is true.	 Test that one next if p's successors fail.  */      for (p1 = p->next; p1 && not_both_true (p, p1, 1); p1 = p1->next)	;      p->afterward = p1;      if (p1)	{	  if (mode == VOIDmode && p1->enforce_mode && p1->mode != VOIDmode)	    p1->retest_mode = 1;	  if (p->code == UNKNOWN && p1->code != UNKNOWN)	    p1->retest_code = 1;	  p1->label_needed = 1;	}      /* If we have a different code or mode than the last node and	 are in a switch on codes, we must either end the switch or	 go to another case.  We must also end the switch if this	 node needs a label and to retest either the mode or code.  */      if (switch_code != UNKNOWN	  && (switch_code != p->code || switch_mode != mode	      || (p->label_needed && (p->retest_mode || p->retest_code))))	{	  enum rtx_code code = p->code;	  /* If P is testing a predicate that we know about and we haven't	     seen any of the codes that are valid for the predicate, we	     can write a series of "case" statement, one for each possible	     code.  Since we are already in a switch, these redundant tests	     are very cheap and will reduce the number of predicate called. */	  if (p->pred >= 0)	    {	      for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i] != 0; i++)		if (codemap[(int) preds[p->pred].codes[i]])		  break;	      if (preds[p->pred].codes[i] == 0)		code = MATCH_OPERAND;	    }	  if (code == UNKNOWN || codemap[(int) code]	      || switch_mode != mode	      || (p->label_needed && (p->retest_mode || p->retest_code)))	    {	      printf ("%s}\n", indents[indent - 2]);	      switch_code = UNKNOWN;	      indent -= 4;	    }	  else	    {	      if (! uncond)		printf ("%sbreak;\n", indents[indent]);	      if (code == MATCH_OPERAND)		{		  for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i] != 0; i++)		    {		      printf ("%scase ", indents[indent - 2]);		      print_code (preds[p->pred].codes[i]);		      printf (":\n");		      codemap[(int) preds[p->pred].codes[i]] = 1;		    }		}	      else		{		  printf ("%scase ", indents[indent - 2]);		  print_code (code);		  printf (":\n");		  codemap[(int) p->code] = 1;		}	      switch_code = code;	    }	  uncond = 0;	}      /* If we were previously in a switch on modes and now have a different	 mode, end at least the case, and maybe end the switch if we are	 not testing a mode or testing a mode whose case we already saw.  */      if (switch_mode != VOIDmode	  && (switch_mode != mode || (p->label_needed && p->retest_mode)))	{	  if (mode == VOIDmode || modemap[(int) mode]	      || (p->label_needed && p->retest_mode))	    {	      printf ("%s}\n", indents[indent - 2]);	      switch_mode = VOIDmode;	      indent -= 4;	    }	  else	    {	      if (! uncond)		printf ("      break;\n");	      printf ("    case %smode:\n", GET_MODE_NAME (mode));	      switch_mode = mode;	      modemap[(int) mode] = 1;	    }	  uncond = 0;	}      /* If we are about to write dead code, something went wrong.  */      if (! p->label_needed && uncond)	abort ();      /* If we need a label and we will want to retest the mode or code at	 that label, write the label now.  We have already ensured that	 things will be valid for the test.  */      if (p->label_needed && (p->retest_mode || p->retest_code))	{	  printf ("%sL%d:\n", indents[indent - 2], p->number);	  p->label_needed = 0;	}      uncond = 0;      /* If we are not in any switches, see if we can shortcut things	 by checking for identical modes and codes.  */      if (switch_mode == VOIDmode && switch_code == UNKNOWN)	{	  /* If p and its alternatives all want the same mode,	     reject all others at once, first, then ignore the mode.  */	  if (mode != VOIDmode && p->next && same_modes (p, mode))	    {	      printf ("  if (GET_MODE (x%d) != %smode)\n",		      depth, GET_MODE_NAME (p->mode));	      if (afterward)		{		  printf ("    {\n");		  change_state (p->position, afterward->position, 6);		  printf ("      goto L%d;\n    }\n", afterward->number);		}	      else		printf ("    goto ret0;\n");	      clear_modes (p);	      mode = VOIDmode;	    }	  /* If p and its alternatives all want the same code,	     reject all others at once, first, then ignore the code.  */	  if (p->code != UNKNOWN && p->next && same_codes (p, p->code))	    {	      printf ("  if (GET_CODE (x%d) != ", depth);	      print_code (p->code);	      printf (")\n");	      if (afterward)		{		  printf ("    {\n");		  change_state (p->position, afterward->position, indent + 4);		  printf ("    goto L%d;\n    }\n", afterward->number);		}	      else		printf ("    goto ret0;\n");	      clear_codes (p);	    }	}      /* If we are not in a mode switch and we are testing for a specific	 mode, start a mode switch unless we have just one node or the next	 node is not testing a mode (we have already tested for the case of	 more than one mode, but all of the same mode).  */      if (switch_mode == VOIDmode && mode != VOIDmode && p->next != 0	  && p->next->enforce_mode && p->next->mode != VOIDmode)	{	  mybzero (modemap, sizeof modemap);	  printf ("%sswitch (GET_MODE (x%d))\n", indents[indent], depth);	  printf ("%s{\n", indents[indent + 2]);	  indent += 4;	  printf ("%scase %smode:\n", indents[indent - 2],		  GET_MODE_NAME (mode));	  modemap[(int) mode] = 1;	  switch_mode = mode;	}      /* Similarly for testing codes.  */      if (switch_code == UNKNOWN && p->code != UNKNOWN && ! p->ignore_code	  && p->next != 0 && p->next->code != UNKNOWN)	{	  mybzero (codemap, sizeof codemap);	  printf ("%sswitch (GET_CODE (x%d))\n", indents[indent], depth);	  printf ("%s{\n", indents[indent + 2]);	  indent += 4;	  printf ("%scase ", indents[indent - 2]);	  print_code (p->code);	  printf (":\n");	  codemap[(int) p->code] = 1;	  switch_code = p->code;	}      /* Now that most mode and code tests have been done, we can write out	 a label for an inner node, if we haven't already. */      if (p->label_needed)	printf ("%sL%d:\n", indents[indent - 2], p->number);      inner_indent = indent;      /* The only way we can have to do a mode or code test here is if	 this node needs such a test but is the only node to be tested.	 In that case, we won't have started a switch.  Note that this is	 the only way the switch and test modes can disagree.  */      if ((mode != switch_mode && ! p->ignore_mode)	  || (p->code != switch_code && p->code != UNKNOWN && ! p->ignore_code)	  || p->test_elt_zero_int || p->test_elt_one_int	  || p->test_elt_zero_wide || p->veclen	  || p->dupno >= 0 || p->tests || p->num_clobbers_to_add)	{	  printf ("%sif (", indents[indent]);	  if (mode != switch_mode && ! p->ignore_mode)	    printf ("GET_MODE (x%d) == %smode && ",		    depth, GET_MODE_NAME (mode));	  if (p->code != switch_code && p->code != UNKNOWN && ! p->ignore_code)	    {	      printf ("GET_CODE (x%d) == ", depth);	      print_code (p->code);	      printf (" && ");	    }	  if (p->test_elt_zero_int)	    printf ("XINT (x%d, 0) == %d && ", depth, p->elt_zero_int);	  if (p->test_elt_one_int)	    printf ("XINT (x%d, 1) == %d && ", depth, p->elt_one_int);	  if (p->test_elt_zero_wide)	    {	      /* Set offset to 1 iff the number might get propagated to	         unsigned long by ANSI C rules, else 0.	         Prospective hosts are required to have at least 32 bit	         ints, and integer constants in machine descriptions	         must fit in 32 bit, thus it suffices to check only	         for 1 << 31 .  */	      HOST_WIDE_INT offset = p->elt_zero_wide == -2147483647 - 1;	      printf (#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT		       "XWINT (x%d, 0) == %d%s && ",#else		       "XWINT (x%d, 0) == %ld%s && ",#endif		       depth, p->elt_zero_wide + offset, offset ? "-1" : "");	    }	  if (p->veclen)

⌨️ 快捷键说明

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