Mercurial > hg > CbC > CbC_gcc
diff gcc/genconditions.c @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | b7f97abdc517 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gcc/genconditions.c Fri Jul 17 14:47:48 2009 +0900 @@ -0,0 +1,257 @@ +/* Process machine description and calculate constant conditions. + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 + Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +/* In a machine description, all of the insn patterns - define_insn, + define_expand, define_split, define_peephole, define_peephole2 - + contain an optional C expression which makes the final decision + about whether or not this pattern is usable. That expression may + turn out to be always false when the compiler is built. If it is, + most of the programs that generate code from the machine + description can simply ignore the entire pattern. */ + +#include "bconfig.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "rtl.h" +#include "errors.h" +#include "hashtab.h" +#include "gensupport.h" + +/* so we can include except.h in the generated file. */ +static int saw_eh_return; + +static void write_header (void); +static void write_conditions (void); +static int write_one_condition (void **, void *); + +/* Generate the header for insn-conditions.c. */ + +static void +write_header (void) +{ + puts ("\ +/* Generated automatically by the program `genconditions' from the target\n\ + machine description file. */\n\ +\n\ +#include \"bconfig.h\"\n\ +#include \"system.h\"\n\ +\n\ +/* It is necessary, but not entirely safe, to include the headers below\n\ + in a generator program. As a defensive measure, don't do so when the\n\ + table isn't going to have anything in it. */\n\ +#if GCC_VERSION >= 3001\n\ +\n\ +/* Do not allow checking to confuse the issue. */\n\ +#undef ENABLE_CHECKING\n\ +#undef ENABLE_TREE_CHECKING\n\ +#undef ENABLE_RTL_CHECKING\n\ +#undef ENABLE_RTL_FLAG_CHECKING\n\ +#undef ENABLE_GC_CHECKING\n\ +#undef ENABLE_GC_ALWAYS_COLLECT\n\ +\n\ +#include \"coretypes.h\"\n\ +#include \"tm.h\"\n\ +#include \"insn-constants.h\"\n\ +#include \"rtl.h\"\n\ +#include \"tm_p.h\"\n\ +#include \"function.h\"\n\ +\n\ +/* Fake - insn-config.h doesn't exist yet. */\n\ +#define MAX_RECOG_OPERANDS 10\n\ +#define MAX_DUP_OPERANDS 10\n\ +#define MAX_INSNS_PER_SPLIT 5\n\ +\n\ +#include \"regs.h\"\n\ +#include \"recog.h\"\n\ +#include \"real.h\"\n\ +#include \"output.h\"\n\ +#include \"flags.h\"\n\ +#include \"hard-reg-set.h\"\n\ +#include \"resource.h\"\n\ +#include \"toplev.h\"\n\ +#include \"reload.h\"\n\ +#include \"tm-constrs.h\"\n"); + + if (saw_eh_return) + puts ("#define HAVE_eh_return 1"); + puts ("#include \"except.h\"\n"); + + puts ("\ +/* Dummy external declarations. */\n\ +extern rtx insn;\n\ +extern rtx ins1;\n\ +extern rtx operands[];\n\ +\n\ +#endif /* gcc >= 3.0.1 */\n"); +} + +/* Write out one entry in the conditions table, using the data pointed + to by SLOT. Each entry looks like this: + + { "! optimize_size && ! TARGET_READ_MODIFY_WRITE", + __builtin_constant_p (! optimize_size && ! TARGET_READ_MODIFY_WRITE) + ? (int) (! optimize_size && ! TARGET_READ_MODIFY_WRITE) + : -1) }, */ + +static int +write_one_condition (void **slot, void * ARG_UNUSED (dummy)) +{ + const struct c_test *test = * (const struct c_test **) slot; + const char *p; + + print_rtx_ptr_loc (test->expr); + fputs (" { \"", stdout); + for (p = test->expr; *p; p++) + { + switch (*p) + { + case '\n': fputs ("\\n\\", stdout); break; + case '\\': + case '\"': putchar ('\\'); break; + default: break; + } + putchar (*p); + } + + fputs ("\",\n __builtin_constant_p ", stdout); + print_c_condition (test->expr); + fputs ("\n ? (int) ", stdout); + print_c_condition (test->expr); + fputs ("\n : -1 },\n", stdout); + return 1; +} + +/* Write out the complete conditions table, its size, and a flag + indicating that gensupport.c can now do insn elision. */ +static void +write_conditions (void) +{ + puts ("\ +/* Structure definition duplicated from gensupport.h rather than\n\ + drag in that file and its dependencies. */\n\ +struct c_test\n\ +{\n\ + const char *expr;\n\ + int value;\n\ +};\n\ +\n\ +/* This table lists each condition found in the machine description.\n\ + Each condition is mapped to its truth value (0 or 1), or -1 if that\n\ + cannot be calculated at compile time.\n\ + If we don't have __builtin_constant_p, or it's not acceptable in array\n\ + initializers, fall back to assuming that all conditions potentially\n\ + vary at run time. It works in 3.0.1 and later; 3.0 only when not\n\ + optimizing. */\n\ +\n\ +#if GCC_VERSION >= 3001\n\ +static const struct c_test insn_conditions[] = {\n"); + + traverse_c_tests (write_one_condition, 0); + + puts ("\n};\n#endif /* gcc >= 3.0.1 */\n"); +} + +/* Emit code which will convert the C-format table to a + (define_conditions) form, which the MD reader can understand. + The result will be added to the set of files scanned by + 'downstream' generators. */ +static void +write_writer (void) +{ + puts ("int\n" + "main(void)\n" + "{\n" + " unsigned int i;\n" + " const char *p;\n" + " puts (\"(define_conditions [\");\n" + "#if GCC_VERSION >= 3001\n" + " for (i = 0; i < ARRAY_SIZE (insn_conditions); i++)\n" + " {\n" + " printf (\" (%d \\\"\", insn_conditions[i].value);\n" + " for (p = insn_conditions[i].expr; *p; p++)\n" + " {\n" + " switch (*p)\n" + " {\n" + " case '\\\\':\n" + " case '\\\"': putchar ('\\\\'); break;\n" + " default: break;\n" + " }\n" + " putchar (*p);\n" + " }\n" + " puts (\"\\\")\");\n" + " }\n" + "#endif /* gcc >= 3.0.1 */\n" + " puts (\"])\");\n" + " fflush (stdout);\n" + "return ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;\n" + "}"); +} + +int +main (int argc, char **argv) +{ + rtx desc; + int pattern_lineno; /* not used */ + int code; + + progname = "genconditions"; + + if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) + return (FATAL_EXIT_CODE); + + /* Read the machine description. */ + while (1) + { + desc = read_md_rtx (&pattern_lineno, &code); + if (desc == NULL) + break; + + /* N.B. define_insn_and_split, define_cond_exec are handled + entirely within read_md_rtx; we never see them. */ + switch (GET_CODE (desc)) + { + default: + break; + + case DEFINE_INSN: + case DEFINE_EXPAND: + add_c_test (XSTR (desc, 2), -1); + /* except.h needs to know whether there is an eh_return + pattern in the machine description. */ + if (!strcmp (XSTR (desc, 0), "eh_return")) + saw_eh_return = 1; + break; + + case DEFINE_SPLIT: + case DEFINE_PEEPHOLE: + case DEFINE_PEEPHOLE2: + add_c_test (XSTR (desc, 1), -1); + break; + } + } + + write_header (); + write_conditions (); + write_writer (); + + fflush (stdout); + return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); +}