1117395Skan/* Process machine description and calculate constant conditions. 2169689Skan Copyright (C) 2001, 2002, 2003, 2004, 2005 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 18169689Skan the Free Software Foundation, 51 Franklin Street, Fifth Floor, 19169689Skan Boston, MA 02110-1301, 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 41132718Skanstatic void write_header (void); 42132718Skanstatic void write_conditions (void); 43132718Skanstatic int write_one_condition (void **, void *); 44117395Skan 45117395Skan/* Generate the header for insn-conditions.c. */ 46117395Skan 47117395Skanstatic void 48132718Skanwrite_header (void) 49117395Skan{ 50117395Skan puts ("\ 51117395Skan/* Generated automatically by the program `genconditions' from the target\n\ 52117395Skan machine description file. */\n\ 53117395Skan\n\ 54132718Skan#include \"bconfig.h\"\n\ 55169689Skan#include \"system.h\"\n\ 56169689Skan\n\ 57169689Skan/* It is necessary, but not entirely safe, to include the headers below\n\ 58169689Skan in a generator program. As a defensive measure, don't do so when the\n\ 59169689Skan table isn't going to have anything in it. */\n\ 60169689Skan#if GCC_VERSION >= 3001\n\ 61169689Skan\n\ 62117395Skan/* Do not allow checking to confuse the issue. */\n\ 63117395Skan#undef ENABLE_CHECKING\n\ 64117395Skan#undef ENABLE_TREE_CHECKING\n\ 65117395Skan#undef ENABLE_RTL_CHECKING\n\ 66117395Skan#undef ENABLE_RTL_FLAG_CHECKING\n\ 67117395Skan#undef ENABLE_GC_CHECKING\n\ 68169689Skan#undef ENABLE_GC_ALWAYS_COLLECT\n\ 69169689Skan\n\ 70132718Skan#include \"coretypes.h\"\n\ 71132718Skan#include \"tm.h\"\n\ 72169689Skan#include \"insn-constants.h\"\n\ 73117395Skan#include \"rtl.h\"\n\ 74117395Skan#include \"tm_p.h\"\n\ 75169689Skan#include \"function.h\"\n\ 76169689Skan\n\ 77117395Skan/* Fake - insn-config.h doesn't exist yet. */\n\ 78117395Skan#define MAX_RECOG_OPERANDS 10\n\ 79117395Skan#define MAX_DUP_OPERANDS 10\n\ 80169689Skan#define MAX_INSNS_PER_SPLIT 5\n\ 81169689Skan\n\ 82117395Skan#include \"regs.h\"\n\ 83117395Skan#include \"recog.h\"\n\ 84117395Skan#include \"real.h\"\n\ 85117395Skan#include \"output.h\"\n\ 86117395Skan#include \"flags.h\"\n\ 87117395Skan#include \"hard-reg-set.h\"\n\ 88117395Skan#include \"resource.h\"\n\ 89117395Skan#include \"toplev.h\"\n\ 90117395Skan#include \"reload.h\"\n\ 91169689Skan#include \"tm-constrs.h\"\n"); 92117395Skan 93117395Skan if (saw_eh_return) 94117395Skan puts ("#define HAVE_eh_return 1"); 95117395Skan puts ("#include \"except.h\"\n"); 96117395Skan 97117395Skan puts ("\ 98117395Skan/* Dummy external declarations. */\n\ 99117395Skanextern rtx insn;\n\ 100117395Skanextern rtx ins1;\n\ 101169689Skanextern rtx operands[];\n\ 102169689Skan\n\ 103169689Skan#endif /* gcc >= 3.0.1 */\n"); 104117395Skan} 105117395Skan 106117395Skan/* Write out one entry in the conditions table, using the data pointed 107117395Skan to by SLOT. Each entry looks like this: 108117395Skan 109169689Skan { "! optimize_size && ! TARGET_READ_MODIFY_WRITE", 110169689Skan __builtin_constant_p (! optimize_size && ! TARGET_READ_MODIFY_WRITE) 111169689Skan ? (int) (! optimize_size && ! TARGET_READ_MODIFY_WRITE) 112169689Skan : -1) }, */ 113169689Skan 114117395Skanstatic int 115169689Skanwrite_one_condition (void **slot, void * ARG_UNUSED (dummy)) 116117395Skan{ 117117395Skan const struct c_test *test = * (const struct c_test **) slot; 118117395Skan const char *p; 119117395Skan 120169689Skan print_rtx_ptr_loc (test->expr); 121117395Skan fputs (" { \"", stdout); 122117395Skan for (p = test->expr; *p; p++) 123117395Skan { 124169689Skan switch (*p) 125169689Skan { 126169689Skan case '\n': fputs ("\\n\\", stdout); break; 127169689Skan case '\\': 128169689Skan case '\"': putchar ('\\'); break; 129169689Skan default: break; 130169689Skan } 131169689Skan putchar (*p); 132117395Skan } 133117395Skan 134169689Skan fputs ("\",\n __builtin_constant_p ", stdout); 135169689Skan print_c_condition (test->expr); 136169689Skan fputs ("\n ? (int) ", stdout); 137169689Skan print_c_condition (test->expr); 138169689Skan fputs ("\n : -1 },\n", stdout); 139117395Skan return 1; 140117395Skan} 141117395Skan 142117395Skan/* Write out the complete conditions table, its size, and a flag 143117395Skan indicating that gensupport.c can now do insn elision. */ 144117395Skanstatic void 145132718Skanwrite_conditions (void) 146117395Skan{ 147117395Skan puts ("\ 148169689Skan/* Structure definition duplicated from gensupport.h rather than\n\ 149169689Skan drag in that file and its dependencies. */\n\ 150169689Skanstruct c_test\n\ 151169689Skan{\n\ 152169689Skan const char *expr;\n\ 153169689Skan int value;\n\ 154169689Skan};\n\ 155169689Skan\n\ 156117395Skan/* This table lists each condition found in the machine description.\n\ 157117395Skan Each condition is mapped to its truth value (0 or 1), or -1 if that\n\ 158169689Skan cannot be calculated at compile time.\n\ 159169689Skan If we don't have __builtin_constant_p, or it's not acceptable in array\n\ 160169689Skan initializers, fall back to assuming that all conditions potentially\n\ 161169689Skan vary at run time. It works in 3.0.1 and later; 3.0 only when not\n\ 162169689Skan optimizing. */\n\ 163117395Skan\n\ 164169689Skan#if GCC_VERSION >= 3001\n\ 165169689Skanstatic const struct c_test insn_conditions[] = {\n"); 166117395Skan 167169689Skan traverse_c_tests (write_one_condition, 0); 168117395Skan 169169689Skan puts ("\n};\n#endif /* gcc >= 3.0.1 */\n"); 170169689Skan} 171117395Skan 172169689Skan/* Emit code which will convert the C-format table to a 173169689Skan (define_conditions) form, which the MD reader can understand. 174169689Skan The result will be added to the set of files scanned by 175169689Skan 'downstream' generators. */ 176169689Skanstatic void 177169689Skanwrite_writer (void) 178169689Skan{ 179169689Skan puts ("int\n" 180169689Skan "main(void)\n" 181169689Skan "{\n" 182169689Skan " unsigned int i;\n" 183169689Skan " const char *p;\n" 184169689Skan " puts (\"(define_conditions [\");\n" 185169689Skan "#if GCC_VERSION >= 3001\n" 186169689Skan " for (i = 0; i < ARRAY_SIZE (insn_conditions); i++)\n" 187169689Skan " {\n" 188169689Skan " printf (\" (%d \\\"\", insn_conditions[i].value);\n" 189169689Skan " for (p = insn_conditions[i].expr; *p; p++)\n" 190169689Skan " {\n" 191169689Skan " switch (*p)\n" 192169689Skan " {\n" 193169689Skan " case '\\\\':\n" 194169689Skan " case '\\\"': putchar ('\\\\'); break;\n" 195169689Skan " default: break;\n" 196169689Skan " }\n" 197169689Skan " putchar (*p);\n" 198169689Skan " }\n" 199169689Skan " puts (\"\\\")\");\n" 200169689Skan " }\n" 201169689Skan "#endif /* gcc >= 3.0.1 */\n" 202169689Skan " puts (\"])\");\n" 203169689Skan " fflush (stdout);\n" 204169689Skan "return ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;\n" 205169689Skan "}"); 206117395Skan} 207117395Skan 208117395Skanint 209132718Skanmain (int argc, char **argv) 210117395Skan{ 211117395Skan rtx desc; 212117395Skan int pattern_lineno; /* not used */ 213117395Skan int code; 214117395Skan 215117395Skan progname = "genconditions"; 216117395Skan 217169689Skan if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 218117395Skan return (FATAL_EXIT_CODE); 219117395Skan 220117395Skan /* Read the machine description. */ 221117395Skan while (1) 222117395Skan { 223117395Skan desc = read_md_rtx (&pattern_lineno, &code); 224117395Skan if (desc == NULL) 225117395Skan break; 226117395Skan 227117395Skan /* N.B. define_insn_and_split, define_cond_exec are handled 228117395Skan entirely within read_md_rtx; we never see them. */ 229117395Skan switch (GET_CODE (desc)) 230117395Skan { 231117395Skan default: 232117395Skan break; 233117395Skan 234117395Skan case DEFINE_INSN: 235117395Skan case DEFINE_EXPAND: 236169689Skan add_c_test (XSTR (desc, 2), -1); 237117395Skan /* except.h needs to know whether there is an eh_return 238117395Skan pattern in the machine description. */ 239117395Skan if (!strcmp (XSTR (desc, 0), "eh_return")) 240117395Skan saw_eh_return = 1; 241117395Skan break; 242117395Skan 243117395Skan case DEFINE_SPLIT: 244117395Skan case DEFINE_PEEPHOLE: 245117395Skan case DEFINE_PEEPHOLE2: 246169689Skan add_c_test (XSTR (desc, 1), -1); 247117395Skan break; 248117395Skan } 249117395Skan } 250117395Skan 251117395Skan write_header (); 252117395Skan write_conditions (); 253169689Skan write_writer (); 254117395Skan 255117395Skan fflush (stdout); 256117395Skan return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 257117395Skan} 258