/* Define builtin-in macros for the C family front ends.
- Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
#include "tree.h"
#include "version.h"
#include "flags.h"
-#include "real.h"
#include "c-common.h"
#include "c-pragma.h"
#include "output.h"
#include "except.h" /* For USING_SJLJ_EXCEPTIONS. */
-#include "debug.h" /* For dwarf2out_do_frame. */
+#include "debug.h" /* For dwarf2out_do_cfi_asm. */
#include "toplev.h"
-#include "tm_p.h" /* Target prototypes. */
+#include "tm_p.h" /* For TARGET_CPU_CPP_BUILTINS & friends. */
#include "target.h"
#ifndef TARGET_OS_CPP_BUILTINS
const char *,
const char *);
static void builtin_define_stdint_macros (void);
-static void builtin_define_type_max (const char *, tree, int);
+static void builtin_define_constants (const char *, tree);
+static void builtin_define_type_max (const char *, tree);
+static void builtin_define_type_minmax (const char *, const char *, tree);
static void builtin_define_type_precision (const char *, tree);
static void builtin_define_type_sizeof (const char *, tree);
-static void builtin_define_float_constants (const char *,
+static void builtin_define_float_constants (const char *,
const char *,
const char *,
tree);
/* Define the float.h constants for TYPE using NAME_PREFIX, FP_SUFFIX,
and FP_CAST. */
static void
-builtin_define_float_constants (const char *name_prefix,
- const char *fp_suffix,
- const char *fp_cast,
+builtin_define_float_constants (const char *name_prefix,
+ const char *fp_suffix,
+ const char *fp_cast,
tree type)
{
/* Used to convert radix-based values to base 10 values in several cases.
const double log10_2 = .30102999566398119521;
double log10_b;
const struct real_format *fmt;
+ const struct real_format *ldfmt;
char name[64], buf[128];
int dig, min_10_exp, max_10_exp;
int decimal_dig;
+ int type_decimal_dig;
fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
gcc_assert (fmt->b != 10);
+ ldfmt = REAL_MODE_FORMAT (TYPE_MODE (long_double_type_node));
+ gcc_assert (ldfmt->b != 10);
/* The radix of the exponent representation. */
if (type == float_type_node)
The only macro we care about is this number for the widest supported
floating type, but we want this value for rendering constants below. */
{
- double d_decimal_dig = 1 + fmt->p * log10_b;
+ double d_decimal_dig
+ = 1 + (fmt->p < ldfmt->p ? ldfmt->p : fmt->p) * log10_b;
decimal_dig = d_decimal_dig;
if (decimal_dig < d_decimal_dig)
decimal_dig++;
}
+ /* Similar, for this type rather than long double. */
+ {
+ double type_d_decimal_dig = 1 + fmt->p * log10_b;
+ type_decimal_dig = type_d_decimal_dig;
+ if (type_decimal_dig < type_d_decimal_dig)
+ type_decimal_dig++;
+ }
if (type == long_double_type_node)
builtin_define_with_int_value ("__DECIMAL_DIG__", decimal_dig);
+ else
+ {
+ sprintf (name, "__%s_DECIMAL_DIG__", name_prefix);
+ builtin_define_with_int_value (name, type_decimal_dig);
+ }
/* Since, for the supported formats, B is always a power of 2, we
construct the following numbers directly as a hexadecimal
constants. */
get_max_float (fmt, buf, sizeof (buf));
-
+
sprintf (name, "__%s_MAX__", name_prefix);
builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
/* Define __DECx__ constants for TYPE using NAME_PREFIX and SUFFIX. */
static void
-builtin_define_decimal_float_constants (const char *name_prefix,
- const char *suffix,
+builtin_define_decimal_float_constants (const char *name_prefix,
+ const char *suffix,
tree type)
{
const struct real_format *fmt;
/* Compute the minimum representable value. */
sprintf (name, "__%s_MIN__", name_prefix);
- sprintf (buf, "1E%d%s", fmt->emin, suffix);
- builtin_define_with_value (name, buf, 0);
+ sprintf (buf, "1E%d%s", fmt->emin - 1, suffix);
+ builtin_define_with_value (name, buf, 0);
/* Compute the maximum representable value. */
sprintf (name, "__%s_MAX__", name_prefix);
*p++ = '.';
}
*p = 0;
- /* fmt->p plus 1, to account for the decimal point. */
- sprintf (&buf[fmt->p + 1], "E%d%s", fmt->emax, suffix);
+ /* fmt->p plus 1, to account for the decimal point and fmt->emax
+ minus 1 because the digits are nines, not 1.0. */
+ sprintf (&buf[fmt->p + 1], "E%d%s", fmt->emax - 1, suffix);
builtin_define_with_value (name, buf, 0);
/* Compute epsilon (the difference between 1 and least value greater
sprintf (buf, "1E-%d%s", fmt->p - 1, suffix);
builtin_define_with_value (name, buf, 0);
- /* Minimum denormalized positive decimal value. */
- sprintf (name, "__%s_DEN__", name_prefix);
+ /* Minimum subnormal positive decimal value. */
+ sprintf (name, "__%s_SUBNORMAL_MIN__", name_prefix);
p = buf;
for (digits = fmt->p; digits > 1; digits--)
{
*p++ = '.';
}
*p = 0;
- sprintf (&buf[fmt->p], "1E%d%s", fmt->emin, suffix);
+ sprintf (&buf[fmt->p], "1E%d%s", fmt->emin - 1, suffix);
builtin_define_with_value (name, buf, 0);
}
cpp_define_formatted (parse_in, "__GNUG__=%d", major);
}
-/* Define macros used by <stdint.h>. Currently only defines limits
- for intmax_t, used by the testsuite. */
+/* Define macros used by <stdint.h>. */
static void
builtin_define_stdint_macros (void)
{
- int intmax_long;
- if (intmax_type_node == long_long_integer_type_node)
- intmax_long = 2;
- else if (intmax_type_node == long_integer_type_node)
- intmax_long = 1;
- else if (intmax_type_node == integer_type_node)
- intmax_long = 0;
- else
- gcc_unreachable ();
- builtin_define_type_max ("__INTMAX_MAX__", intmax_type_node, intmax_long);
+ builtin_define_type_max ("__INTMAX_MAX__", intmax_type_node);
+ builtin_define_constants ("__INTMAX_C", intmax_type_node);
+ builtin_define_type_max ("__UINTMAX_MAX__", uintmax_type_node);
+ builtin_define_constants ("__UINTMAX_C", uintmax_type_node);
+ if (sig_atomic_type_node)
+ builtin_define_type_minmax ("__SIG_ATOMIC_MIN__", "__SIG_ATOMIC_MAX__",
+ sig_atomic_type_node);
+ if (int8_type_node)
+ builtin_define_type_max ("__INT8_MAX__", int8_type_node);
+ if (int16_type_node)
+ builtin_define_type_max ("__INT16_MAX__", int16_type_node);
+ if (int32_type_node)
+ builtin_define_type_max ("__INT32_MAX__", int32_type_node);
+ if (int64_type_node)
+ builtin_define_type_max ("__INT64_MAX__", int64_type_node);
+ if (uint8_type_node)
+ builtin_define_type_max ("__UINT8_MAX__", uint8_type_node);
+ if (uint16_type_node)
+ builtin_define_type_max ("__UINT16_MAX__", uint16_type_node);
+ if (c_uint32_type_node)
+ builtin_define_type_max ("__UINT32_MAX__", c_uint32_type_node);
+ if (c_uint64_type_node)
+ builtin_define_type_max ("__UINT64_MAX__", c_uint64_type_node);
+ if (int_least8_type_node)
+ {
+ builtin_define_type_max ("__INT_LEAST8_MAX__", int_least8_type_node);
+ builtin_define_constants ("__INT8_C", int_least8_type_node);
+ }
+ if (int_least16_type_node)
+ {
+ builtin_define_type_max ("__INT_LEAST16_MAX__", int_least16_type_node);
+ builtin_define_constants ("__INT16_C", int_least16_type_node);
+ }
+ if (int_least32_type_node)
+ {
+ builtin_define_type_max ("__INT_LEAST32_MAX__", int_least32_type_node);
+ builtin_define_constants ("__INT32_C", int_least32_type_node);
+ }
+ if (int_least64_type_node)
+ {
+ builtin_define_type_max ("__INT_LEAST64_MAX__", int_least64_type_node);
+ builtin_define_constants ("__INT64_C", int_least64_type_node);
+ }
+ if (uint_least8_type_node)
+ {
+ builtin_define_type_max ("__UINT_LEAST8_MAX__", uint_least8_type_node);
+ builtin_define_constants ("__UINT8_C", uint_least8_type_node);
+ }
+ if (uint_least16_type_node)
+ {
+ builtin_define_type_max ("__UINT_LEAST16_MAX__", uint_least16_type_node);
+ builtin_define_constants ("__UINT16_C", uint_least16_type_node);
+ }
+ if (uint_least32_type_node)
+ {
+ builtin_define_type_max ("__UINT_LEAST32_MAX__", uint_least32_type_node);
+ builtin_define_constants ("__UINT32_C", uint_least32_type_node);
+ }
+ if (uint_least64_type_node)
+ {
+ builtin_define_type_max ("__UINT_LEAST64_MAX__", uint_least64_type_node);
+ builtin_define_constants ("__UINT64_C", uint_least64_type_node);
+ }
+ if (int_fast8_type_node)
+ builtin_define_type_max ("__INT_FAST8_MAX__", int_fast8_type_node);
+ if (int_fast16_type_node)
+ builtin_define_type_max ("__INT_FAST16_MAX__", int_fast16_type_node);
+ if (int_fast32_type_node)
+ builtin_define_type_max ("__INT_FAST32_MAX__", int_fast32_type_node);
+ if (int_fast64_type_node)
+ builtin_define_type_max ("__INT_FAST64_MAX__", int_fast64_type_node);
+ if (uint_fast8_type_node)
+ builtin_define_type_max ("__UINT_FAST8_MAX__", uint_fast8_type_node);
+ if (uint_fast16_type_node)
+ builtin_define_type_max ("__UINT_FAST16_MAX__", uint_fast16_type_node);
+ if (uint_fast32_type_node)
+ builtin_define_type_max ("__UINT_FAST32_MAX__", uint_fast32_type_node);
+ if (uint_fast64_type_node)
+ builtin_define_type_max ("__UINT_FAST64_MAX__", uint_fast64_type_node);
+ if (intptr_type_node)
+ builtin_define_type_max ("__INTPTR_MAX__", intptr_type_node);
+ if (uintptr_type_node)
+ builtin_define_type_max ("__UINTPTR_MAX__", uintptr_type_node);
}
/* Adjust the optimization macros when a #pragma GCC optimization is done to
if (USING_SJLJ_EXCEPTIONS)
cpp_define (pfile, "__USING_SJLJ_EXCEPTIONS__");
- /* limits.h needs to know these. */
- builtin_define_type_max ("__SCHAR_MAX__", signed_char_type_node, 0);
- builtin_define_type_max ("__SHRT_MAX__", short_integer_type_node, 0);
- builtin_define_type_max ("__INT_MAX__", integer_type_node, 0);
- builtin_define_type_max ("__LONG_MAX__", long_integer_type_node, 1);
- builtin_define_type_max ("__LONG_LONG_MAX__", long_long_integer_type_node, 2);
- builtin_define_type_max ("__WCHAR_MAX__", wchar_type_node, 0);
+ /* limits.h and stdint.h need to know these. */
+ builtin_define_type_max ("__SCHAR_MAX__", signed_char_type_node);
+ builtin_define_type_max ("__SHRT_MAX__", short_integer_type_node);
+ builtin_define_type_max ("__INT_MAX__", integer_type_node);
+ builtin_define_type_max ("__LONG_MAX__", long_integer_type_node);
+ builtin_define_type_max ("__LONG_LONG_MAX__", long_long_integer_type_node);
+ builtin_define_type_minmax ("__WCHAR_MIN__", "__WCHAR_MAX__",
+ underlying_wchar_type_node);
+ builtin_define_type_minmax ("__WINT_MIN__", "__WINT_MAX__", wint_type_node);
+ builtin_define_type_max ("__PTRDIFF_MAX__", ptrdiff_type_node);
+ builtin_define_type_max ("__SIZE_MAX__", size_type_node);
builtin_define_type_precision ("__CHAR_BIT__", char_type_node);
- /* stdint.h (eventually) and the testsuite need to know these. */
+ /* stdint.h and the testsuite need to know these. */
builtin_define_stdint_macros ();
/* float.h needs to know these. */
TARGET_DEC_EVAL_METHOD);
builtin_define_float_constants ("FLT", "F", "%s", float_type_node);
- /* Cast the double precision constants when single precision constants are
- specified. The correct result is computed by the compiler when using
- macros that include a cast. This has the side-effect of making the value
- unusable in const expressions. */
- if (flag_single_precision_constant)
- builtin_define_float_constants ("DBL", "L", "((double)%s)", double_type_node);
- else
- builtin_define_float_constants ("DBL", "", "%s", double_type_node);
+ /* Cast the double precision constants. This is needed when single
+ precision constants are specified or when pragma FLOAT_CONST_DECIMAL64
+ is used. The correct result is computed by the compiler when using
+ macros that include a cast. */
+ builtin_define_float_constants ("DBL", "L", "((double)%s)", double_type_node);
builtin_define_float_constants ("LDBL", "L", "%s", long_double_type_node);
/* For decfloat.h. */
#endif
#ifdef DWARF2_UNWIND_INFO
- if (flag_dwarf2_cfi_asm && dwarf2out_do_frame ())
+ if (dwarf2out_do_cfi_asm ())
cpp_define (pfile, "__GCC_HAVE_DWARF2_CFI_ASM");
#endif
cpp_define (pfile, "__NEXT_RUNTIME__");
/* Show the availability of some target pragmas. */
- if (flag_mudflap || targetm.handle_pragma_redefine_extname)
- cpp_define (pfile, "__PRAGMA_REDEFINE_EXTNAME");
+ cpp_define (pfile, "__PRAGMA_REDEFINE_EXTNAME");
if (targetm.handle_pragma_extern_prefix)
cpp_define (pfile, "__PRAGMA_EXTERN_PREFIX");
format. */
if (ENABLE_DECIMAL_FLOAT && ENABLE_DECIMAL_BID_FORMAT)
cpp_define (pfile, "__DECIMAL_BID_FORMAT__");
+
+ builtin_define_with_int_value ("__BIGGEST_ALIGNMENT__",
+ BIGGEST_ALIGNMENT / BITS_PER_UNIT);
}
/* Pass an object-like macro. If it doesn't lie in the user's
/* Pass an object-like macro a hexadecimal floating-point value. */
static void
builtin_define_with_hex_fp_value (const char *macro,
- tree type ATTRIBUTE_UNUSED, int digits,
- const char *hex_str,
+ tree type, int digits,
+ const char *hex_str,
const char *fp_suffix,
const char *fp_cast)
{
then print it back out as decimal. */
real_from_string (&real, hex_str);
- real_to_decimal (dec_str, &real, sizeof (dec_str), digits, 0);
+ real_to_decimal_for_mode (dec_str, &real, sizeof (dec_str), digits, 0,
+ TYPE_MODE (type));
/* Assemble the macro in the following fashion
macro = fp_cast [dec_str fp_suffix] */
sprintf (buf1, "%s%s", dec_str, fp_suffix);
sprintf (buf2, fp_cast, buf1);
sprintf (buf1, "%s=%s", macro, buf2);
-
+
cpp_define (parse_in, buf1);
}
-/* Define MAX for TYPE based on the precision of the type. IS_LONG is
- 1 for type "long" and 2 for "long long". We have to handle
- unsigned types, since wchar_t might be unsigned. */
+/* Return a string constant for the suffix for a value of type TYPE
+ promoted according to the integer promotions. The type must be one
+ of the standard integer type nodes. */
+
+static const char *
+type_suffix (tree type)
+{
+ static const char *const suffixes[] = { "", "U", "L", "UL", "LL", "ULL" };
+ int unsigned_suffix;
+ int is_long;
+
+ if (type == long_long_integer_type_node
+ || type == long_long_unsigned_type_node)
+ is_long = 2;
+ else if (type == long_integer_type_node
+ || type == long_unsigned_type_node)
+ is_long = 1;
+ else if (type == integer_type_node
+ || type == unsigned_type_node
+ || type == short_integer_type_node
+ || type == short_unsigned_type_node
+ || type == signed_char_type_node
+ || type == unsigned_char_type_node
+ /* ??? "char" is not a signed or unsigned integer type and
+ so is not permitted for the standard typedefs, but some
+ systems use it anyway. */
+ || type == char_type_node)
+ is_long = 0;
+ else
+ gcc_unreachable ();
+
+ unsigned_suffix = TYPE_UNSIGNED (type);
+ if (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+ unsigned_suffix = 0;
+ return suffixes[is_long * 2 + unsigned_suffix];
+}
+
+/* Define MACRO as a <stdint.h> constant-suffix macro for TYPE. */
+static void
+builtin_define_constants (const char *macro, tree type)
+{
+ const char *suffix;
+ char *buf;
+
+ suffix = type_suffix (type);
+
+ if (suffix[0] == 0)
+ {
+ buf = (char *) alloca (strlen (macro) + 6);
+ sprintf (buf, "%s(c)=c", macro);
+ }
+ else
+ {
+ buf = (char *) alloca (strlen (macro) + 9 + strlen (suffix) + 1);
+ sprintf (buf, "%s(c)=c ## %s", macro, suffix);
+ }
+
+ cpp_define (parse_in, buf);
+}
+
+/* Define MAX for TYPE based on the precision of the type. */
static void
-builtin_define_type_max (const char *macro, tree type, int is_long)
+builtin_define_type_max (const char *macro, tree type)
+{
+ builtin_define_type_minmax (NULL, macro, type);
+}
+
+/* Define MIN_MACRO (if not NULL) and MAX_MACRO for TYPE based on the
+ precision of the type. */
+
+static void
+builtin_define_type_minmax (const char *min_macro, const char *max_macro,
+ tree type)
{
static const char *const values[]
= { "127", "255",
"9223372036854775807", "18446744073709551615",
"170141183460469231731687303715884105727",
"340282366920938463463374607431768211455" };
- static const char *const suffixes[] = { "", "U", "L", "UL", "LL", "ULL" };
const char *value, *suffix;
char *buf;
}
value = values[idx + TYPE_UNSIGNED (type)];
- suffix = suffixes[is_long * 2 + TYPE_UNSIGNED (type)];
+ suffix = type_suffix (type);
- buf = (char *) alloca (strlen (macro) + 1 + strlen (value)
+ buf = (char *) alloca (strlen (max_macro) + 1 + strlen (value)
+ strlen (suffix) + 1);
- sprintf (buf, "%s=%s%s", macro, value, suffix);
+ sprintf (buf, "%s=%s%s", max_macro, value, suffix);
cpp_define (parse_in, buf);
+
+ if (min_macro)
+ {
+ if (TYPE_UNSIGNED (type))
+ {
+ buf = (char *) alloca (strlen (min_macro) + 2 + strlen (suffix) + 1);
+ sprintf (buf, "%s=0%s", min_macro, suffix);
+ }
+ else
+ {
+ buf = (char *) alloca (strlen (min_macro) + 3
+ + strlen (max_macro) + 6);
+ sprintf (buf, "%s=(-%s - 1)", min_macro, max_macro);
+ }
+ cpp_define (parse_in, buf);
+ }
}