r110123@banpei: zack | 2006-01-22 14:44:34 -0800

r110123@banpei:  zack | 2006-01-22 14:44:34 -0800
 	* genconditions.c (condition_table, add_condition): Delete.
 	(write_conditions): Don't emit n_insn_conditions nor
 	insn_elision_unavailable.  Issue the gcc version #ifdef here,
 	inside the table, with no #else clause ...
 	(write_header): ...not here.
 	(write_writer): New function.
 	(main): Don't initialize condition_table.  Use add_c_test.
 	Call write_writer.
 	* gensupport.c (init_md_reader_args_cb): Handle multiple input
 	files on the command line.
 	(maybe_eval_c_test): Don't check insn_elision_unavailable.
 	Return -1 if there is no entry in the table, don't abort.
 	(add_c_test, traverse_c_tests): New functions.
 	* gensupport.h (insn_elision_unavailable, insn_conditions)
 	(n_insn_conditions): Delete declarations.
 	(add_c_test, traverse_c_tests): Declare.
 	* read-rtl.c: Include gensupport.h.
 	(read_conditions): New function.
 	(read_rtx): If read_rtx_1 returns 0, treat as EOF.
 	(read_rtx_1): If we get EOF when we were looking for an initial
 	open paren, return 0.  Call read_conditions when appropriate.
 	* Makefile.in: Kill BUILD_EARLY_SUPPORT and all references to
 	dummy-conditions.o.  Eliminate references to insn-conditions.o,
 	or change them to build/gencondmd.o, as appropriate.  Remove
 	insn-constants.h from $(simple_generated_h) and insn-conditions.c
 	from $(simple_generated_c).  For all files remaining in those
 	two lists, add insn-conditions.md to the generator command line.
 	Give insn-constants.h/s-constants their own rules.  Add rules
 	for build/gencondmd.c, s-conditions, insn-conditions.md, s-condmd.
 	(build/read-rtl.o): Depend on gensupport.h.
 	(genprognormal): Include preds.
 	(genprogearly): Rename genprognoprint; only difference is now that
 	they don't link with $(BUILD_PRINT).
 	* dummy-conditions.c: Delete.

From-SVN: r110119
This commit is contained in:
Zack Weinberg 2006-01-23 15:15:05 +00:00 committed by Zack Weinberg
parent 245fc63928
commit 1c7352cde8
7 changed files with 343 additions and 188 deletions

View File

@ -1,3 +1,40 @@
2006-01-22 Zack Weinberg <zackw@panix.com>
* genconditions.c (condition_table, add_condition): Delete.
(write_conditions): Don't emit n_insn_conditions nor
insn_elision_unavailable. Issue the gcc version #ifdef here,
inside the table, with no #else clause ...
(write_header): ...not here.
(write_writer): New function.
(main): Don't initialize condition_table. Use add_c_test.
Call write_writer.
* gensupport.c (init_md_reader_args_cb): Handle multiple input
files on the command line.
(maybe_eval_c_test): Don't check insn_elision_unavailable.
Return -1 if there is no entry in the table, don't abort.
(add_c_test, traverse_c_tests): New functions.
* gensupport.h (insn_elision_unavailable, insn_conditions)
(n_insn_conditions): Delete declarations.
(add_c_test, traverse_c_tests): Declare.
* read-rtl.c: Include gensupport.h.
(read_conditions): New function.
(read_rtx): If read_rtx_1 returns 0, treat as EOF.
(read_rtx_1): If we get EOF when we were looking for an initial
open paren, return 0. Call read_conditions when appropriate.
* Makefile.in: Kill BUILD_EARLY_SUPPORT and all references to
dummy-conditions.o. Eliminate references to insn-conditions.o,
or change them to build/gencondmd.o, as appropriate. Remove
insn-constants.h from $(simple_generated_h) and insn-conditions.c
from $(simple_generated_c). For all files remaining in those
two lists, add insn-conditions.md to the generator command line.
Give insn-constants.h/s-constants their own rules. Add rules
for build/gencondmd.c, s-conditions, insn-conditions.md, s-condmd.
(build/read-rtl.o): Depend on gensupport.h.
(genprognormal): Include preds.
(genprogearly): Rename genprognoprint; only difference is now that
they don't link with $(BUILD_PRINT).
* dummy-conditions.c: Delete.
2006-01-22 Zack Weinberg <zackw@panix.com>
* genextract.c: Don't include insn-config.h. Do include vec.h.

