OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / builtins.c
index 630cd25..7e1ca21 100644 (file)
@@ -279,9 +279,7 @@ get_pointer_alignment (tree exp, unsigned int max_align)
     {
       switch (TREE_CODE (exp))
        {
-       case NOP_EXPR:
-       case CONVERT_EXPR:
-       case NON_LVALUE_EXPR:
+       CASE_CONVERT:
          exp = TREE_OPERAND (exp, 0);
          if (! POINTER_TYPE_P (TREE_TYPE (exp)))
            return align;
@@ -448,7 +446,12 @@ c_strlen (tree src, int only_value)
      runtime.  */
   if (offset < 0 || offset > max)
     {
-      warning (0, "offset outside bounds of constant string");
+     /* Suppress multiple warnings for propagated constant strings.  */
+      if (! TREE_NO_WARNING (src))
+        {
+          warning (0, "offset outside bounds of constant string");
+          TREE_NO_WARNING (src) = 1;
+        }
       return NULL_TREE;
     }
 
@@ -588,7 +591,7 @@ expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
       tem = hard_frame_pointer_rtx;
 
       /* Tell reload not to eliminate the frame pointer.  */
-      current_function_accesses_prior_frames = 1;
+      crtl->accesses_prior_frames = 1;
     }
 #endif
 
@@ -691,10 +694,10 @@ expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
 
   /* Tell optimize_save_area_alloca that extra work is going to
      need to go on during alloca.  */
-  current_function_calls_setjmp = 1;
+  cfun->calls_setjmp = 1;
 
   /* We have a nonlocal label.   */
-  current_function_has_nonlocal_label = 1;
+  cfun->has_nonlocal_label = 1;
 }
 
 /* Construct the trailing part of a __builtin_setjmp call.  This is
@@ -741,7 +744,7 @@ expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
          /* Now restore our arg pointer from the address at which it
             was saved in our stack frame.  */
          emit_move_insn (virtual_incoming_args_rtx,
-                         copy_to_reg (get_arg_pointer_save_area (cfun)));
+                         copy_to_reg (get_arg_pointer_save_area ()));
        }
     }
 #endif
@@ -878,7 +881,7 @@ expand_builtin_nonlocal_goto (tree exp)
   r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
                      plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
 
-  current_function_has_nonlocal_goto = 1;
+  crtl->has_nonlocal_goto = 1;
 
 #ifdef HAVE_nonlocal_goto
   /* ??? We no longer need to pass the static chain value, afaik.  */
@@ -1073,8 +1076,7 @@ get_memory_rtx (tree exp, tree len)
   /* Get an expression we can use to find the attributes to assign to MEM.
      If it is an ADDR_EXPR, use the operand.  Otherwise, dereference it if
      we can.  First remove any nops.  */
