summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog37
-rw-r--r--gcc/Makefile.in4
-rw-r--r--gcc/genmodes.c244
-rw-r--r--gcc/machmode.def19
-rw-r--r--gcc/machmode.h7
-rw-r--r--gcc/toplev.c2
6 files changed, 260 insertions, 53 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 41b0ead0728..632cc39d1d1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,8 +1,35 @@
+2003-10-15 Zack Weinberg <zack@codesourcery.com>
+
+ * genmodes.c: Include hashtab.h.
+ (modes_by_name, hash_mode, eq_mode, struct mode_adjust)
+ (adj_bytesize, adj_alignment, adj_format, new_adjust)
+ (_ADD_ADJUST, ADJUST_BYTESIZE, ADJUST_ALIGNMENT, ADJUST_FORMAT)
+ (print_maybe_const_decl, emit_mode_adjustments): New.
+ (known_modes): Rename to modes.
+ (find_mode): Kill class argument; look up in hash table.
+ (new_mode): Insert into hash table also.
+ (new_adjust): New.
+ (reset_float_format, make_partial_integer_mode)
+ (make_vector_mode): Tweak error reporting.
+ (reset_float_format): Correct type of fourth argument.
+ (emit_insn_modes_h): Add #defines to help make mode_size,
+ mode_base_align, and real_format_for_mode conditionally const.
+ (emit_mode_size, emit_mode_base_align): Use print_maybe_const_decl.
+ (emit_real_format_for_mode): Likewise, but temporarily disabled.
+ (emit_insn_modes_c): Call emit_mode_adjustments.
+ (main): Initialize modes_by_name.
+ * Makefile.in: Update dependencies.
+ * machmode.def: Document EXPR arguments and new ADJUST_* statements.
+ * machmode.h: Use CONST_MODE_SIZE and CONST_MODE_BASE_ALIGN in
+ declarations of mode_size and mode_base_align. Declare
+ init_adjust_machine_modes.
+ * toplev.c (backend_init): Call init_adjust_machine_modes.
+
2003-10-15 Olivier Hainque <hainque@act-europe.fr>
* genmodes.c (calc_wider_mode): Allocate enough room for all the
entries we'll possibly assign in the sort buffer.
-
+
2003-10-15 Ulrich Weigand <uweigand@de.ibm.com>
* config.gcc (s390x-ibm-tpf*): New target.
@@ -50,13 +77,13 @@
New functions.
* config/s390/s390.h (PREDICATE_CODES): Add s390_alc_comparison
and s390_slb_comparison.
- * config/s390/s390.md ("*adddi3_31", "*subdi3_31"): Do not use on
+ * config/s390/s390.md ("*adddi3_31", "*subdi3_31"): Do not use on
zSeries machines.
("*adddi3_31z", "*subdi3_31z"): New insns.
("*adddi3_alc_cc", "*adddi3_alc", "*subdi3_slb_cc", "*subdi3_slb",
"*addsi3_alc_cc", "*addsi3_alc", "*subsi3_slb_cc", "*subsi3_slb"):
New insns.
-
+
2003-10-14 Nathanael Nerode <neroden@gcc.gnu.org>
* configure.in: Clean up some feedback echoes.
@@ -76,7 +103,7 @@
* config/s390/s390.md ("muldf3", "*muldf3", "*muldf3_ibm",
"mulsf3", "*mulsf3", "*mulsf3_ibm"): Do not clobber CC.
- ("divdf3", "*divdf3", "*divdf3_ibm", "divsf3", "*divsf3",
+ ("divdf3", "*divdf3", "*divdf3_ibm", "divsf3", "*divsf3",
"*divsf3_ibm"): Likewise.
2003-10-14 Nathanael Nerode <neroden@gcc.gnu.org>
@@ -103,7 +130,7 @@
* fixinc/inclhack.def (alpha_pthread_gcc): New fix.
* fixinc/fixincl.x: Regenerate.
* fixinc/tests/base/pthread.h [ALPHA_PTHREAD_GCC_CHECK]: New
- testcase.
+ testcase.
Fixes PR bootstrap/9330.
2003-10-13 Eric Christopher <echristo@redhat.com>
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 944a5cd73a3..a05808d6fae 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2198,8 +2198,8 @@ genmodes$(build_exeext) : genmodes.o $(BUILD_ERRORS) $(BUILD_LIBDEPS)
$(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \
genmodes.o $(BUILD_ERRORS) $(BUILD_LIBS)
-genmodes.o : genmodes.c $(BCONFIG_H) $(SYSTEM_H) errors.h machmode.def \
- $(extra_modes_file)
+genmodes.o : genmodes.c $(BCONFIG_H) $(SYSTEM_H) errors.h $(HASHTAB_H) \
+ machmode.def $(extra_modes_file)
genpreds$(build_exeext) : genpreds.o $(BUILD_LIBDEPS)
$(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \
diff --git a/gcc/genmodes.c b/gcc/genmodes.c
index 127392cf5a5..6d32d708d62 100644
--- a/gcc/genmodes.c
+++ b/gcc/genmodes.c
@@ -22,6 +22,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "bconfig.h"
#include "system.h"
#include "errors.h"
+#include "hashtab.h"
/* enum mode_class is normally defined by machmode.h but we can't
include that header here. */
@@ -68,7 +69,7 @@ struct mode_data
unsigned int line; /* for error reporting */
};
-static struct mode_data *known_modes[MAX_MODE_CLASS];
+static struct mode_data *modes[MAX_MODE_CLASS];
static unsigned int n_modes[MAX_MODE_CLASS];
static struct mode_data *void_mode;
@@ -79,6 +80,25 @@ static const struct mode_data blank_mode = {
"<unknown>", 0
};
+static htab_t modes_by_name;
+
+/* Data structure for recording target-specified runtime adjustments
+ to a particular mode. We support varying the byte size, the
+ alignment, and the floating point format. */
+struct mode_adjust
+{
+ struct mode_adjust *next;
+ struct mode_data *mode;
+ const char *adjustment;
+
+ const char *file;
+ unsigned int line;
+};
+
+static struct mode_adjust *adj_bytesize;
+static struct mode_adjust *adj_alignment;
+static struct mode_adjust *adj_format;
+
/* Mode class operations. */
static enum mode_class
complex_class (enum mode_class class)
@@ -106,16 +126,14 @@ vector_class (enum mode_class class)
}
}
-static struct mode_data *
-find_mode (enum mode_class class, const char *name)
+/* Utility routines. */
+static inline struct mode_data *
+find_mode (const char *name)
{
- struct mode_data *m;
+ struct mode_data key;
- for (m = known_modes[class]; m; m = m->next)
- if (!strcmp (name, m->name))
- return m;
-
- return 0;
+ key.name = name;
+ return htab_find (modes_by_name, &key);
}
static struct mode_data *
@@ -124,7 +142,7 @@ new_mode (enum mode_class class, const char *name,
{
struct mode_data *m;
- m = find_mode (class, name);
+ m = find_mode (name);
if (m)
{
error ("%s:%d: duplicate definition of mode \"%s\"",
@@ -141,16 +159,79 @@ new_mode (enum mode_class class, const char *name,
m->file = trim_filename (file);
m->line = line;
- m->next = known_modes[class];
- known_modes[class] = m;
+ m->next = modes[class];
+ modes[class] = m;
n_modes[class]++;
+
+ *htab_find_slot (modes_by_name, m, INSERT) = m;
+
return m;
}
+static hashval_t
+hash_mode (const void *p)
+{
+ const struct mode_data *m = (const struct mode_data *)p;
+ return htab_hash_string (m->name);
+}
+
+static int
+eq_mode (const void *p, const void *q)
+{
+ const struct mode_data *a = (const struct mode_data *)p;
+ const struct mode_data *b = (const struct mode_data *)q;
+
+ return !strcmp (a->name, b->name);
+}
+
#define for_all_modes(C, M) \
for (C = 0; C < MAX_MODE_CLASS; C++) \
- for (M = known_modes[C]; M; M = M->next)
+ for (M = modes[C]; M; M = M->next)
+
+static void ATTRIBUTE_UNUSED
+new_adjust (const char *name,
+ struct mode_adjust **category, const char *catname,
+ const char *adjustment,
+ enum mode_class required_class,
+ const char *file, unsigned int line)
+{
+ struct mode_data *mode = find_mode (name);
+ struct mode_adjust *a;
+
+ file = trim_filename (file);
+
+ if (!mode)
+ {
+ error ("%s:%d: no mode \"%s\"", file, line, name);
+ return;
+ }
+
+ if (required_class != MODE_RANDOM && mode->class != required_class)
+ {
+ error ("%s:%d: mode \"%s\" is not class %s",
+ file, line, name, mode_class_names[required_class] + 5);
+ return;
+ }
+
+ for (a = *category; a; a = a->next)
+ if (a->mode == mode)
+ {
+ error ("%s:%d: mode \"%s\" already has a %s adjustment",
+ file, line, name, catname);
+ error ("%s:%d: previous adjustment here", a->file, a->line);
+ return;
+ }
+
+ a = xmalloc (sizeof (struct mode_adjust));
+ a->mode = mode;
+ a->adjustment = adjustment;
+ a->file = file;
+ a->line = line;
+
+ a->next = *category;
+ *category = a;
+}
/* Diagnose failure to meet expectations in a partially filled out
mode structure. */
@@ -318,7 +399,7 @@ make_complex_modes (enum mode_class class,
if (cclass == MODE_RANDOM)
return;
- for (m = known_modes[class]; m; m = m->next)
+ for (m = modes[class]; m; m = m->next)
{
/* Skip BImode. FIXME: BImode probably shouldn't be MODE_INT. */
if (m->bitsize == 1)
@@ -372,7 +453,7 @@ make_vector_modes (enum mode_class class, unsigned int width,
if (vclass == MODE_RANDOM)
return;
- for (m = known_modes[class]; m; m = m->next)
+ for (m = modes[class]; m; m = m->next)
{
/* Do not construct vector modes with only one element, or
vector modes where the element size doesn't divide the full
@@ -451,12 +532,17 @@ make_float_mode (const char *name,
reset_float_format (#N, #F, __FILE__, __LINE__)
static void ATTRIBUTE_UNUSED
reset_float_format (const char *name, const char *format,
- const char *file, const char *line)
+ const char *file, unsigned int line)
{
- struct mode_data *m = find_mode (MODE_FLOAT, name);
+ struct mode_data *m = find_mode (name);
if (!m)
{
- error ("%s:%d: no mode \"%s\" in class FLOAT", file, line, name);
+ error ("%s:%d: no mode \"%s\"", file, line, name);
+ return;
+ }
+ if (m->class != MODE_FLOAT)
+ {
+ error ("%s:%d: mode \"%s\" is not class FLOAT", file, line, name);
return;
}
m->format = format;
@@ -472,10 +558,15 @@ make_partial_integer_mode (const char *base, const char *name,
const char *file, unsigned int line)
{
struct mode_data *m;
- struct mode_data *component = find_mode (MODE_INT, base);
+ struct mode_data *component = find_mode (base);
if (!component)
{
- error ("%s:%d: no mode \"%s\" in class INT", file, line, name);
+ error ("%s:%d: no mode \"%s\"", file, line, name);
+ return;
+ }
+ if (component->class != MODE_INT)
+ {
+ error ("%s:%d: mode \"%s\" is not class INT", file, line, name);
return;
}
@@ -496,14 +587,19 @@ make_vector_mode (enum mode_class bclass,
{
struct mode_data *v;
enum mode_class vclass = vector_class (bclass);
- struct mode_data *component = find_mode (bclass, base);
+ struct mode_data *component = find_mode (base);
char namebuf[8];
if (vclass == MODE_RANDOM)
return;
if (component == 0)
{
- error ("%s:%d: no mode \"%s\" in class %s",
+ error ("%s:%d: no mode \"%s\"", file, line, base);
+ return;
+ }
+ if (component->class != bclass)
+ {
+ error ("%s:%d: mode \"%s\" is not class %s",
file, line, base, mode_class_names[bclass] + 5);
return;
}
@@ -520,7 +616,14 @@ make_vector_mode (enum mode_class bclass,
v->ncomponents = ncomponents;
v->component = component;
}
-
+
+/* Adjustability. */
+#define _ADD_ADJUST(A, M, X, C) \
+ new_adjust (#M, &adj_##A, #A, #X, MODE_##C, __FILE__, __LINE__)
+
+#define ADJUST_BYTESIZE(M, X) _ADD_ADJUST(bytesize, M, X, RANDOM)
+#define ADJUST_ALIGNMENT(M, X) _ADD_ADJUST(alignment, M, X, RANDOM)
+#define ADJUST_FLOAT_FORMAT(M, X) _ADD_ADJUST(format, M, X, FLOAT)
static void
create_modes (void)
@@ -600,7 +703,7 @@ calc_wider_mode (void)
{
struct mode_data *prev, *next;
- for (prev = 0, m = known_modes[c]; m; m = next)
+ for (prev = 0, m = modes[c]; m; m = next)
{
m->wider = void_mode;
@@ -609,14 +712,14 @@ calc_wider_mode (void)
m->next = prev;
prev = m;
}
- known_modes[c] = prev;
+ modes[c] = prev;
}
else
{
- if (!known_modes[c])
+ if (!modes[c])
continue;
- for (i = 0, m = known_modes[c]; m; i++, m = m->next)
+ for (i = 0, m = modes[c]; m; i++, m = m->next)
sortbuf[i] = m;
qsort (sortbuf, i, sizeof (struct mode_data *), cmp_modes);
@@ -626,7 +729,7 @@ calc_wider_mode (void)
sortbuf[j]->next = sortbuf[j]->wider = sortbuf[j + 1];
- known_modes[c] = sortbuf[0];
+ modes[c] = sortbuf[0];
}
}
}
@@ -640,7 +743,11 @@ calc_wider_mode (void)
} while (0)
#define print_decl(TYPE, NAME, ASIZE) \
- printf ("\nconst %s %s[%s] =\n{\n", TYPE, NAME, ASIZE);
+ puts ("\nconst " TYPE " " NAME "[" ASIZE "] =\n{");
+
+#define print_maybe_const_decl(TYPE, NAME, ASIZE, CATEGORY) \
+ printf ("\n" TYPE " " NAME "[" ASIZE "] = \n{\n", \
+ adj_##CATEGORY ? "" : "const ")
#define print_closer() puts ("};")
@@ -663,7 +770,7 @@ emit_insn_modes_h (void)
enum machine_mode\n{");
for (c = 0; c < MAX_MODE_CLASS; c++)
- for (m = known_modes[c]; m; m = m->next)
+ for (m = modes[c]; m; m = m->next)
{
int count_;
printf (" %smode,%n", m->name, &count_);
@@ -675,7 +782,7 @@ enum machine_mode\n{");
for (c = 0; c < MAX_MODE_CLASS; c++)
{
- first = known_modes[c];
+ first = modes[c];
last = 0;
for (m = first; m; last = m, m = m->next)
;
@@ -699,7 +806,15 @@ enum machine_mode\n{");
puts ("\
NUM_MACHINE_MODES = MAX_MACHINE_MODE\n\
-};\n\
+};\n");
+
+ /* I can't think of a better idea, can you? */
+ printf ("#define CONST_MODE_SIZE%s\n", adj_bytesize ? "" : " const");
+ printf ("#define CONST_MODE_BASE_ALIGN%s\n", adj_alignment ? "" : " const");
+#if 0 /* disabled for backward compatibility, temporary */
+ printf ("#define CONST_REAL_FORMAT_FOR_MODE%s\n", adj_format ? "" :" const");
+#endif
+ puts ("\
\n\
#endif /* insn-modes.h */");
}
@@ -788,7 +903,8 @@ emit_mode_size (void)
enum mode_class c;
struct mode_data *m;
- print_decl ("unsigned char", "mode_size", "NUM_MACHINE_MODES");
+ print_maybe_const_decl ("%sunsigned char", "mode_size",
+ "NUM_MACHINE_MODES", bytesize);
for_all_modes (c, m)
tagged_printf ("%u", m->bytesize, m->name);
@@ -875,7 +991,9 @@ emit_mode_base_align (void)
enum mode_class c;
struct mode_data *m;
- print_decl ("unsigned char", "mode_base_align", "NUM_MACHINE_MODES");
+ print_maybe_const_decl ("%sunsigned char",
+ "mode_base_align", "NUM_MACHINE_MODES",
+ alignment);
for_all_modes (c, m)
tagged_printf ("%u", m->alignment, m->name);
@@ -893,11 +1011,11 @@ emit_class_narrowest_mode (void)
for (c = 0; c < MAX_MODE_CLASS; c++)
/* Bleah, all this to get the comment right for MIN_MODE_INT. */
tagged_printf ("MIN_%s", mode_class_names[c],
- known_modes[c]
- ? (known_modes[c]->bitsize != 1
- ? known_modes[c]->name
- : (known_modes[c]->next
- ? known_modes[c]->next->name
+ modes[c]
+ ? (modes[c]->bitsize != 1
+ ? modes[c]->name
+ : (modes[c]->next
+ ? modes[c]->next->name
: void_mode->name))
: void_mode->name);
@@ -909,12 +1027,23 @@ emit_real_format_for_mode (void)
{
struct mode_data *m;
- /* This will produce a table which is not constant, but points to
- entities that are constant, which is what we want. */
- print_decl ("struct real_format *\n ", "real_format_for_mode",
+ /* The entities pointed to by this table are constant, whether
+ or not the table itself is constant.
+
+ For backward compatibility this table is always writable
+ (several targets modify it in OVERRIDE_OPTIONS). FIXME:
+ convert all said targets to use ADJUST_FORMAT instead. */
+#if 0
+ print_maybe_const_decl ("const struct real_format *%s",
+ "real_format_for_mode",
+ "MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1",
+ format);
+#else
+ print_decl ("struct real_format *\n", "real_format_for_mode",
"MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1");
+#endif
- for (m = known_modes[MODE_FLOAT]; m; m = m->next)
+ for (m = modes[MODE_FLOAT]; m; m = m->next)
if (!strcmp (m->format, "0"))
tagged_printf ("%s", m->format, m->name);
else
@@ -924,6 +1053,32 @@ emit_real_format_for_mode (void)
}
static void
+emit_mode_adjustments (void)
+{
+ struct mode_adjust *a;
+
+ puts ("\nvoid\ninit_adjust_machine_modes (void)\n{");
+
+ for (a = adj_bytesize; a; a = a->next)
+ printf (" /* %s:%d */\n mode_size[%smode] = %s;\n",
+ a->file, a->line, a->mode->name, a->adjustment);
+ if (adj_bytesize && (adj_alignment || adj_format))
+ putchar ('\n');
+
+ for (a = adj_alignment; a; a = a->next)
+ printf (" /* %s:%d */\n mode_base_align[%smode] = %s;\n",
+ a->file, a->line, a->mode->name, a->adjustment);
+ if (adj_alignment && adj_format)
+ putchar ('\n');
+
+ for (a = adj_format; a; a = a->next)
+ printf (" /* %s:%d */\n REAL_MODE_FORMAT (%smode) = %s;\n",
+ a->file, a->line, a->mode->name, a->adjustment);
+
+ puts ("}");
+}
+
+static void
emit_insn_modes_c (void)
{
emit_insn_modes_c_header ();
@@ -938,6 +1093,7 @@ emit_insn_modes_c (void)
emit_mode_base_align ();
emit_class_narrowest_mode ();
emit_real_format_for_mode ();
+ emit_mode_adjustments ();
}
static void
@@ -969,6 +1125,8 @@ main(int argc, char **argv)
return FATAL_EXIT_CODE;
}
+ modes_by_name = htab_create_alloc (64, hash_mode, eq_mode, 0, xcalloc, free);
+
create_modes ();
complete_all_modes ();
diff --git a/gcc/machmode.def b/gcc/machmode.def
index 72b1ec83644..0b762497d00 100644
--- a/gcc/machmode.def
+++ b/gcc/machmode.def
@@ -51,7 +51,13 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
constant.
A FORMAT argument must be one of the real_mode_format structures
- declared in real.h, or else a literal 0.
+ declared in real.h, or else a literal 0. Do not put a leading &
+ on the argument.
+
+ An EXPR argument must be a syntactically valid C expression.
+ If an EXPR contains commas, you may need to write an extra pair of
+ parentheses around it, so it appears to be a single argument to the
+ statement.
This file defines only those modes which are of use on almost all
machines. Other modes can be defined in the target-specific
@@ -120,6 +126,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
error if there is no 'F'. For INT modes, the names are
derived by prefixing a C to the name.
+ ADJUST_BYTESIZE (MODE, EXPR);
+ ADJUST_ALIGNMENT (MODE, EXPR);
+ ADJUST_FLOAT_FORMAT (MODE, EXPR);
+ Arrange for the byte size, alignment, or floating point format
+ of MODE to be adjustable at run time. EXPR will be executed
+ once after processing all command line options, and should
+ evaluate to the desired byte size, alignment, or format.
+
+ Unlike a FORMAT argument, if you are adjusting a float format
+ you must put an & in front of the name of each format structure.
+
Note: If a mode is ever made which is more than 255 bytes wide,
machmode.h and genmodes.c will have to be changed to allocate
more space for the mode_size and mode_alignment arrays. */
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 04b2de16753..c8c63c7a9e4 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -78,7 +78,7 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES];
/* Get the size in bytes of an object of mode MODE. */
-extern const unsigned char mode_size[NUM_MACHINE_MODES];
+extern CONST_MODE_SIZE unsigned char mode_size[NUM_MACHINE_MODES];
#define GET_MODE_SIZE(MODE) mode_size[MODE]
/* Get the size in bytes of the basic parts of an object of mode MODE. */
@@ -139,7 +139,7 @@ extern enum machine_mode get_best_mode (int, int, unsigned int,
/* Determine alignment, 1<=result<=BIGGEST_ALIGNMENT. */
-extern const unsigned char mode_base_align[NUM_MACHINE_MODES];
+extern CONST_MODE_BASE_ALIGN unsigned char mode_base_align[NUM_MACHINE_MODES];
extern unsigned get_mode_alignment (enum machine_mode);
@@ -157,4 +157,7 @@ extern enum machine_mode byte_mode;
extern enum machine_mode word_mode;
extern enum machine_mode ptr_mode;
+/* Target-dependent machine mode initialization - in insn-modes.c. */
+extern void init_adjust_machine_modes (void);
+
#endif /* not HAVE_MACHINE_MODES */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 797a9908360..e711135476a 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -4365,6 +4365,8 @@ process_options (void)
static void
backend_init (void)
{
+ init_adjust_machine_modes ();
+
init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE
#ifdef VMS_DEBUGGING_INFO