View File

@ -198,7 +198,7 @@ GCC_WARN_CFLAGS = $(LOOSE_WARN) $($(@D)-warn) $(NOCOMMON_FLAG) $($@-warn)
# These files are to have -Werror bypassed in stage2:
# These are very hard to completely clean due to target complexities.
gcc.o-warn = -Wno-error
build/insn-conditions.o-warn = -Wno-error
build/gencondmd.o-warn = -Wno-error
# Bison-1.75 output often yields (harmless) -Wtraditional warnings
build/gengtype-yacc.o-warn = -Wno-error
# flex output may yield harmless "no previous prototype" warnings
@ -840,9 +840,7 @@ BUILD_LIBS = $(BUILD_LIBIBERTY)
BUILD_RTL = build/rtl.o build/read-rtl.o build/ggc-none.o \
build/min-insn-modes.o
BUILD_SUPPORT = build/gensupport.o build/insn-conditions.o
BUILD_EARLY_SUPPORT = build/gensupport.o build/dummy-conditions.o
BUILD_SUPPORT = build/gensupport.o
BUILD_PRINT = build/print-rtl.o
BUILD_ERRORS = build/errors.o
BUILD_VARRAY = build/varray.o
@ -1019,7 +1017,7 @@ STAGECOPYSTUFF = insn-flags.h insn-config.h insn-codes.h \
insn-output.c insn-recog.c insn-emit.c insn-extract.c insn-peep.c \
insn-attr.h insn-attrtab.c insn-opinit.c insn-preds.c insn-constants.h \
tm-preds.h \
tree-check.h insn-conditions.c min-insn-modes.c insn-modes.c insn-modes.h \
tree-check.h min-insn-modes.c insn-modes.c insn-modes.h \
genrtl.c genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-gen.h
# Files to be moved away after each stage in building.
@ -2678,26 +2676,38 @@ insn-recog.o : insn-recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
# The "; @true" construct forces Make to recheck the timestamp on the
# target file.
simple_generated_h = insn-attr.h insn-codes.h insn-config.h \
insn-constants.h insn-flags.h
simple_generated_h = insn-attr.h insn-codes.h insn-config.h insn-flags.h
simple_generated_c = insn-attrtab.c insn-conditions.c insn-emit.c \
insn-extract.c insn-opinit.c insn-output.c \
insn-peep.c insn-recog.c
simple_generated_c = insn-attrtab.c insn-emit.c insn-extract.c \
insn-opinit.c insn-output.c insn-peep.c \
insn-recog.c
$(simple_generated_h): insn-%.h: s-%; @true
$(simple_generated_h:insn-%.h=s-%): s-%: $(MD_DEPS) build/gen%$(build_exeext)
$(RUN_GEN) build/gen$*$(build_exeext) $(md_file) > tmp-$*.h
$(simple_generated_h:insn-%.h=s-%): s-%: build/gen%$(build_exeext) \
$(MD_DEPS) insn-conditions.md
$(RUN_GEN) build/gen$*$(build_exeext) $(md_file) \
insn-conditions.md > tmp-$*.h
$(SHELL) $(srcdir)/../move-if-change tmp-$*.h insn-$*.h
$(STAMP) s-$*
$(simple_generated_c): insn-%.c: s-%; @true
$(simple_generated_c:insn-%.c=s-%): s-%: $(MD_DEPS) build/gen%$(build_exeext)
$(RUN_GEN) build/gen$*$(build_exeext) $(md_file) > tmp-$*.c
$(simple_generated_c:insn-%.c=s-%): s-%: build/gen%$(build_exeext) \
$(MD_DEPS) insn-conditions.md
$(RUN_GEN) build/gen$*$(build_exeext) $(md_file) \
insn-conditions.md > tmp-$*.c
$(SHELL) $(srcdir)/../move-if-change tmp-$*.c insn-$*.c
$(STAMP) s-$*
# genconstants needs to run before insn-conditions.md is available
# (because the constants may be used in the conditions).
insn-constants.h: s-constants; @true
s-constants: build/genconstants$(build_exeext) $(MD_DEPS)
$(RUN_GEN) build/genconstants$(build_exeext) $(md_file) \
> tmp-constants.h
$(SHELL) $(srcdir)/../move-if-change tmp-constants.h insn-constants.h
$(STAMP) s-constants
# gencheck doesn't read the machine description, and the file produced
# doesn't use the insn-* convention.
tree-check.h: s-check ; @true
@ -2706,6 +2716,20 @@ s-check : build/gencheck$(build_exeext)
$(SHELL) $(srcdir)/../move-if-change tmp-check.h tree-check.h
$(STAMP) s-check
# gencondmd doesn't use the standard naming convention.
build/gencondmd.c: s-conditions; @true
s-conditions: $(MD_DEPS) build/genconditions$(build_exeext)
$(RUN_GEN) build/genconditions$(build_exeext) $(md_file) > tmp-condmd.c
$(SHELL) $(srcdir)/../move-if-change tmp-condmd.c build/gencondmd.c
$(STAMP) s-conditions
insn-conditions.md: s-condmd; @true
s-condmd: build/gencondmd$(build_exeext)
$(RUN_GEN) build/gencondmd$(build_exeext) > tmp-cond.md
$(SHELL) $(srcdir)/../move-if-change tmp-cond.md insn-conditions.md
$(STAMP) s-condmd
# These files are generated by running the same generator more than
# once with different options, so they have custom rules. The
# stampfile idiom is the same.
@ -2859,7 +2883,6 @@ build/%.o : # dependencies provided by explicit rule later
# Header dependencies for the programs that generate source code.
# These are library modules...
build/dummy-conditions.o : dummy-conditions.c
build/errors.o : errors.c $(BCONFIG_H) $(SYSTEM_H) errors.h
build/gensupport.o: gensupport.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
$(GTM_H) $(RTL_BASE_H) $(OBSTACK_H) errors.h $(HASHTAB_H) \
@ -2871,16 +2894,16 @@ build/min-insn-modes.o : min-insn-modes.c $(BCONFIG_H) $(SYSTEM_H) \
build/print-rtl.o: print-rtl.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
$(GTM_H) $(RTL_BASE_H)
build/read-rtl.o: read-rtl.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
$(GTM_H) $(RTL_BASE_H) $(OBSTACK_H) $(HASHTAB_H)
$(GTM_H) $(RTL_BASE_H) $(OBSTACK_H) $(HASHTAB_H) gensupport.h
build/rtl.o: rtl.c $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) \
$(RTL_H) real.h $(GGC_H) errors.h
build/varray.o: varray.c $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) \
$(VARRAY_H) $(RTL_BASE_H) $(GGC_H) $(TREE_H) bitmap.h errors.h
build/vec.o : vec.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) coretypes.h vec.h \
$(GGC_H) toplev.h
build/insn-conditions.o : insn-conditions.c $(CONFIG_H) $(SYSTEM_H) \
$(GTM_H) $(RTL_H) $(TM_P_H) $(REGS_H) $(FUNCTION_H) $(RECOG_H) real.h \
output.h $(FLAGS_H) hard-reg-set.h $(RESOURCE_H) toplev.h reload.h \
build/gencondmd.o : build/gencondmd.c $(CONFIG_H) $(SYSTEM_H) $(GTM_H) \
$(RTL_H) $(TM_P_H) $(REGS_H) $(FUNCTION_H) $(RECOG_H) real.h output.h \
$(FLAGS_H) hard-reg-set.h $(RESOURCE_H) toplev.h reload.h \
gensupport.h insn-constants.h coretypes.h
# ...these are the programs themselves.
@ -2942,15 +2965,16 @@ build/gen%$(build_exeext): build/gen%.o $(BUILD_LIBDEPS)
$(filter-out $(BUILD_LIBDEPS), $^) $(BUILD_LIBS)
# All these programs have the same additional dependency set.
genprognormal = attr codes config emit extract flags opinit output peep recog
genprognormal = attr codes config emit extract flags opinit output peep recog \
preds
$(genprognormal:%=build/gen%$(build_exeext)): $(BUILD_RTL) $(BUILD_SUPPORT) \
$(BUILD_PRINT) $(BUILD_ERRORS)
# And all of these, but it's a different set.
genprogearly = mddeps constants conditions preds
$(genprogearly:%=build/gen%$(build_exeext)): $(BUILD_RTL) $(BUILD_ERRORS) \
$(BUILD_EARLY_SUPPORT)
build/genpreds$(build_exeext) : $(BUILD_PRINT)
# These don't have the glue to link with print-rtl.o.
genprognoprint = mddeps constants conditions
$(genprognoprint:%=build/gen%$(build_exeext)): $(BUILD_RTL) $(BUILD_SUPPORT) \
$(BUILD_ERRORS)
build/gengenrtl$(build_exeext) : $(BUILD_ERRORS)
build/genmodes$(build_exeext) : $(BUILD_ERRORS)

