#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#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"
#include "toplev.h"
#include "tm_p.h"
#include "target.h"
#ifndef TARGET_OS_CPP_BUILTINS
# define TARGET_OS_CPP_BUILTINS()
#endif
#ifndef TARGET_OBJFMT_CPP_BUILTINS
# define TARGET_OBJFMT_CPP_BUILTINS()
#endif
#ifndef REGISTER_PREFIX
#define REGISTER_PREFIX ""
#endif
void builtin_define_std (const char *) ATTRIBUTE_UNUSED;
static void builtin_define_with_value_n (const char *, const char *,
size_t);
static void builtin_define_with_int_value (const char *, HOST_WIDE_INT);
static void builtin_define_with_hex_fp_value (const char *, tree,
int, const char *,
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_type_precision (const char *, tree);
static void builtin_define_float_constants (const char *,
const char *,
const char *,
tree);
static void define__GNUC__ (void);
static void
builtin_define_type_precision (const char *name, tree type)
{
builtin_define_with_int_value (name, TYPE_PRECISION (type));
}
static void
builtin_define_float_constants (const char *name_prefix,
const char *fp_suffix,
const char *fp_cast,
tree type)
{
const double log10_2 = .30102999566398119521;
double log10_b;
const struct real_format *fmt;
char name[64], buf[128];
int dig, min_10_exp, max_10_exp;
int decimal_dig;
fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
gcc_assert (fmt->b != 10);
if (type == float_type_node)
builtin_define_with_int_value ("__FLT_RADIX__", fmt->b);
log10_b = log10_2 * fmt->log2_b;
sprintf (name, "__%s_MANT_DIG__", name_prefix);
builtin_define_with_int_value (name, fmt->p);
dig = (fmt->p - 1) * log10_b;
sprintf (name, "__%s_DIG__", name_prefix);
builtin_define_with_int_value (name, dig);
sprintf (name, "__%s_MIN_EXP__", name_prefix);
sprintf (buf, "(%d)", fmt->emin);
builtin_define_with_value (name, buf, 0);
min_10_exp = (fmt->emin - 1) * log10_b;
sprintf (name, "__%s_MIN_10_EXP__", name_prefix);
sprintf (buf, "(%d)", min_10_exp);
builtin_define_with_value (name, buf, 0);
sprintf (name, "__%s_MAX_EXP__", name_prefix);
builtin_define_with_int_value (name, fmt->emax);
max_10_exp = fmt->emax * log10_b;
sprintf (name, "__%s_MAX_10_EXP__", name_prefix);
builtin_define_with_int_value (name, max_10_exp);
{
double d_decimal_dig = 1 + fmt->p * log10_b;
decimal_dig = d_decimal_dig;
if (decimal_dig < d_decimal_dig)
decimal_dig++;
}
if (type == long_double_type_node)
builtin_define_with_int_value ("__DECIMAL_DIG__", decimal_dig);
{
int i, n;
char *p;
strcpy (buf, "0x0.");
n = fmt->p * fmt->log2_b;
for (i = 0, p = buf + 4; i + 3 < n; i += 4)
*p++ = 'f';
if (i < n)
*p++ = "08ce"[n - i];
sprintf (p, "p%d", fmt->emax * fmt->log2_b);
if (fmt->pnan < fmt->p)
{
buf[4 + fmt->pnan / 4] = "7bde"[fmt->pnan % 4];
}
}
sprintf (name, "__%s_MAX__", name_prefix);
builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
sprintf (name, "__%s_MIN__", name_prefix);
sprintf (buf, "0x1p%d", (fmt->emin - 1) * fmt->log2_b);
builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
sprintf (name, "__%s_EPSILON__", name_prefix);
if (fmt->pnan < fmt->p)
sprintf (buf, "0x1p%d", (fmt->emin - fmt->p) * fmt->log2_b);
else
sprintf (buf, "0x1p%d", (1 - fmt->p) * fmt->log2_b);
builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
sprintf (name, "__%s_DENORM_MIN__", name_prefix);
if (fmt->has_denorm)
{
sprintf (buf, "0x1p%d", (fmt->emin - fmt->p) * fmt->log2_b);
builtin_define_with_hex_fp_value (name, type, decimal_dig,
buf, fp_suffix, fp_cast);
}
else
{
sprintf (buf, "0.0%s", fp_suffix);
builtin_define_with_value (name, buf, 0);
}
sprintf (name, "__%s_HAS_DENORM__", name_prefix);
builtin_define_with_value (name, fmt->has_denorm ? "1" : "0", 0);
sprintf (name, "__%s_HAS_INFINITY__", name_prefix);
builtin_define_with_int_value (name,
MODE_HAS_INFINITIES (TYPE_MODE (type)));
sprintf (name, "__%s_HAS_QUIET_NAN__", name_prefix);
builtin_define_with_int_value (name, MODE_HAS_NANS (TYPE_MODE (type)));
}
static void
builtin_define_decimal_float_constants (const char *name_prefix,
const char *suffix,
tree type)
{
const struct real_format *fmt;
char name[64], buf[128], *p;
int digits;
fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
sprintf (name, "__%s_MANT_DIG__", name_prefix);
builtin_define_with_int_value (name, fmt->p);
sprintf (name, "__%s_MIN_EXP__", name_prefix);
sprintf (buf, "(%d)", fmt->emin);
builtin_define_with_value (name, buf, 0);
sprintf (name, "__%s_MAX_EXP__", name_prefix);
builtin_define_with_int_value (name, fmt->emax);
sprintf (name, "__%s_MIN__", name_prefix);
sprintf (buf, "1E%d%s", fmt->emin, suffix);
builtin_define_with_value (name, buf, 0);
sprintf (name, "__%s_MAX__", name_prefix);
p = buf;
for (digits = fmt->p; digits; digits--)
{
*p++ = '9';
if (digits == fmt->p)
*p++ = '.';
}
*p = 0;
sprintf (&buf[fmt->p + 1], "E%d%s", fmt->emax, suffix);
builtin_define_with_value (name, buf, 0);
sprintf (name, "__%s_EPSILON__", name_prefix);
sprintf (buf, "1E-%d%s", fmt->p - 1, suffix);
builtin_define_with_value (name, buf, 0);
sprintf (name, "__%s_DEN__", name_prefix);
p = buf;
for (digits = fmt->p; digits > 1; digits--)
{
*p++ = '0';
if (digits == fmt->p)
*p++ = '.';
}
*p = 0;
sprintf (&buf[fmt->p], "1E%d%s", fmt->emin, suffix);
builtin_define_with_value (name, buf, 0);
}
static void
define__GNUC__ (void)
{
const char *q, *v = version_string;
while (*v && !ISDIGIT (*v))
v++;
gcc_assert (*v && (v <= version_string || v[-1] == '-'));
q = v;
while (ISDIGIT (*v))
v++;
builtin_define_with_value_n ("__GNUC__", q, v - q);
if (c_dialect_cxx ())
builtin_define_with_value_n ("__GNUG__", q, v - q);
gcc_assert (*v == '.' && ISDIGIT (v[1]));
q = ++v;
while (ISDIGIT (*v))
v++;
builtin_define_with_value_n ("__GNUC_MINOR__", q, v - q);
if (*v == '.')
{
gcc_assert (ISDIGIT (v[1]));
q = ++v;
while (ISDIGIT (*v))
v++;
builtin_define_with_value_n ("__GNUC_PATCHLEVEL__", q, v - q);
}
else
builtin_define_with_value_n ("__GNUC_PATCHLEVEL__", "0", 1);
gcc_assert (!*v || *v == ' ' || *v == '-');
}
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);
}
void
c_cpp_builtins (cpp_reader *pfile)
{
if (flag_undef)
return;
define__GNUC__ ();
c_stddef_cpp_builtins ();
if (c_dialect_cxx ())
{
if (flag_weak && SUPPORTS_ONE_ONLY)
cpp_define (pfile, "__GXX_WEAK__=1");
else
cpp_define (pfile, "__GXX_WEAK__=0");
if (warn_deprecated)
cpp_define (pfile, "__DEPRECATED");
}
if (flag_exceptions)
cpp_define (pfile, "__EXCEPTIONS");
if (flag_abi_version == 0)
builtin_define_with_int_value ("__GXX_ABI_VERSION", 999999);
else if (flag_abi_version == 1)
builtin_define_with_int_value ("__GXX_ABI_VERSION", 102);
else
builtin_define_with_int_value ("__GXX_ABI_VERSION",
1000 + flag_abi_version);
if (USING_SJLJ_EXCEPTIONS)
cpp_define (pfile, "__USING_SJLJ_EXCEPTIONS__");
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);
builtin_define_type_precision ("__CHAR_BIT__", char_type_node);
builtin_define_stdint_macros ();
builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
TARGET_FLT_EVAL_METHOD);
builtin_define_with_int_value ("__DEC_EVAL_METHOD__",
TARGET_DEC_EVAL_METHOD);
builtin_define_float_constants ("FLT", "F", "%s", float_type_node);
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);
builtin_define_float_constants ("LDBL", "L", "%s", long_double_type_node);
builtin_define_decimal_float_constants ("DEC32", "DF", dfloat32_type_node);
builtin_define_decimal_float_constants ("DEC64", "DD", dfloat64_type_node);
builtin_define_decimal_float_constants ("DEC128", "DL", dfloat128_type_node);
builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0);
builtin_define_with_value ("__USER_LABEL_PREFIX__", user_label_prefix, 0);
builtin_define_with_value ("__VERSION__", version_string, 1);
cpp_define (pfile, "__GNUC_GNU_INLINE__");
if (TYPE_PRECISION (long_integer_type_node) == 64
&& POINTER_SIZE == 64
&& TYPE_PRECISION (integer_type_node) == 32)
{
cpp_define (pfile, "_LP64");
cpp_define (pfile, "__LP64__");
}
if (optimize_size)
cpp_define (pfile, "__OPTIMIZE_SIZE__");
if (optimize)
cpp_define (pfile, "__OPTIMIZE__");
if (fast_math_flags_set_p ())
cpp_define (pfile, "__FAST_MATH__");
if (flag_really_no_inline)
cpp_define (pfile, "__NO_INLINE__");
if (flag_signaling_nans)
cpp_define (pfile, "__SUPPORT_SNAN__");
if (flag_finite_math_only)
cpp_define (pfile, "__FINITE_MATH_ONLY__=1");
else
cpp_define (pfile, "__FINITE_MATH_ONLY__=0");
if (flag_pic)
{
builtin_define_with_int_value ("__pic__", flag_pic);
builtin_define_with_int_value ("__PIC__", flag_pic);
}
if (flag_iso)
cpp_define (pfile, "__STRICT_ANSI__");
if (!flag_signed_char)
cpp_define (pfile, "__CHAR_UNSIGNED__");
if (c_dialect_cxx () && TYPE_UNSIGNED (wchar_type_node))
cpp_define (pfile, "__WCHAR_UNSIGNED__");
if (c_dialect_objc () && flag_next_runtime)
cpp_define (pfile, "__NEXT_RUNTIME__");
if (flag_mudflap || targetm.handle_pragma_redefine_extname)
cpp_define (pfile, "__PRAGMA_REDEFINE_EXTNAME");
if (targetm.handle_pragma_extern_prefix)
cpp_define (pfile, "__PRAGMA_EXTERN_PREFIX");
if (flag_stack_protect == 2)
cpp_define (pfile, "__SSP_ALL__=2");
else if (flag_stack_protect == 1)
cpp_define (pfile, "__SSP__=1");
if (flag_openmp)
cpp_define (pfile, "_OPENMP=200505");
# define preprocessing_asm_p() (cpp_get_options (pfile)->lang == CLK_ASM)
# define preprocessing_trad_p() (cpp_get_options (pfile)->traditional)
# define builtin_define(TXT) cpp_define (pfile, TXT)
# define builtin_assert(TXT) cpp_assert (pfile, TXT)
TARGET_CPU_CPP_BUILTINS ();
TARGET_OS_CPP_BUILTINS ();
TARGET_OBJFMT_CPP_BUILTINS ();
if (TARGET_DECLSPEC)
builtin_define ("__declspec(x)=__attribute__((x))");
}
void
builtin_define_std (const char *macro)
{
size_t len = strlen (macro);
char *buff = (char *) alloca (len + 5);
char *p = buff + 2;
char *q = p + len;
memcpy (p, macro, len + 1);
if (!( *p == '_' && (p[1] == '_' || ISUPPER (p[1]))))
{
if (*p != '_')
*--p = '_';
if (p[1] != '_')
*--p = '_';
}
cpp_define (parse_in, p);
if (p != buff + 2)
{
if (q[-1] != '_')
*q++ = '_';
if (q[-2] != '_')
*q++ = '_';
*q = '\0';
cpp_define (parse_in, p);
if (!flag_iso)
cpp_define (parse_in, macro);
}
}
void
builtin_define_with_value (const char *macro, const char *expansion, int is_str)
{
char *buf;
size_t mlen = strlen (macro);
size_t elen = strlen (expansion);
size_t extra = 2;
if (is_str)
extra += 2;
buf = (char *) alloca (mlen + elen + extra);
if (is_str)
sprintf (buf, "%s=\"%s\"", macro, expansion);
else
sprintf (buf, "%s=%s", macro, expansion);
cpp_define (parse_in, buf);
}
static void
builtin_define_with_value_n (const char *macro, const char *expansion, size_t elen)
{
char *buf;
size_t mlen = strlen (macro);
buf = (char *) alloca (mlen + elen + 2);
memcpy (buf, macro, mlen);
buf[mlen] = '=';
memcpy (buf + mlen + 1, expansion, elen);
buf[mlen + elen + 1] = '\0';
cpp_define (parse_in, buf);
}
static void
builtin_define_with_int_value (const char *macro, HOST_WIDE_INT value)
{
char *buf;
size_t mlen = strlen (macro);
size_t vlen = 18;
size_t extra = 2;
buf = (char *) alloca (mlen + vlen + extra);
memcpy (buf, macro, mlen);
buf[mlen] = '=';
sprintf (buf + mlen + 1, HOST_WIDE_INT_PRINT_DEC, value);
cpp_define (parse_in, buf);
}
static void
builtin_define_with_hex_fp_value (const char *macro,
tree type ATTRIBUTE_UNUSED, int digits,
const char *hex_str,
const char *fp_suffix,
const char *fp_cast)
{
REAL_VALUE_TYPE real;
char dec_str[64], buf1[256], buf2[256];
real_from_string (&real, hex_str);
real_to_decimal (dec_str, &real, sizeof (dec_str), digits, 0);
sprintf (buf1, "%s%s", dec_str, fp_suffix);
sprintf (buf2, fp_cast, buf1);
sprintf (buf1, "%s=%s", macro, buf2);
cpp_define (parse_in, buf1);
}
static void
builtin_define_type_max (const char *macro, tree type, int is_long)
{
static const char *const values[]
= { "127", "255",
"32767", "65535",
"2147483647", "4294967295",
"9223372036854775807", "18446744073709551615",
"170141183460469231731687303715884105727",
"340282366920938463463374607431768211455" };
static const char *const suffixes[] = { "", "U", "L", "UL", "LL", "ULL" };
const char *value, *suffix;
char *buf;
size_t idx;
switch (TYPE_PRECISION (type))
{
case 8: idx = 0; break;
case 16: idx = 2; break;
case 32: idx = 4; break;
case 64: idx = 6; break;
case 128: idx = 8; break;
default: gcc_unreachable ();
}
value = values[idx + TYPE_UNSIGNED (type)];
suffix = suffixes[is_long * 2 + TYPE_UNSIGNED (type)];
buf = (char *) alloca (strlen (macro) + 1 + strlen (value)
+ strlen (suffix) + 1);
sprintf (buf, "%s=%s%s", macro, value, suffix);
cpp_define (parse_in, buf);
}