genconditions.c revision 132718
1117395Skan/* Process machine description and calculate constant conditions. 2132718Skan Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. 3117395Skan 4132718Skan This file is part of GCC. 5117395Skan 6132718Skan GCC is free software; you can redistribute it and/or modify 7117395Skan it under the terms of the GNU General Public License as published by 8117395Skan the Free Software Foundation; either version 2, or (at your option) 9117395Skan any later version. 10117395Skan 11132718Skan GCC is distributed in the hope that it will be useful, 12117395Skan but WITHOUT ANY WARRANTY; without even the implied warranty of 13117395Skan MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14117395Skan GNU General Public License for more details. 15117395Skan 16117395Skan You should have received a copy of the GNU General Public License 17132718Skan along with GCC; see the file COPYING. If not, write to 18117395Skan the Free Software Foundation, 59 Temple Place - Suite 330, 19117395Skan Boston, MA 02111-1307, USA. */ 20117395Skan 21117395Skan/* In a machine description, all of the insn patterns - define_insn, 22117395Skan define_expand, define_split, define_peephole, define_peephole2 - 23117395Skan contain an optional C expression which makes the final decision 24117395Skan about whether or not this pattern is usable. That expression may 25117395Skan turn out to be always false when the compiler is built. If it is, 26117395Skan most of the programs that generate code from the machine 27117395Skan description can simply ignore the entire pattern. */ 28117395Skan 29132718Skan#include "bconfig.h" 30117395Skan#include "system.h" 31132718Skan#include "coretypes.h" 32132718Skan#include "tm.h" 33117395Skan#include "rtl.h" 34117395Skan#include "errors.h" 35117395Skan#include "hashtab.h" 36117395Skan#include "gensupport.h" 37117395Skan 38132718Skan/* so we can include except.h in the generated file. */ 39117395Skanstatic int saw_eh_return; 40117395Skan 41117395Skanstatic htab_t condition_table; 42117395Skan 43132718Skanstatic void add_condition (const char *); 44132718Skanstatic void write_header (void); 45132718Skanstatic void write_conditions (void); 46132718Skanstatic int write_one_condition (void **, void *); 47117395Skan 48117395Skan/* Record the C test expression EXPR in the condition_table. 49117395Skan Duplicates clobber previous entries, which leaks memory, but 50117395Skan we don't care for this application. */ 51117395Skan 52117395Skanstatic void 53132718Skanadd_condition (const char *expr) 54117395Skan{ 55117395Skan struct c_test *test; 56117395Skan 57117395Skan if (expr[0] == 0) 58117395Skan return; 59117395Skan 60132718Skan test = xmalloc (sizeof (struct c_test)); 61117395Skan test->expr = expr; 62117395Skan 63117395Skan *(htab_find_slot (condition_table, test, INSERT)) = test; 64117395Skan} 65117395Skan 66117395Skan/* Generate the header for insn-conditions.c. */ 67117395Skan 68117395Skanstatic void 69132718Skanwrite_header (void) 70117395Skan{ 71117395Skan puts ("\ 72117395Skan/* Generated automatically by the program `genconditions' from the target\n\ 73117395Skan machine description file. */\n\ 74117395Skan\n\ 75132718Skan#include \"bconfig.h\"\n\ 76117395Skan#include \"insn-constants.h\"\n"); 77117395Skan 78117395Skan puts ("\ 79117395Skan/* Do not allow checking to confuse the issue. */\n\ 80117395Skan#undef ENABLE_CHECKING\n\ 81117395Skan#undef ENABLE_TREE_CHECKING\n\ 82117395Skan#undef ENABLE_RTL_CHECKING\n\ 83117395Skan#undef ENABLE_RTL_FLAG_CHECKING\n\ 84117395Skan#undef ENABLE_GC_CHECKING\n\ 85117395Skan#undef ENABLE_GC_ALWAYS_COLLECT\n"); 86117395Skan 87117395Skan puts ("\ 88117395Skan#include \"system.h\"\n\ 89132718Skan#include \"coretypes.h\"\n\ 90132718Skan#include \"tm.h\"\n\ 91117395Skan#include \"rtl.h\"\n\ 92117395Skan#include \"tm_p.h\"\n\ 93117395Skan#include \"function.h\"\n"); 94117395Skan 95117395Skan puts ("\ 96117395Skan/* Fake - insn-config.h doesn't exist yet. */\n\ 97117395Skan#define MAX_RECOG_OPERANDS 10\n\ 98117395Skan#define MAX_DUP_OPERANDS 10\n\ 99117395Skan#define MAX_INSNS_PER_SPLIT 5\n"); 100117395Skan 101117395Skan puts ("\ 102117395Skan#include \"regs.h\"\n\ 103117395Skan#include \"recog.h\"\n\ 104117395Skan#include \"real.h\"\n\ 105117395Skan#include \"output.h\"\n\ 106117395Skan#include \"flags.h\"\n\ 107117395Skan#include \"hard-reg-set.h\"\n\ 108117395Skan#include \"resource.h\"\n\ 109117395Skan#include \"toplev.h\"\n\ 110117395Skan#include \"reload.h\"\n\ 111117395Skan#include \"gensupport.h\"\n"); 112117395Skan 113117395Skan if (saw_eh_return) 114117395Skan puts ("#define HAVE_eh_return 1"); 115117395Skan puts ("#include \"except.h\"\n"); 116117395Skan 117117395Skan puts ("\ 118117395Skan/* Dummy external declarations. */\n\ 119117395Skanextern rtx insn;\n\ 120117395Skanextern rtx ins1;\n\ 121132718Skanextern rtx operands[];\n"); 122117395Skan 123117395Skan puts ("\ 124117395Skan/* If we don't have __builtin_constant_p, or it's not acceptable in\n\ 125117395Skan array initializers, fall back to assuming that all conditions\n\ 126117395Skan potentially vary at run time. It works in 3.0.1 and later; 3.0\n\ 127117395Skan only when not optimizing. */\n\ 128117395Skan#if (GCC_VERSION >= 3001) || ((GCC_VERSION == 3000) && !__OPTIMIZE__)\n\ 129117395Skan# define MAYBE_EVAL(expr) (__builtin_constant_p(expr) ? (int) (expr) : -1)\n\ 130117395Skan#else\n\ 131117395Skan# define MAYBE_EVAL(expr) -1\n\ 132117395Skan#endif\n"); 133117395Skan} 134117395Skan 135117395Skan/* Write out one entry in the conditions table, using the data pointed 136117395Skan to by SLOT. Each entry looks like this: 137117395Skan { "! optimize_size && ! TARGET_READ_MODIFY_WRITE", 138117395Skan MAYBE_EVAL (! optimize_size && ! TARGET_READ_MODIFY_WRITE) }, */ 139117395Skan 140117395Skanstatic int 141132718Skanwrite_one_condition (void **slot, void *dummy ATTRIBUTE_UNUSED) 142117395Skan{ 143117395Skan const struct c_test *test = * (const struct c_test **) slot; 144117395Skan const char *p; 145117395Skan 146117395Skan fputs (" { \"", stdout); 147117395Skan for (p = test->expr; *p; p++) 148117395Skan { 149117395Skan if (*p == '\n') 150117395Skan fputs ("\\n\\\n", stdout); 151117395Skan else if (*p == '"') 152117395Skan fputs ("\\\"", stdout); 153117395Skan else 154117395Skan putchar (*p); 155117395Skan } 156117395Skan 157117395Skan printf ("\",\n MAYBE_EVAL (%s) },\n", test->expr); 158117395Skan return 1; 159117395Skan} 160117395Skan 161117395Skan/* Write out the complete conditions table, its size, and a flag 162117395Skan indicating that gensupport.c can now do insn elision. */ 163117395Skanstatic void 164132718Skanwrite_conditions (void) 165117395Skan{ 166117395Skan puts ("\ 167117395Skan/* This table lists each condition found in the machine description.\n\ 168117395Skan Each condition is mapped to its truth value (0 or 1), or -1 if that\n\ 169117395Skan cannot be calculated at compile time. */\n\ 170117395Skan\n\ 171117395Skanconst struct c_test insn_conditions[] = {"); 172117395Skan 173117395Skan htab_traverse (condition_table, write_one_condition, 0); 174117395Skan 175117395Skan puts ("};\n"); 176117395Skan 177117395Skan printf ("const size_t n_insn_conditions = %lu;\n", 178117395Skan (unsigned long) htab_elements (condition_table)); 179117395Skan puts ("const int insn_elision_unavailable = 0;"); 180117395Skan} 181117395Skan 182117395Skanint 183132718Skanmain (int argc, char **argv) 184117395Skan{ 185117395Skan rtx desc; 186117395Skan int pattern_lineno; /* not used */ 187117395Skan int code; 188117395Skan 189117395Skan progname = "genconditions"; 190117395Skan 191117395Skan if (argc <= 1) 192117395Skan fatal ("No input file name."); 193117395Skan 194117395Skan if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE) 195117395Skan return (FATAL_EXIT_CODE); 196117395Skan 197117395Skan condition_table = htab_create (1000, hash_c_test, cmp_c_test, NULL); 198117395Skan 199117395Skan /* Read the machine description. */ 200117395Skan 201117395Skan while (1) 202117395Skan { 203117395Skan desc = read_md_rtx (&pattern_lineno, &code); 204117395Skan if (desc == NULL) 205117395Skan break; 206117395Skan 207117395Skan /* N.B. define_insn_and_split, define_cond_exec are handled 208117395Skan entirely within read_md_rtx; we never see them. */ 209117395Skan switch (GET_CODE (desc)) 210117395Skan { 211117395Skan default: 212117395Skan break; 213117395Skan 214117395Skan case DEFINE_INSN: 215117395Skan case DEFINE_EXPAND: 216117395Skan add_condition (XSTR (desc, 2)); 217117395Skan /* except.h needs to know whether there is an eh_return 218117395Skan pattern in the machine description. */ 219117395Skan if (!strcmp (XSTR (desc, 0), "eh_return")) 220117395Skan saw_eh_return = 1; 221117395Skan break; 222117395Skan 223117395Skan case DEFINE_SPLIT: 224117395Skan case DEFINE_PEEPHOLE: 225117395Skan case DEFINE_PEEPHOLE2: 226117395Skan add_condition (XSTR (desc, 1)); 227117395Skan break; 228117395Skan } 229117395Skan } 230117395Skan 231117395Skan write_header (); 232117395Skan write_conditions (); 233117395Skan 234117395Skan fflush (stdout); 235117395Skan return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 236117395Skan} 237