View File

@ -1,42 +0,0 @@
/* Support for calculating constant conditions.
Copyright (C) 2002, 2004 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 2, 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 COPYING. If not, write to
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
#include <stddef.h> /* for size_t */
/* MD generators that are run before insn-conditions.c exists should
link against this file instead. Currently that is genconditions
and genconstants. */
/* In order to avoid dragging in all the headers that are needed to
declare things that gensupport.h uses, we duplicate the declaration
of struct c_test here. (In particular we do not want to have to
include tm.h nor rtl.h in this file.) */
struct c_test
{
const char *expr;
int value;
};
/* Empty conditions table to prevent link errors. */
const struct c_test insn_conditions[1] = { { 0, 0 } };
const size_t n_insn_conditions = 0;
/* Disable insn elision, since it is currently impossible. */
const int insn_elision_unavailable = 1;

View File

@ -38,31 +38,10 @@
/* so we can include except.h in the generated file. */
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 *);
/* Record the C test expression EXPR in the condition_table.
Duplicates clobber previous entries, which leaks memory, but
we don't care for this application. */
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;
}
/* Generate the header for insn-conditions.c. */
static void
@ -86,13 +65,6 @@ write_header (void)
puts ("\
#include \"system.h\"\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\
#if GCC_VERSION < 3001\n\
#include \"dummy-conditions.c\"\n\
#else\n\
#include \"coretypes.h\"\n\
#include \"tm.h\"\n\
#include \"rtl.h\"\n\
@ -172,15 +144,35 @@ write_conditions (void)
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[] = {");
static const struct c_test insn_conditions[] = {\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\
#if GCC_VERSION >= 3001");
htab_traverse (condition_table, write_one_condition, 0);
traverse_c_tests (write_one_condition, 0);
puts ("};\n");
puts ("#endif\n};\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");
/* 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\nmain(void)\n{\n\
unsigned int i;\n\
\n\
puts (\"(define_conditions [\");\n\
for (i = 0; i < ARRAY_SIZE (insn_conditions); i++)\n\
printf (\" (%d \\\"%s\\\")\\n\",\n\
insn_conditions[i].value, insn_conditions[i].expr);\n\
puts (\"])\");\n\
fflush (stdout);\n\
return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);\n}");
}
int
@ -195,10 +187,7 @@ main (int argc, char **argv)
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);
/* Read the machine description. */
while (1)
{
desc = read_md_rtx (&pattern_lineno, &code);
@ -214,7 +203,7 @@ main (int argc, char **argv)
case DEFINE_INSN:
case DEFINE_EXPAND:
add_condition (XSTR (desc, 2));
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"))
@ -224,13 +213,14 @@ main (int argc, char **argv)
case DEFINE_SPLIT:
case DEFINE_PEEPHOLE:
case DEFINE_PEEPHOLE2:
add_condition (XSTR (desc, 1));
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);

View File

@ -901,93 +901,148 @@ int
init_md_reader_args_cb (int argc, char **argv, bool (*parse_opt)(const char *))
{
FILE *input_file;
int i, lineno;
size_t ix;
int c, i, lineno;
char *lastsl;
rtx desc;
bool no_more_options;
bool already_read_stdin;
/* Unlock the stdio streams. */
unlock_std_streams ();
/* First we loop over all the options. */
for (i = 1; i < argc; i++)
{
if (argv[i][0] != '-')
continue;
c = argv[i][1];
switch (c)
{
if (in_fname)
fatal ("too many input files");
case 'I': /* Add directory to path for includes. */
{
struct file_name_list *dirtmp;
in_fname = argv[i];
}
else
{
int c = argv[i][1];
switch (c)
{
case 'I': /* Add directory to path for includes. */
{
struct file_name_list *dirtmp;
dirtmp = XNEW (struct file_name_list);
dirtmp->next = 0; /* New one goes on the end */
if (first_dir_md_include == 0)
first_dir_md_include = dirtmp;
else
last_dir_md_include->next = dirtmp;
last_dir_md_include = dirtmp; /* Tail follows the last one */
if (argv[i][1] == 'I' && argv[i][2] != 0)
dirtmp->fname = argv[i] + 2;
else if (i + 1 == argc)
fatal ("directory name missing after -I option");
else
dirtmp->fname = argv[++i];
if (strlen (dirtmp->fname) > max_include_len)
max_include_len = strlen (dirtmp->fname);
}
break;
dirtmp = XNEW (struct file_name_list);
dirtmp->next = 0; /* New one goes on the end */
if (first_dir_md_include == 0)
first_dir_md_include = dirtmp;
else
last_dir_md_include->next = dirtmp;
last_dir_md_include = dirtmp; /* Tail follows the last one */
if (argv[i][1] == 'I' && argv[i][2] != 0)
dirtmp->fname = argv[i] + 2;
else if (i + 1 == argc)
fatal ("directory name missing after -I option");
else
dirtmp->fname = argv[++i];
if (strlen (dirtmp->fname) > max_include_len)
max_include_len = strlen (dirtmp->fname);
}
break;
default:
/* The program may have provided a callback so it can
accept its own options. */
if (parse_opt && parse_opt (argv[i]))
break;
case '\0':
/* An argument consisting of exactly one dash is a request to
read stdin. This will be handled in the second loop. */
continue;
fatal ("invalid option `%s'", argv[i]);
}
case '-':
/* An argument consisting of just two dashes causes option
parsing to cease. */
if (argv[i][2] == '\0')
goto stop_parsing_options;
default:
/* The program may have provided a callback so it can
accept its own options. */
if (parse_opt && parse_opt (argv[i]))
break;
fatal ("invalid option `%s'", argv[i]);
}
}
if (!in_fname)
fatal ("no input file name");
lastsl = strrchr (in_fname, '/');
if (lastsl != NULL)
base_dir = save_string (in_fname, lastsl - in_fname + 1 );
read_rtx_filename = in_fname;
input_file = fopen (in_fname, "r");
if (input_file == 0)
{
perror (in_fname);
return FATAL_EXIT_CODE;
}
/* Initialize the table of insn conditions. */
condition_table = htab_create (n_insn_conditions,
hash_c_test, cmp_c_test, NULL);
for (ix = 0; ix < n_insn_conditions; ix++)
*(htab_find_slot (condition_table, &insn_conditions[ix], INSERT))
= (void *) &insn_conditions[ix];
stop_parsing_options:
/* Prepare to read input. */
condition_table = htab_create (500, hash_c_test, cmp_c_test, NULL);
init_predicate_table ();
obstack_init (rtl_obstack);
errors = 0;
sequence_num = 0;
no_more_options = false;
already_read_stdin = false;
/* Read the entire file. */
while (read_rtx (input_file, &desc, &lineno))
process_rtx (desc, lineno);
fclose (input_file);
/* Now loop over all input files. */
for (i = 1; i < argc; i++)
{
if (argv[i][0] == '-')
{
if (argv[i][1] == '\0')
{
/* Read stdin. */
if (already_read_stdin)
fatal ("cannot read standard input twice");
base_dir = NULL;
read_rtx_filename = in_fname = "<stdin>";
read_rtx_lineno = 1;
input_file = stdin;
already_read_stdin = true;
while (read_rtx (input_file, &desc, &lineno))
process_rtx (desc, lineno);
fclose (input_file);
continue;
}
else if (argv[i][1] == '-' && argv[i][2] == '\0')
{
/* No further arguments are to be treated as options. */
no_more_options = true;
continue;
}
else if (!no_more_options)
continue;
}
/* If we get here we are looking at a non-option argument, i.e.
a file to be processed. */
in_fname = argv[i];
lastsl = strrchr (in_fname, '/');
if (lastsl != NULL)
base_dir = save_string (in_fname, lastsl - in_fname + 1 );
else
base_dir = NULL;
read_rtx_filename = in_fname;
read_rtx_lineno = 1;
input_file = fopen (in_fname, "r");
if (input_file == 0)
{
perror (in_fname);
return FATAL_EXIT_CODE;
}
while (read_rtx (input_file, &desc, &lineno))
process_rtx (desc, lineno);
fclose (input_file);
}
/* If we get to this point without having seen any files to process,
read standard input now. */
if (!in_fname)
{
base_dir = NULL;
read_rtx_filename = in_fname = "<stdin>";
read_rtx_lineno = 1;
input_file = stdin;
while (read_rtx (input_file, &desc, &lineno))
process_rtx (desc, lineno);
fclose (input_file);
}
/* Process define_cond_exec patterns. */
if (define_cond_exec_queue != NULL)
@ -1119,16 +1174,41 @@ maybe_eval_c_test (const char *expr)
if (expr[0] == 0)
return 1;
if (insn_elision_unavailable)
return -1;
dummy.expr = expr;
test = (const struct c_test *)htab_find (condition_table, &dummy);
gcc_assert (test);
if (!test)
return -1;
return test->value;
}
/* Record the C test expression EXPR in the condition_table, with
value VAL. Duplicates clobber previous entries. */
void
add_c_test (const char *expr, int value)
{
struct c_test *test;
if (expr[0] == 0)
return;
test = XNEW (struct c_test);
test->expr = expr;
test->value = value;
*(htab_find_slot (condition_table, test, INSERT)) = test;
}
/* For every C test, call CALLBACK with two arguments: a pointer to
the condition structure and INFO. Stops when CALLBACK returns zero. */
void
traverse_c_tests (htab_trav callback, void *info)
{
if (condition_table)
htab_traverse (condition_table, callback, info);
}
/* Given a string, return the number of comma-separated elements in it.
Return 0 for the null string. */
int

View File

@ -37,31 +37,27 @@ extern void message_with_line (int, const char *, ...)
Must be set before calling init_md_reader. */
extern int insn_elision;
/* If this is 1, the insn elision table doesn't even exist yet;
maybe_eval_c_test will always return -1. This is distinct from
insn_elision because genflags and gencodes need to see all the
patterns, but treat elided patterns differently. */
extern const int insn_elision_unavailable;
/* If the C test passed as the argument can be evaluated at compile
time, return its truth value; else return -1. The test must have
appeared somewhere in the machine description when genconditions
was run. */
extern int maybe_eval_c_test (const char *);
/* This table should not be accessed directly; use maybe_eval_c_test. */
/* Add an entry to the table of conditions. Used by genconditions and
by read-rtl.c. */
extern void add_c_test (const char *, int);
/* This structure is used internally by gensupport.c and genconditions.c. */
struct c_test
{
const char *expr;
int value;
};
extern const struct c_test insn_conditions[];
extern const size_t n_insn_conditions;
#ifdef __HASHTAB_H__
extern hashval_t hash_c_test (const void *);
extern int cmp_c_test (const void *, const void *);
extern void traverse_c_tests (htab_trav, void *);
#endif
extern int n_comma_elts (const char *);

View File

@ -31,6 +31,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "rtl.h"
#include "obstack.h"
#include "hashtab.h"
#include "gensupport.h"
static htab_t md_constants;
@ -138,6 +139,7 @@ static void read_escape (FILE *);
static hashval_t def_hash (const void *);
static int def_name_eq_p (const void *, const void *);
static void read_constants (FILE *infile, char *tmp_char);
static void read_conditions (FILE *infile, char *tmp_char);
static void validate_const_int (FILE *, const char *);
static int find_macro (struct macro_group *, const char *, FILE *);
static struct mapping *read_mapping (struct macro_group *, htab_t, FILE *);
@ -1205,6 +1207,58 @@ traverse_md_constants (htab_trav callback, void *info)
if (md_constants)
htab_traverse (md_constants, callback, info);
}
/* INFILE is a FILE pointer to read text from. TMP_CHAR is a buffer
suitable to read a name or number into. Process a
define_conditions directive, starting with the optional space after
the "define_conditions". The directive looks like this:
(define_conditions [
(number "string")
(number "string")
...
])
It's not intended to appear in machine descriptions. It is
generated by (the program generated by) genconditions.c, and
slipped in at the beginning of the sequence of MD files read by
most of the other generators. */
static void
read_conditions (FILE *infile, char *tmp_char)
{
int c;
c = read_skip_spaces (infile);
if (c != '[')
fatal_expected_char (infile, '[', c);
while ( (c = read_skip_spaces (infile)) != ']')
{
char *expr;
int value;
if (c != '(')
fatal_expected_char (infile, '(', c);
read_name (tmp_char, infile);
validate_const_int (infile, tmp_char);
value = atoi (tmp_char);
c = read_skip_spaces (infile);
if (c != '"')
fatal_expected_char (infile, '"', c);
expr = read_quoted_string (infile);
c = read_skip_spaces (infile);
if (c != ')')
fatal_expected_char (infile, ')', c);
add_c_test (expr, value);
}
c = read_skip_spaces (infile);
if (c != ')')
fatal_expected_char (infile, ')', c);
}
static void
validate_const_int (FILE *infile, const char *string)
@ -1354,16 +1408,23 @@ read_rtx (FILE *infile, rtx *x, int *lineno)
{
struct map_value *mode_maps;
struct macro_traverse_data mtd;
rtx from_file;
c = read_skip_spaces (infile);
if (c == EOF)
return false;
ungetc (c, infile);
queue_next = queue_head;
queue_lineno = read_rtx_lineno;
mode_maps = 0;
XEXP (queue_next, 0) = read_rtx_1 (infile, &mode_maps);
from_file = read_rtx_1 (infile, &mode_maps);
if (from_file == 0)
return false; /* This confuses a top level (nil) with end of
file, but a top level (nil) would have
crashed our caller anyway. */
queue_next = queue_head;
XEXP (queue_next, 0) = from_file;
XEXP (queue_next, 1) = 0;
mtd.queue = queue_next;
@ -1412,6 +1473,10 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps)
again:
c = read_skip_spaces (infile); /* Should be open paren. */
if (c == EOF)
return 0;
if (c != '(')
fatal_expected_char (infile, '(', c);
@ -1429,6 +1494,11 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps)
read_constants (infile, tmp_char);
goto again;
}
if (strcmp (tmp_char, "define_conditions") == 0)
{
read_conditions (infile, tmp_char);
goto again;
}
if (strcmp (tmp_char, "define_mode_attr") == 0)
{
read_mapping (&modes, modes.attrs, infile);