-  while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
-         || TREE_CODE (exp) == NON_LVALUE_EXPR)
+  while (CONVERT_EXPR_P (exp)
         && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
     exp = TREE_OPERAND (exp, 0);
 
@@ -1104,9 +1106,7 @@ get_memory_rtx (tree exp, tree len)
          tree inner = exp;
 
          while (TREE_CODE (inner) == ARRAY_REF
-                || TREE_CODE (inner) == NOP_EXPR
-                || TREE_CODE (inner) == CONVERT_EXPR
-                || TREE_CODE (inner) == NON_LVALUE_EXPR
+                || CONVERT_EXPR_P (inner)
                 || TREE_CODE (inner) == VIEW_CONVERT_EXPR
                 || TREE_CODE (inner) == SAVE_EXPR)
            inner = TREE_OPERAND (inner, 0);
@@ -1351,7 +1351,7 @@ expand_builtin_apply_args_1 (void)
      as we might have pretended they were passed.  Make sure it's a valid
      operand, as emit_move_insn isn't expected to handle a PLUS.  */
   tem
-    = force_operand (plus_constant (tem, current_function_pretend_args_size),
+    = force_operand (plus_constant (tem, crtl->args.pretend_args_size),
                     NULL_RTX);
 #endif
   emit_move_insn (adjust_address (registers, Pmode, 0), tem);
@@ -1804,6 +1804,9 @@ expand_errno_check (tree exp, rtx target)
     }
 #endif
 
+  /* Make sure the library call isn't expanded as a tail call.  */
+  CALL_EXPR_TAILCALL (exp) = 0;
+
   /* We can't set errno=EDOM directly; let the library call do it.
      Pop the arguments right away in case the call gets deleted.  */
   NO_DEFER_POP;
@@ -2983,6 +2986,8 @@ expand_builtin_pow (tree exp, rtx target, rtx subtarget)
       && (tree_expr_nonnegative_p (arg0)
          || !HONOR_NANS (mode)))
     {
+      REAL_VALUE_TYPE dconst3;
+      real_from_integer (&dconst3, VOIDmode, 3, 0, 0);
       real_arithmetic (&c2, MULT_EXPR, &c, &dconst3);
       real_round (&c2, mode, &c2);
       n = real_to_integer (&c2);
@@ -4598,7 +4603,7 @@ static rtx
 expand_builtin_args_info (tree exp)
 {
   int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
-  int *word_ptr = (int *) &current_function_args_info;
+  int *word_ptr = (int *) &crtl->args.info;
 
   gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
 
@@ -4630,8 +4635,8 @@ expand_builtin_next_arg (void)
   /* Checking arguments is already done in fold_builtin_next_arg
      that must be called before this function.  */
   return expand_binop (ptr_mode, add_optab,
-                      current_function_internal_arg_pointer,
-                      current_function_arg_offset_rtx,
+                      crtl->args.internal_arg_pointer,
+                      crtl->args.arg_offset_rtx,
                       NULL_RTX, 0, OPTAB_LIB_WIDEN);
 }
 
@@ -4716,11 +4721,10 @@ expand_builtin_va_start (tree exp)
   nextarg = expand_builtin_next_arg ();
   valist = stabilize_va_list (CALL_EXPR_ARG (exp, 0), 1);
 
-#ifdef EXPAND_BUILTIN_VA_START
-  EXPAND_BUILTIN_VA_START (valist, nextarg);
-#else
-  std_expand_builtin_va_start (valist, nextarg);
-#endif
+  if (targetm.expand_builtin_va_start)
+    targetm.expand_builtin_va_start (valist, nextarg);
+  else
+    std_expand_builtin_va_start (valist, nextarg);
 
   return const0_rtx;
 }
@@ -5193,6 +5197,7 @@ expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
     return NULL_RTX;
 
   arg = CALL_EXPR_ARG (exp, 0);
+  CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
   mode = TYPE_MODE (TREE_TYPE (arg));
   op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
   return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
@@ -5234,7 +5239,6 @@ build_string_literal (int len, const char *str)
   type = build_array_type (elem, index);
   TREE_TYPE (t) = type;
   TREE_CONSTANT (t) = 1;
-  TREE_INVARIANT (t) = 1;
   TREE_READONLY (t) = 1;
   TREE_STATIC (t) = 1;
 
@@ -6092,7 +6096,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
      none of its arguments are volatile, we can avoid expanding the
      built-in call and just evaluate the arguments for side-effects.  */
   if (target == const0_rtx
-      && (DECL_IS_PURE (fndecl) || TREE_READONLY (fndecl)))
+      && (DECL_PURE_P (fndecl) || TREE_READONLY (fndecl)))
     {
       bool volatilep = false;
       tree arg;
@@ -6702,7 +6706,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
 
     case BUILT_IN_VA_START:
-    case BUILT_IN_STDARG_START:
       return expand_builtin_va_start (exp);
     case BUILT_IN_VA_END:
       return expand_builtin_va_end (exp);
@@ -7149,7 +7152,7 @@ fold_builtin_expect (tree arg0, tree arg1)
     }
 
   /* If the argument isn't invariant then there's nothing else we can do.  */
