summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/c-common.c76
-rw-r--r--gcc/config/alpha/alpha.c42
-rw-r--r--gcc/doc/tm.texi12
-rw-r--r--gcc/expr.c2
-rw-r--r--gcc/target-def.h5
-rw-r--r--gcc/target.h9
-rw-r--r--gcc/targhooks.c47
-rw-r--r--gcc/targhooks.h2
9 files changed, 174 insertions, 36 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 36363d1148e..43d00b5fd39 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,20 @@
2004-08-25 Richard Henderson <rth@redhat.com>
+ * target-def.h (TARGET_SCALAR_MODE_SUPPORTED_P): New.
+ * target.h (struct gcc_target): Add scalar_mode_supported_p.
+ * targhooks.c (default_scalar_mode_supported_p): New.
+ * targhooks.h (default_scalar_mode_supported_p): Declare.
+ * doc/tm.texi (TARGET_SCALAR_MODE_SUPPORTED_P): Document.
+
+ * c-common.c (handle_mode_attribute): Query scalar_mode_supported_p
+ before attempting to create types. Tidy.
+ * expr.c (vector_mode_valid_p): Use scalar_mode_supported_p.
+
+ * config/alpha/alpha.c (alpha_scalar_mode_supported_p): New.
+ (TARGET_SCALAR_MODE_SUPPORTED_P): New.
+
+2004-08-25 Richard Henderson <rth@redhat.com>
+
* config/i386/freebsd.h (SUBTARGET_OVERRIDE_OPTIONS): Don't
set REAL_MODE_FORMAT for TFmode.
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 62d2231587f..7e691660ac4 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -4267,7 +4267,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
int len = strlen (p);
enum machine_mode mode = VOIDmode;
tree typefm;
- tree ptr_type;
+ bool valid_mode;
if (len > 4 && p[0] == '_' && p[1] == '_'
&& p[len - 1] == '_' && p[len - 2] == '_')
@@ -4294,51 +4294,67 @@ handle_mode_attribute (tree *node, tree name, tree args,
if (mode == VOIDmode)
{
- error ("unknown machine mode `%s'", p);
+ error ("unknown machine mode %<%s%>", p);
return NULL_TREE;
}
- if (VECTOR_MODE_P (mode))
+ valid_mode = false;
+ switch (GET_MODE_CLASS (mode))
{
+ case MODE_INT:
+ case MODE_PARTIAL_INT:
+ case MODE_FLOAT:
+ valid_mode = targetm.scalar_mode_supported_p (mode);
+ break;
+
+ case MODE_COMPLEX_INT:
+ case MODE_COMPLEX_FLOAT:
+ valid_mode = targetm.scalar_mode_supported_p (GET_MODE_INNER (mode));
+ break;
+
+ case MODE_VECTOR_INT:
+ case MODE_VECTOR_FLOAT:
warning ("specifying vector types with __attribute__ ((mode)) "
"is deprecated");
warning ("use __attribute__ ((vector_size)) instead");
- }
+ valid_mode = vector_mode_valid_p (mode);
+ break;
- typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type));
- if (typefm == NULL_TREE)
- error ("no data type for mode `%s'", p);
+ default:
+ break;
+ }
+ if (!valid_mode)
+ {
+ error ("unable to emulate %<%s%>", p);
+ return NULL_TREE;
+ }
- else if ((TREE_CODE (type) == POINTER_TYPE
- || TREE_CODE (type) == REFERENCE_TYPE)
- && !targetm.valid_pointer_mode (mode))
- error ("invalid pointer mode `%s'", p);
- else
+ if (POINTER_TYPE_P (type))
{
- /* If this is a vector, make sure we either have hardware
- support, or we can emulate it. */
- if (VECTOR_MODE_P (mode) && !vector_mode_valid_p (mode))
+ tree (*fn)(tree, enum machine_mode, bool);
+
+ if (!targetm.valid_pointer_mode (mode))
{
- error ("unable to emulate '%s'", GET_MODE_NAME (mode));
+ error ("invalid pointer mode %<%s%>", p);
return NULL_TREE;
}
- if (TREE_CODE (type) == POINTER_TYPE)
- {
- ptr_type = build_pointer_type_for_mode (TREE_TYPE (type),
- mode, false);
- *node = ptr_type;
- }
- else if (TREE_CODE (type) == REFERENCE_TYPE)
- {
- ptr_type = build_reference_type_for_mode (TREE_TYPE (type),
- mode, false);
- *node = ptr_type;
- }
+ if (TREE_CODE (type) == POINTER_TYPE)
+ fn = build_pointer_type_for_mode;
else
- *node = typefm;
- /* No need to layout the type here. The caller should do this. */
+ fn = build_reference_type_for_mode;
+ typefm = fn (TREE_TYPE (type), mode, false);
}
+ else
+ typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type));
+ if (typefm == NULL_TREE)
+ {
+ error ("no data type for mode %<%s%>", p);
+ return NULL_TREE;
+ }
+ *node = typefm;
+
+ /* No need to layout the type here. The caller should do this. */
}
return NULL_TREE;
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index c623e009fb1..c6d93446a84 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -670,14 +670,45 @@ alpha_extra_constraint (rtx value, int c)
}
}
-/* Implements target hook vector_mode_supported_p. */
+/* The scalar modes supported differs from the default check-what-c-supports
+ version in that sometimes TFmode is available even when long double
+ indicates only DFmode. On unicosmk, we have the situation that HImode
+ doesn't map to any C type, but of course we still support that. */
+
+static bool
+alpha_scalar_mode_supported_p (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case QImode:
+ case HImode:
+ case SImode:
+ case DImode:
+ case TImode: /* via optabs.c */
+ return true;
+
+ case SFmode:
+ case DFmode:
+ return true;
+
+ case TFmode:
+ return TARGET_HAS_XFLOATING_LIBS;
+
+ default:
+ return false;
+ }
+}
+
+/* Alpha implements a couple of integer vector mode operations when
+ TARGET_MAX is enabled. */
+
static bool
alpha_vector_mode_supported_p (enum machine_mode mode)
{
if (TARGET_MAX
- && ((mode == V8QImode)
- || (mode == V4HImode)
- || (mode == V2SImode)))
+ && (mode == V8QImode
+ || mode == V4HImode
+ || mode == V2SImode))
return true;
return false;
@@ -9362,6 +9393,9 @@ alpha_init_libfuncs (void)
#define TARGET_SPLIT_COMPLEX_ARG alpha_split_complex_arg
#undef TARGET_GIMPLIFY_VA_ARG_EXPR
#define TARGET_GIMPLIFY_VA_ARG_EXPR alpha_gimplify_va_arg
+
+#undef TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P alpha_scalar_mode_supported_p
#undef TARGET_VECTOR_MODE_SUPPORTED_P
#define TARGET_VECTOR_MODE_SUPPORTED_P alpha_vector_mode_supported_p
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 7240d19e837..b15cb53dec6 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -3878,6 +3878,18 @@ arguments to @code{va_arg}; the latter two are as in
@code{gimplify.c:gimplify_expr}.
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_SCALAR_MODE_SUPPORTED_P (enum machine_mode @var{mode})
+Define this to return nonzero if the port is prepared to handle
+insns involving scalar mode @var{mode}. For a scalar mode to be
+considered supported, all the basic arithmetic and comparisons
+must work.
+
+The default version of this hook returns true for any mode
+required to handle the basic C types (as defined by the port).
+Included here are the double-word arithmetic supported by the
+code in @file{optabs.c}.
+@end deftypefn
+
@deftypefn {Target Hook} bool TARGET_VECTOR_MODE_SUPPORTED_P (enum machine_mode @var{mode})
Define this to return nonzero if the port is prepared to handle
insns involving vector mode @var{mode}. At the very least, it
diff --git a/gcc/expr.c b/gcc/expr.c
index b98986447f4..6811abedd80 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -8799,7 +8799,7 @@ vector_mode_valid_p (enum machine_mode mode)
/* If we have support for the inner mode, we can safely emulate it.
We may not have V2DI, but me can emulate with a pair of DIs. */
- return mov_optab->handlers[innermode].insn_code != CODE_FOR_nothing;
+ return targetm.scalar_mode_supported_p (innermode);
}
/* Return a CONST_VECTOR rtx for a VECTOR_CST tree. */
diff --git a/gcc/target-def.h b/gcc/target-def.h
index 4d8fea0c8dd..156ebef7c7b 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -305,6 +305,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TARGET_VALID_POINTER_MODE default_valid_pointer_mode
#endif
+#ifndef TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P default_scalar_mode_supported_p
+#endif
+
#ifndef TARGET_VECTOR_MODE_SUPPORTED_P
#define TARGET_VECTOR_MODE_SUPPORTED_P hook_bool_mode_false
#endif
@@ -475,6 +479,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_ENCODE_SECTION_INFO, \
TARGET_STRIP_NAME_ENCODING, \
TARGET_VALID_POINTER_MODE, \
+ TARGET_SCALAR_MODE_SUPPORTED_P, \
TARGET_VECTOR_MODE_SUPPORTED_P, \
TARGET_VECTOR_OPAQUE_P, \
TARGET_RTX_COSTS, \
diff --git a/gcc/target.h b/gcc/target.h
index 2c3798eaa5d..27e4086129e 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -381,7 +381,14 @@ struct gcc_target
/* True if MODE is valid for a pointer in __attribute__((mode("MODE"))). */
bool (* valid_pointer_mode) (enum machine_mode mode);
- /* True if MODE is valid for a vector. */
+ /* True if MODE is valid for the target. By "valid", we mean able to
+ be manipulated in non-trivial ways. In particular, this means all
+ the arithmetic is supported. */
+ bool (* scalar_mode_supported_p) (enum machine_mode mode);
+
+ /* Similarly for vector modes. "Supported" here is less strict. At
+ least some operations are supported; need to check optabs or builtins
+ for further details. */
bool (* vector_mode_supported_p) (enum machine_mode mode);
/* True if a vector is opaque. */
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 00d7e8444d7..6aa2e07117b 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -62,6 +62,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tm_p.h"
#include "target-def.h"
+
void
default_external_libcall (rtx fun ATTRIBUTE_UNUSED)
{
@@ -207,3 +208,49 @@ default_unwind_emit (FILE * stream ATTRIBUTE_UNUSED,
/* Should never happen. */
abort ();
}
+
+/* True if MODE is valid for the target. By "valid", we mean able to
+ be manipulated in non-trivial ways. In particular, this means all
+ the arithmetic is supported.
+
+ By default we guess this means that any C type is supported. If
+ we can't map the mode back to a type that would be available in C,
+ then reject it. Special case, here, is the double-word arithmetic
+ supported by optabs.c. */
+
+bool
+default_scalar_mode_supported_p (enum machine_mode mode)
+{
+ int precision = GET_MODE_PRECISION (mode);
+
+ switch (GET_MODE_CLASS (mode))
+ {
+ case MODE_PARTIAL_INT:
+ case MODE_INT:
+ if (precision == CHAR_TYPE_SIZE)
+ return true;
+ if (precision == SHORT_TYPE_SIZE)
+ return true;
+ if (precision == INT_TYPE_SIZE)
+ return true;
+ if (precision == LONG_TYPE_SIZE)
+ return true;
+ if (precision == LONG_LONG_TYPE_SIZE)
+ return true;
+ if (precision == 2 * BITS_PER_WORD)
+ return true;
+ return false;
+
+ case MODE_FLOAT:
+ if (precision == FLOAT_TYPE_SIZE)
+ return true;
+ if (precision == DOUBLE_TYPE_SIZE)
+ return true;
+ if (precision == LONG_DOUBLE_TYPE_SIZE)
+ return true;
+ return false;
+
+ default:
+ abort ();
+ }
+}
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 077175eda9d..b91e51dec84 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -43,3 +43,5 @@ extern bool hook_pass_by_reference_must_pass_in_stack
(CUMULATIVE_ARGS *, enum machine_mode mode, tree, bool);
extern void default_unwind_emit (FILE *, rtx);
+
+extern bool default_scalar_mode_supported_p (enum machine_mode);
OpenPOWER on IntegriCloud