#include "bconfig.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "rtl.h"
#include "errors.h"
#include "hashtab.h"
#include "gensupport.h"
static int saw_eh_return;
static void write_header (void);
static void write_conditions (void);
static int write_one_condition (void **, void *);
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");
}
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;
}
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");
}
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;
int code;
progname = "genconditions";
if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
return (FATAL_EXIT_CODE);
while (1)
{
desc = read_md_rtx (&pattern_lineno, &code);
if (desc == NULL)
break;
switch (GET_CODE (desc))
{
default:
break;
case DEFINE_INSN:
case DEFINE_EXPAND:
add_c_test (XSTR (desc, 2), -1);
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);
}