-  if (!TREE_INVARIANT (arg0))
+  if (!TREE_CONSTANT (arg0))
     return NULL_TREE;
 
   /* If we expect that a comparison against the argument will fold to
@@ -7261,7 +7264,6 @@ integer_valued_real_p (tree t)
 
     case ABS_EXPR:
     case SAVE_EXPR:
-    case NON_LVALUE_EXPR:
       return integer_valued_real_p (TREE_OPERAND (t, 0));
 
     case COMPOUND_EXPR:
@@ -7459,7 +7461,8 @@ fold_builtin_cabs (tree arg, tree type, tree fndecl)
          && operand_equal_p (real, imag, OEP_PURE_SAME))
         {
          const REAL_VALUE_TYPE sqrt2_trunc
-           = real_value_truncate (TYPE_MODE (type), dconstsqrt2);
+           = real_value_truncate (TYPE_MODE (type),
+                                  *get_real_const (rv_sqrt2));
          STRIP_NOPS (real);
          return fold_build2 (MULT_EXPR, type,
                              fold_build1 (ABS_EXPR, type, real),
@@ -7542,7 +7545,7 @@ fold_builtin_sqrt (tree arg, tree type)
          tree tree_root;
          /* The inner root was either sqrt or cbrt.  */
          REAL_VALUE_TYPE dconstroot =
-           BUILTIN_SQRT_P (fcode) ? dconsthalf : dconstthird;
+           BUILTIN_SQRT_P (fcode) ? dconsthalf : *get_real_const (rv_third);
 
          /* Adjust for the outer root.  */
          SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
@@ -7595,7 +7598,7 @@ fold_builtin_cbrt (tree arg, tree type)
        {
          tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
          const REAL_VALUE_TYPE third_trunc =
-           real_value_truncate (TYPE_MODE (type), dconstthird);
+           real_value_truncate (TYPE_MODE (type), *get_real_const (rv_third));
          arg = fold_build2 (MULT_EXPR, type,
                             CALL_EXPR_ARG (arg, 0),
                             build_real (type, third_trunc));
@@ -7611,7 +7614,7 @@ fold_builtin_cbrt (tree arg, tree type)
            {
              tree arg0 = CALL_EXPR_ARG (arg, 0);
              tree tree_root;
-             REAL_VALUE_TYPE dconstroot = dconstthird;
+             REAL_VALUE_TYPE dconstroot = *get_real_const (rv_third);
 
              SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
              dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
@@ -7633,7 +7636,9 @@ fold_builtin_cbrt (tree arg, tree type)
                  tree tree_root;
                  REAL_VALUE_TYPE dconstroot;
 
-                 real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird);
+                 real_arithmetic (&dconstroot, MULT_EXPR,
+                                  get_real_const (rv_third),
+                                  get_real_const (rv_third));
                  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
                  tree_root = build_real (type, dconstroot);
                  return build_call_expr (powfn, 2, arg0, tree_root);
@@ -7652,7 +7657,8 @@ fold_builtin_cbrt (tree arg, tree type)
            {
              tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
              const REAL_VALUE_TYPE dconstroot
-               = real_value_truncate (TYPE_MODE (type), dconstthird);
+               = real_value_truncate (TYPE_MODE (type),
+                                      *get_real_const (rv_third));
              tree narg01 = fold_build2 (MULT_EXPR, type, arg01,
                                         build_real (type, dconstroot));
              return build_call_expr (powfn, 2, arg00, narg01);
@@ -8200,7 +8206,7 @@ fold_builtin_logarithm (tree fndecl, tree arg,
       if (flag_unsafe_math_optimizations && func == mpfr_log)
         {
          const REAL_VALUE_TYPE e_truncated =
-           real_value_truncate (TYPE_MODE (type), dconste);
+           real_value_truncate (TYPE_MODE (type), *get_real_const (rv_e));
          if (real_dconstp (arg, &e_truncated))
            return build_real (type, dconst1);
        }
@@ -8234,7 +8240,8 @@ fold_builtin_logarithm (tree fndecl, tree arg,
          CASE_FLT_FN (BUILT_IN_EXP):
            /* Prepare to do logN(exp(exponent) -> exponent*logN(e).  */
            x = build_real (type,
-                           real_value_truncate (TYPE_MODE (type), dconste));
+                           real_value_truncate (TYPE_MODE (type),
+                                                *get_real_const (rv_e)));
            exponent = CALL_EXPR_ARG (arg, 0);
            break;
          CASE_FLT_FN (BUILT_IN_EXP2):
@@ -8245,7 +8252,11 @@ fold_builtin_logarithm (tree fndecl, tree arg,
          CASE_FLT_FN (BUILT_IN_EXP10):
          CASE_FLT_FN (BUILT_IN_POW10):
            /* Prepare to do logN(exp10(exponent) -> exponent*logN(10).  */
-           x = build_real (type, dconst10);
+           {
+             REAL_VALUE_TYPE dconst10;
+             real_from_integer (&dconst10, VOIDmode, 10, 0, 0);
+             x = build_real (type, dconst10);
+           }
            exponent = CALL_EXPR_ARG (arg, 0);
            break;
          CASE_FLT_FN (BUILT_IN_SQRT):
@@ -8257,7 +8268,7 @@ fold_builtin_logarithm (tree fndecl, tree arg,
            /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x).  */
            x = CALL_EXPR_ARG (arg, 0);
            exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
-                                                             dconstthird));
+                                                             *get_real_const (rv_third)));
            break;
          CASE_FLT_FN (BUILT_IN_POW):
            /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x).  */
