#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 htab_t condition_table;
static void add_condition (const char *);
static void write_header (void);
static void write_conditions (void);
static int write_one_condition (void **, void *);
static void
add_condition (const char *expr)
{
struct c_test *test;
if (expr[0] == 0)
return;
test = XNEW (struct c_test);
test->expr = expr;
*(htab_find_slot (condition_table, test, INSERT)) = test;
}
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 \"insn-constants.h\"\n");
puts ("\
/* 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");
puts ("\
#include \"system.h\"\n\
#if GCC_VERSION < 3001\n\
#include \"dummy-conditions.c\"\n\
#else\n\
#include \"coretypes.h\"\n\
#include \"tm.h\"\n\
#include \"rtl.h\"\n\
#include \"tm_p.h\"\n\
#include \"function.h\"\n");
puts ("\
/* 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");
puts ("\
#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 \"gensupport.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");
puts ("\
/* If we don't have __builtin_constant_p, or it's not acceptable in\n\
array initializers, fall back (by using dummy-conditions.c above)\n\
to assuming that all conditions potentially vary at run time. It\n\
works in 3.0.1 and later; 3.0 only when not optimizing. */\n\
#define MAYBE_EVAL(expr) (__builtin_constant_p(expr) ? (int) (expr) : -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;
fputs (" { \"", stdout);
for (p = test->expr; *p; p++)
{
if (*p == '\n')
fputs ("\\n\\\n", stdout);
else if (*p == '"')
fputs ("\\\"", stdout);
else
putchar (*p);
}
printf ("\",\n MAYBE_EVAL (%s) },\n", test->expr);
return 1;
}
static void
write_conditions (void)
{
puts ("\
/* 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\
\n\
const struct c_test insn_conditions[] = {");
htab_traverse (condition_table, write_one_condition, 0);
puts ("};\n");
printf ("const size_t n_insn_conditions = %lu;\n",
(unsigned long) htab_elements (condition_table));
puts ("const int insn_elision_unavailable = 0;\n#endif");
}
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);
condition_table = htab_create (1000, hash_c_test, cmp_c_test, NULL);
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_condition (XSTR (desc, 2));
if (!strcmp (XSTR (desc, 0), "eh_return"))
saw_eh_return = 1;
break;
case DEFINE_SPLIT:
case DEFINE_PEEPHOLE:
case DEFINE_PEEPHOLE2:
add_condition (XSTR (desc, 1));
break;
}
}
write_header ();
write_conditions ();
fflush (stdout);
return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
}