@@ -8317,7 +8328,7 @@ fold_builtin_hypot (tree fndecl, tree arg0, tree arg1, tree type)
       && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
     {
       const REAL_VALUE_TYPE sqrt2_trunc
-       = real_value_truncate (TYPE_MODE (type), dconstsqrt2);
+       = real_value_truncate (TYPE_MODE (type), *get_real_const (rv_sqrt2));
       return fold_build2 (MULT_EXPR, type,
                          fold_build1 (ABS_EXPR, type, arg0),
                          build_real (type, sqrt2_trunc));
@@ -8383,7 +8394,8 @@ fold_builtin_pow (tree fndecl, tree arg0, tree arg1, tree type)
       if (flag_unsafe_math_optimizations)
        {
          const REAL_VALUE_TYPE dconstroot
-           = real_value_truncate (TYPE_MODE (type), dconstthird);
+           = real_value_truncate (TYPE_MODE (type),
+                                  *get_real_const (rv_third));
 
          if (REAL_VALUES_EQUAL (c, dconstroot))
            {
@@ -8450,7 +8462,8 @@ fold_builtin_pow (tree fndecl, tree arg0, tree arg1, tree type)
          if (tree_expr_nonnegative_p (arg))
            {
              const REAL_VALUE_TYPE dconstroot
-               = real_value_truncate (TYPE_MODE (type), dconstthird);
+               = real_value_truncate (TYPE_MODE (type),
+                                      *get_real_const (rv_third));
              tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
                                        build_real (type, dconstroot));
              return build_call_expr (fndecl, 2, arg, narg1);
@@ -9635,11 +9648,7 @@ fold_builtin_classify (tree fndecl, tree arg, int builtin_index)
   REAL_VALUE_TYPE r;
 
   if (!validate_arg (arg, REAL_TYPE))
-    {
-      error ("non-floating-point argument to function %qs",
-            IDENTIFIER_POINTER (DECL_NAME (fndecl)));
-      return error_mark_node;
-    }
+    return NULL_TREE;
 
   switch (builtin_index)
     {
@@ -9723,12 +9732,6 @@ fold_builtin_unordered_cmp (tree fndecl, tree arg0, tree arg1,
     cmp_type = type0;
   else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
     cmp_type = type1;
-  else
-    {
-      error ("non-floating-point argument to function %qs",
-                IDENTIFIER_POINTER (DECL_NAME (fndecl)));
-      return error_mark_node;
-    }
 
   arg0 = fold_convert (cmp_type, arg0);
   arg1 = fold_convert (cmp_type, arg1);
@@ -10077,15 +10080,6 @@ fold_builtin_1 (tree fndecl, tree arg0, bool ignore)
     case BUILT_IN_ISNAND128:
       return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISNAN);
 
-    case BUILT_IN_ISNORMAL:
-      if (!validate_arg (arg0, REAL_TYPE))
-       {
-         error ("non-floating-point argument to function %qs",
-                IDENTIFIER_POINTER (DECL_NAME (fndecl)));
-         return error_mark_node;
-       }
-      break;
-
     case BUILT_IN_PRINTF:
     case BUILT_IN_PRINTF_UNLOCKED:
     case BUILT_IN_VPRINTF:
@@ -10431,55 +10425,8 @@ fold_builtin_4 (tree fndecl, tree arg0, tree arg1, tree arg2, tree arg3,
 static tree
 fold_builtin_n (tree fndecl, tree *args, int nargs, bool ignore)
 {
-  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   tree ret = NULL_TREE;
 
-  /* Verify the number of arguments for type-generic and thus variadic
-     builtins.  */
-  switch (fcode)
-    {
-    case BUILT_IN_ISFINITE:
-    case BUILT_IN_ISINF:
-    case BUILT_IN_ISNAN:
-    case BUILT_IN_ISNORMAL:
-      if (nargs < 1)
-       {
-         error ("too few arguments to function %qs",
-                IDENTIFIER_POINTER (DECL_NAME (fndecl)));
-         return error_mark_node;
-       }
-      else if (nargs > 1)
-       {
-         error ("too many arguments to function %qs",
-                IDENTIFIER_POINTER (DECL_NAME (fndecl)));
-         return error_mark_node;
-       }
-      break;
-
-    case BUILT_IN_ISGREATER:
-    case BUILT_IN_ISGREATEREQUAL:
-    case BUILT_IN_ISLESS:
-    case BUILT_IN_ISLESSEQUAL:
-    case BUILT_IN_ISLESSGREATER:
-    case BUILT_IN_ISUNORDERED:
-      if (nargs < 2)
-       {
-         error ("too few arguments to function %qs",
-                IDENTIFIER_POINTER (DECL_NAME (fndecl)));
-         return error_mark_node;
-       }
-      else if (nargs > 2)
-       {
-         error ("too many arguments to function %qs",
-                IDENTIFIER_POINTER (DECL_NAME (fndecl)));
-         return error_mark_node;
-       }
-      break;
-
-    default:
-      break;
-    }
-
   switch (nargs)
     {
     case 0:
@@ -10604,6 +10551,7 @@ fold_call_expr (tree exp, bool ignore)
                  if (CAN_HAVE_LOCATION_P (realret)
                      && !EXPR_HAS_LOCATION (realret))
                    SET_EXPR_LOCATION (realret, EXPR_LOCATION (exp));
+                 return realret;
                }
              return ret;
            }
@@ -10750,6 +10698,8 @@ validate_arg (const_tree arg, enum tree_code code)
     return false;
   else if (code == POINTER_TYPE)
     return POINTER_TYPE_P (TREE_TYPE (arg));
+  else if (code == INTEGER_TYPE)
+    return INTEGRAL_TYPE_P (TREE_TYPE (arg));
   return code == TREE_CODE (TREE_TYPE (arg));
 }
 
@@ -11416,9 +11366,7 @@ fold_builtin_next_arg (tree exp, bool va_start_p)
         is not quite the same as STRIP_NOPS.  It does more.
         We must also strip off INDIRECT_EXPR for C++ reference
         parameters.  */
-      while (TREE_CODE (arg) == NOP_EXPR
-            || TREE_CODE (arg) == CONVERT_EXPR
-            || TREE_CODE (arg) == NON_LVALUE_EXPR
+      while (CONVERT_EXPR_P (arg)
             || TREE_CODE (arg) == INDIRECT_REF)
        arg = TREE_OPERAND (arg, 0);
       if (arg != last_parm)