]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
* asan.c (handle_builtin_alloca): Deal with all alloca variants.
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 19 Oct 2017 15:58:05 +0000 (15:58 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 19 Oct 2017 15:58:05 +0000 (15:58 +0000)
(get_mem_refs_of_builtin_call): Likewise.
* builtins.c (expand_builtin_apply): Adjust call to
allocate_dynamic_stack_space.
(expand_builtin_alloca): For __builtin_alloca_with_align_and_max, pass
the third argument to allocate_dynamic_stack_space, otherwise -1.
(expand_builtin): Deal with all alloca variants.
(is_inexpensive_builtin): Likewise.
* builtins.def (BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX): New.
* calls.c (special_function_p): Deal with all alloca variants.
(initialize_argument_information): Adjust call to
allocate_dynamic_stack_space.
(expand_call): Likewise.
* cfgexpand.c (expand_call_stmt): Deal with all alloca variants.
* doc/extend.texi (Built-ins): Add __builtin_alloca_with_align_and_max
* explow.c (allocate_dynamic_stack_space): Add MAX_SIZE parameter and
use it for the stack usage computation.
* explow.h (allocate_dynamic_stack_space): Adjust prototype.
* function.c (gimplify_parameters): Turn BUILT_IN_ALLOCA_WITH_ALIGN
into BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX and pass maximum size.
* gimple-ssa-warn-alloca.c (alloca_call_type): Simplify control flow.
Take into account 3rd argument of __builtin_alloca_with_align_and_max.
(in_loop_p): Remove first argument and useless check.
(pass_walloca::execute): Remove useless test and adjust call to above.
* gimple.c (gimple_build_call_from_tree): Deal with all alloc variants
* gimplify.c (gimplify_vla_decl): Turn BUILT_IN_ALLOCA_WITH_ALIGN into
BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX and pass maximum size.
(gimplify_call_expr): Deal with all alloca variants.
* hsa-gen.c (gen_hsa_alloca): Likewise.
(gen_hsa_insns_for_call): Likewise.
* ipa-pure-const.c (special_builtin_state): Likewise.
* tree-chkp.c (chkp_build_returned_bound): Likewise.
* tree-object-size.c (alloc_object_size): Likewise.
* tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Likewise.
(call_may_clobber_ref_p_1): Likewise.
* tree-ssa-ccp.c (evaluate_stmt): Likewise.
(ccp_fold_stmt): Likewise.
(optimize_stack_restore): Likewise.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Likewise.
(mark_all_reaching_defs_necessary_1): Likewise.
(propagate_necessity): Likewise.
(eliminate_unnecessary_stmts): Likewise.
* tree.c (build_common_builtin_nodes): Build
BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX.
* tree.h (ALLOCA_FUNCTION_CODE_P): New macro.
(CASE_BUILT_IN_ALLOCA): Likewise.
* varasm.c (incorporeal_function_p): Deal with all alloca variants.
c-family/
* c-common.c (check_builtin_function_arguments): Also check arguments
of __builtin_alloca_with_align_and_max.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@253901 138bc75d-0d04-0410-961f-82ee72b054a4

29 files changed:
gcc/ChangeLog
gcc/asan.c
gcc/builtins.c
gcc/builtins.def
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/calls.c
gcc/cfgexpand.c
gcc/doc/extend.texi
gcc/explow.c
gcc/explow.h
gcc/function.c
gcc/gimple-ssa-warn-alloca.c
gcc/gimple.c
gcc/gimplify.c
gcc/hsa-gen.c
gcc/ipa-pure-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/Walloca-15.c [new file with mode: 0644]
gcc/testsuite/gnat.dg/stack_usage4.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/stack_usage4_pkg.ads [new file with mode: 0644]
gcc/tree-chkp.c
gcc/tree-object-size.c
gcc/tree-ssa-alias.c
gcc/tree-ssa-ccp.c
gcc/tree-ssa-dce.c
gcc/tree.c
gcc/tree.h
gcc/varasm.c

index d8619c106cae9ca0bc38343727f1e0ea4729441e..c63d73424a73343e228a795748e87664ed33aed1 100644 (file)
@@ -1,3 +1,53 @@
+2017-10-19  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * asan.c (handle_builtin_alloca): Deal with all alloca variants.
+       (get_mem_refs_of_builtin_call): Likewise.
+       * builtins.c (expand_builtin_apply): Adjust call to
+       allocate_dynamic_stack_space.
+       (expand_builtin_alloca): For __builtin_alloca_with_align_and_max, pass
+       the third argument to allocate_dynamic_stack_space, otherwise -1.
+       (expand_builtin): Deal with all alloca variants.
+       (is_inexpensive_builtin): Likewise.
+       * builtins.def (BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX): New.
+       * calls.c (special_function_p): Deal with all alloca variants.
+       (initialize_argument_information): Adjust call to
+       allocate_dynamic_stack_space.
+       (expand_call): Likewise.
+       * cfgexpand.c (expand_call_stmt): Deal with all alloca variants.
+       * doc/extend.texi (Built-ins): Add __builtin_alloca_with_align_and_max
+       * explow.c (allocate_dynamic_stack_space): Add MAX_SIZE parameter and
+       use it for the stack usage computation.
+       * explow.h (allocate_dynamic_stack_space): Adjust prototype.
+       * function.c (gimplify_parameters): Turn BUILT_IN_ALLOCA_WITH_ALIGN
+       into BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX and pass maximum size.
+       * gimple-ssa-warn-alloca.c (alloca_call_type): Simplify control flow.
+       Take into account 3rd argument of __builtin_alloca_with_align_and_max.
+       (in_loop_p): Remove first argument and useless check.
+       (pass_walloca::execute): Remove useless test and adjust call to above.
+       * gimple.c (gimple_build_call_from_tree): Deal with all alloc variants
+       * gimplify.c (gimplify_vla_decl): Turn BUILT_IN_ALLOCA_WITH_ALIGN into
+       BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX and pass maximum size.
+       (gimplify_call_expr): Deal with all alloca variants.
+       * hsa-gen.c (gen_hsa_alloca): Likewise.
+       (gen_hsa_insns_for_call): Likewise.
+       * ipa-pure-const.c (special_builtin_state): Likewise.
+       * tree-chkp.c (chkp_build_returned_bound): Likewise.
+       * tree-object-size.c (alloc_object_size): Likewise.
+       * tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Likewise.
+       (call_may_clobber_ref_p_1): Likewise.
+       * tree-ssa-ccp.c (evaluate_stmt): Likewise.
+       (ccp_fold_stmt): Likewise.
+       (optimize_stack_restore): Likewise.
+       * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Likewise.
+       (mark_all_reaching_defs_necessary_1): Likewise.
+       (propagate_necessity): Likewise.
+       (eliminate_unnecessary_stmts): Likewise.
+       * tree.c (build_common_builtin_nodes): Build
+       BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX.
+       * tree.h (ALLOCA_FUNCTION_CODE_P): New macro.
+       (CASE_BUILT_IN_ALLOCA): Likewise.
+       * varasm.c (incorporeal_function_p): Deal with all alloca variants.
+
 2017-10-19  Eric Botcazou  <ebotcazou@adacore.com>
 
        PR debug/82509
index 99958ecc330e751c38d56bbc2ad6e2448be986f4..be8b79e3554fcd3581b7fcc238aa81693a210d23 100644 (file)
@@ -628,10 +628,9 @@ handle_builtin_alloca (gcall *call, gimple_stmt_iterator *iter)
   tree ptr_type = gimple_call_lhs (call) ? TREE_TYPE (gimple_call_lhs (call))
                                         : ptr_type_node;
   tree partial_size = NULL_TREE;
-  bool alloca_with_align
-    = DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA_WITH_ALIGN;
   unsigned int align
-    = alloca_with_align ? tree_to_uhwi (gimple_call_arg (call, 1)) : 0;
+    = DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
+      ? 0 : tree_to_uhwi (gimple_call_arg (call, 1));
 
   /* If ALIGN > ASAN_RED_ZONE_SIZE, we embed left redzone into first ALIGN
      bytes of allocated space.  Otherwise, align alloca to ASAN_RED_ZONE_SIZE
@@ -793,8 +792,7 @@ get_mem_refs_of_builtin_call (gcall *call,
       handle_builtin_stack_restore (call, iter);
       break;
 
-    case BUILT_IN_ALLOCA_WITH_ALIGN:
-    case BUILT_IN_ALLOCA:
+    CASE_BUILT_IN_ALLOCA:
       handle_builtin_alloca (call, iter);
       break;
     /* And now the __atomic* and __sync builtins.
index 28fc76b5fc0f547262d1203ca211a9843db3100a..d3498bb16c47995e68a0d6406ecf6f3d227ce74e 100644 (file)
@@ -1609,7 +1609,7 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
      arguments to the outgoing arguments address.  We can pass TRUE
      as the 4th argument because we just saved the stack pointer
      and will restore it right after the call.  */
-  allocate_dynamic_stack_space (argsize, 0, BIGGEST_ALIGNMENT, true);
+  allocate_dynamic_stack_space (argsize, 0, BIGGEST_ALIGNMENT, -1, true);
 
   /* Set DRAP flag to true, even though allocate_dynamic_stack_space
      may have already set current_function_calls_alloca to true.
@@ -4858,19 +4858,22 @@ expand_builtin_alloca (tree exp)
   rtx result;
   unsigned int align;
   tree fndecl = get_callee_fndecl (exp);
-  bool alloca_with_align = (DECL_FUNCTION_CODE (fndecl)
-                           == BUILT_IN_ALLOCA_WITH_ALIGN);
+  HOST_WIDE_INT max_size;
+  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   bool alloca_for_var = CALL_ALLOCA_FOR_VAR_P (exp);
   bool valid_arglist
-    = (alloca_with_align
-       ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
-       : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
+    = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
+       ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, INTEGER_TYPE,
+                          VOID_TYPE)
+       : fcode == BUILT_IN_ALLOCA_WITH_ALIGN
+        ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
+        : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
 
   if (!valid_arglist)
     return NULL_RTX;
 
-  if ((alloca_with_align && !warn_vla_limit)
-      || (!alloca_with_align && !warn_alloca_limit))
+  if ((alloca_for_var && !warn_vla_limit)
+      || (!alloca_for_var && !warn_alloca_limit))
     {
       /* -Walloca-larger-than and -Wvla-larger-than settings override
         the more general -Walloc-size-larger-than so unless either of
@@ -4885,13 +4888,19 @@ expand_builtin_alloca (tree exp)
   op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
 
   /* Compute the alignment.  */
-  align = (alloca_with_align
-          ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1))
-          : BIGGEST_ALIGNMENT);
+  align = (fcode == BUILT_IN_ALLOCA
+          ? BIGGEST_ALIGNMENT
+          : TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1)));
+
+  /* Compute the maximum size.  */
+  max_size = (fcode == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
+              ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 2))
+              : -1);
 
   /* Allocate the desired space.  If the allocation stems from the declaration
      of a variable-sized object, it cannot accumulate.  */
-  result = allocate_dynamic_stack_space (op0, 0, align, alloca_for_var);
+  result
+    = allocate_dynamic_stack_space (op0, 0, align, max_size, alloca_for_var);
   result = convert_memory_address (ptr_mode, result);
 
   return result;
@@ -6482,8 +6491,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
       && fcode != BUILT_IN_EXECLE
       && fcode != BUILT_IN_EXECVP
       && fcode != BUILT_IN_EXECVE
-      && fcode != BUILT_IN_ALLOCA
-      && fcode != BUILT_IN_ALLOCA_WITH_ALIGN
+      && !ALLOCA_FUNCTION_CODE_P (fcode)
       && fcode != BUILT_IN_FREE
       && fcode != BUILT_IN_CHKP_SET_PTR_BOUNDS
       && fcode != BUILT_IN_CHKP_INIT_PTR_BOUNDS
@@ -6712,8 +6720,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
       else
        return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
 
-    case BUILT_IN_ALLOCA:
-    case BUILT_IN_ALLOCA_WITH_ALIGN:
+    CASE_BUILT_IN_ALLOCA:
       target = expand_builtin_alloca (exp);
       if (target)
        return target;
@@ -10425,8 +10432,7 @@ is_inexpensive_builtin (tree decl)
     switch (DECL_FUNCTION_CODE (decl))
       {
       case BUILT_IN_ABS:
-      case BUILT_IN_ALLOCA:
-      case BUILT_IN_ALLOCA_WITH_ALIGN:
+      CASE_BUILT_IN_ALLOCA:
       case BUILT_IN_BSWAP16:
       case BUILT_IN_BSWAP32:
       case BUILT_IN_BSWAP64:
index 1c1efceea217339643aea1ec4f4e0e2423c90da2..880259422065734604ea82cf27e9753ee8b1c996 100644 (file)
@@ -921,6 +921,7 @@ DEF_BUILTIN_STUB (BUILT_IN_SETJMP_RECEIVER, "__builtin_setjmp_receiver")
 DEF_BUILTIN_STUB (BUILT_IN_STACK_SAVE, "__builtin_stack_save")
 DEF_BUILTIN_STUB (BUILT_IN_STACK_RESTORE, "__builtin_stack_restore")
 DEF_BUILTIN_STUB (BUILT_IN_ALLOCA_WITH_ALIGN, "__builtin_alloca_with_align")
+DEF_BUILTIN_STUB (BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX, "__builtin_alloca_with_align_and_max")
 
 /* An internal version of memcmp, used when the result is only tested for
    equality with zero.  */
index ef1211523a471e724b33d02e1c35a09acd56738c..963c79a7e2b95296d83feee37f69fb8522bd7820 100644 (file)
@@ -1,3 +1,8 @@
+2017-10-19  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * c-common.c (check_builtin_function_arguments): Also check arguments
+       of __builtin_alloca_with_align_and_max.
+
 2017-10-17  David Malcolm  <dmalcolm@redhat.com>
 
        * c-format.c (format_warning_at_char): Pass UNKNOWN_LOCATION
index dfcfb1960285d0f9afd2d5313bbbe804ce4286a2..8f36c77967faaa942808549264fc6721fa940d5a 100644 (file)
@@ -5695,6 +5695,16 @@ check_builtin_function_arguments (location_t loc, vec<location_t> arg_loc,
 
   switch (DECL_FUNCTION_CODE (fndecl))
     {
+    case BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX:
+      if (!tree_fits_uhwi_p (args[2]))
+       {
+         error_at (ARG_LOCATION (2),
+                   "third argument to function %qE must be a constant integer",
+                   fndecl);
+         return false;
+       }
+      /* fall through */
+
     case BUILT_IN_ALLOCA_WITH_ALIGN:
       {
        /* Get the requested alignment (in bits) if it's a constant
index 7ed05d40d86b13fed4343715394b1693301e189a..3730f43c7a9640de804683aea6cb72383b61f7ec 100644 (file)
@@ -607,16 +607,9 @@ special_function_p (const_tree fndecl, int flags)
        flags |= ECF_RETURNS_TWICE;
     }
 
-  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
-    switch (DECL_FUNCTION_CODE (fndecl))
-      {
-      case BUILT_IN_ALLOCA:
-      case BUILT_IN_ALLOCA_WITH_ALIGN:
-       flags |= ECF_MAY_BE_ALLOCA;
-       break;
-      default:
-       break;
-      }
+  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+      && ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (fndecl)))
+    flags |= ECF_MAY_BE_ALLOCA;
 
   return flags;
 }
@@ -698,8 +691,7 @@ gimple_alloca_call_p (const gimple *stmt)
   if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
     switch (DECL_FUNCTION_CODE (fndecl))
       {
-      case BUILT_IN_ALLOCA:
-      case BUILT_IN_ALLOCA_WITH_ALIGN:
+      CASE_BUILT_IN_ALLOCA:
         return true;
       default:
        break;
@@ -719,8 +711,7 @@ alloca_call_p (const_tree exp)
       && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
     switch (DECL_FUNCTION_CODE (fndecl))
       {
-      case BUILT_IN_ALLOCA:
-      case BUILT_IN_ALLOCA_WITH_ALIGN:
+      CASE_BUILT_IN_ALLOCA:
         return true;
       default:
        break;
@@ -1819,6 +1810,8 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
                  copy = allocate_dynamic_stack_space (size_rtx,
                                                       TYPE_ALIGN (type),
                                                       TYPE_ALIGN (type),
+                                                      max_int_size_in_bytes
+                                                      (type),
                                                       true);
                  copy = gen_rtx_MEM (BLKmode, copy);
                  set_mem_attributes (copy, type, 1);
@@ -3638,8 +3631,8 @@ expand_call (tree exp, rtx target, int ignore)
              /* We can pass TRUE as the 4th argument because we just
                 saved the stack pointer and will restore it right after
                 the call.  */
-             allocate_dynamic_stack_space (push_size, 0,
-                                           BIGGEST_ALIGNMENT, true);
+             allocate_dynamic_stack_space (push_size, 0, BIGGEST_ALIGNMENT,
+                                           -1, true);
            }
 
          /* If argument evaluation might modify the stack pointer,
index be93c5843e50c6157edd61437240c9f578152540..df60f80491ca5b66a363b6b568edb2960cc53f33 100644 (file)
@@ -2634,8 +2634,7 @@ expand_call_stmt (gcall *stmt)
   CALL_EXPR_RETURN_SLOT_OPT (exp) = gimple_call_return_slot_opt_p (stmt);
   if (decl
       && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
-      && (DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA
-         || DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA_WITH_ALIGN))
+      && ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (decl)))
     CALL_ALLOCA_FOR_VAR_P (exp) = gimple_call_alloca_for_var_p (stmt);
   else
     CALL_FROM_THUNK_P (exp) = gimple_call_from_thunk_p (stmt);
index d9b7a540cbdc22f670b2aea642be92381eebabdf..768751f58a1ec7a98ec2af86fdc1f3e00b67ea2f 100644 (file)
@@ -10869,6 +10869,7 @@ in the Cilk Plus language manual which can be found at
 @cindex built-in functions
 @findex __builtin_alloca
 @findex __builtin_alloca_with_align
+@findex __builtin_alloca_with_align_and_max
 @findex __builtin_call_with_static_chain
 @findex __builtin_fpclassify
 @findex __builtin_isfinite
@@ -11516,6 +11517,16 @@ an extension.  @xref{Variable Length}, for details.
 
 @end deftypefn
 
+@deftypefn {Built-in Function} void *__builtin_alloca_with_align_and_max (size_t size, size_t alignment, size_t max_size)
+Similar to @code{__builtin_alloca_with_align} but takes an extra argument
+specifying an upper bound for @var{size} in case its value cannot be computed
+at compile time, for use by @option{-fstack-usage}, @option{-Wstack-usage}
+and @option{-Walloca-larger-than}.  @var{max_size} must be a constant integer
+expression, it has no effect on code generation and no attempt is made to
+check its compatibility with @var{size}.
+
+@end deftypefn
+
 @deftypefn {Built-in Function} int __builtin_types_compatible_p (@var{type1}, @var{type2})
 
 You can use the built-in function @code{__builtin_types_compatible_p} to
index 6131d1810cba13f4330ddadc78d345a72fcfc803..662865d2808beceafd28ce72def65c5964037a0b 100644 (file)
@@ -1322,6 +1322,9 @@ get_stack_check_protect (void)
    REQUIRED_ALIGN is the alignment (in bits) required for the region
    of memory.
 
+   MAX_SIZE is an upper bound for SIZE, if SIZE is not constant, or -1 if
+   no such upper bound is known.
+
    If CANNOT_ACCUMULATE is set to TRUE, the caller guarantees that the
    stack space allocated by the generated code cannot be added with itself
    in the course of the execution of the function.  It is always safe to
@@ -1331,7 +1334,9 @@ get_stack_check_protect (void)
 
 rtx
 allocate_dynamic_stack_space (rtx size, unsigned size_align,
-                             unsigned required_align, bool cannot_accumulate)
+                             unsigned required_align,
+                             HOST_WIDE_INT max_size,
+                             bool cannot_accumulate)
 {
   HOST_WIDE_INT stack_usage_size = -1;
   rtx_code_label *final_label;
@@ -1370,8 +1375,12 @@ allocate_dynamic_stack_space (rtx size, unsigned size_align,
            }
        }
 
-      /* If the size is not constant, we can't say anything.  */
-      if (stack_usage_size == -1)
+      /* If the size is not constant, try the maximum size.  */
+      if (stack_usage_size < 0)
+       stack_usage_size = max_size;
+
+      /* If the size is still not constant, we can't say anything.  */
+      if (stack_usage_size < 0)
        {
          current_function_has_unbounded_dynamic_stack_size = 1;
          stack_usage_size = 0;
index b85c051e8ce90e1cb396521f387ac176b964f55d..8eca20b2fd28f6061ee96d8688c370a04fe86549 100644 (file)
@@ -94,7 +94,8 @@ extern void update_nonlocal_goto_save_area (void);
 extern void record_new_stack_level (void);
 
 /* Allocate some space on the stack dynamically and return its address.  */
-extern rtx allocate_dynamic_stack_space (rtx, unsigned, unsigned, bool);
+extern rtx allocate_dynamic_stack_space (rtx, unsigned, unsigned,
+                                        HOST_WIDE_INT, bool);
 
 /* Calculate the necessary size of a constant dynamic stack allocation from the
    size of the variable area.  */
index c03e2ac514270e32da3c16439f6f38f169b40f1f..10bcefb2cfe617ae8012b0f1a70bceec7aeca53d 100644 (file)
@@ -4049,10 +4049,9 @@ gimplify_parameters (void)
                  DECL_IGNORED_P (addr) = 0;
                  local = build_fold_indirect_ref (addr);
 
-                 t = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
-                 t = build_call_expr (t, 2, DECL_SIZE_UNIT (parm),
-                                      size_int (DECL_ALIGN (parm)));
-
+                 t = build_alloca_call_expr (DECL_SIZE_UNIT (parm),
+                                             DECL_ALIGN (parm),
+                                             max_int_size_in_bytes (type));
                  /* The call has been built for a variable-sized object.  */
                  CALL_ALLOCA_FOR_VAR_P (t) = 1;
                  t = fold_convert (ptr_type, t);
index 2d255a493d024a5c34b4b4f02b45255cb9053807..08c2195575a0302de13a045ac5dd711090a713c2 100644 (file)
@@ -264,7 +264,7 @@ is_max (tree x, wide_int max)
 
 // Analyze the alloca call in STMT and return the alloca type with its
 // corresponding limit (if applicable).  IS_VLA is set if the alloca
-// call is really a BUILT_IN_ALLOCA_WITH_ALIGN, signifying a VLA.
+// call was created by the gimplifier for a VLA.
 //
 // If the alloca call may be too large because of a cast from a signed
 // type to an unsigned type, set *INVALID_CASTED_TYPE to the
@@ -278,7 +278,8 @@ alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type)
   tree len = gimple_call_arg (stmt, 0);
   tree len_casted = NULL;
   wide_int min, max;
-  struct alloca_type_and_limit ret = alloca_type_and_limit (ALLOCA_UNBOUNDED);
+  edge_iterator ei;
+  edge e;
 
   gcc_assert (!is_vla || (unsigned HOST_WIDE_INT) warn_vla_limit > 0);
   gcc_assert (is_vla || (unsigned HOST_WIDE_INT) warn_alloca_limit > 0);
@@ -299,16 +300,18 @@ alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type)
                                      wi::to_wide (len));
       if (integer_zerop (len))
        return alloca_type_and_limit (ALLOCA_ARG_IS_ZERO);
-      ret = alloca_type_and_limit (ALLOCA_OK);
+
+      return alloca_type_and_limit (ALLOCA_OK);
     }
+
   // Check the range info if available.
-  else if (TREE_CODE (len) == SSA_NAME)
+  if (TREE_CODE (len) == SSA_NAME)
     {
       value_range_type range_type = get_range_info (len, &min, &max);
       if (range_type == VR_RANGE)
        {
          if (wi::leu_p (max, max_size))
-           ret = alloca_type_and_limit (ALLOCA_OK);
+           return alloca_type_and_limit (ALLOCA_OK);
          else
            {
              // A cast may have created a range we don't care
@@ -391,52 +394,41 @@ alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type)
   // If we couldn't find anything, try a few heuristics for things we
   // can easily determine.  Check these misc cases but only accept
   // them if all predecessors have a known bound.
-  basic_block bb = gimple_bb (stmt);
-  if (ret.type == ALLOCA_UNBOUNDED)
+  struct alloca_type_and_limit ret = alloca_type_and_limit (ALLOCA_OK);
+  FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds)
     {
-      ret.type = ALLOCA_OK;
-      for (unsigned ix = 0; ix < EDGE_COUNT (bb->preds); ix++)
-       {
-         gcc_assert (!len_casted || TYPE_UNSIGNED (TREE_TYPE (len_casted)));
-         ret = alloca_call_type_by_arg (len, len_casted,
-                                        EDGE_PRED (bb, ix), max_size);
-         if (ret.type != ALLOCA_OK)
-           break;
-       }
+      gcc_assert (!len_casted || TYPE_UNSIGNED (TREE_TYPE (len_casted)));
+      ret = alloca_call_type_by_arg (len, len_casted, e, max_size);
+      if (ret.type != ALLOCA_OK)
+       break;
+    }
+
+  if (ret.type != ALLOCA_OK && tentative_cast_from_signed)
+    ret = alloca_type_and_limit (ALLOCA_CAST_FROM_SIGNED);
+
+  // If we have a declared maximum size, we can take it into account.
+  if (ret.type != ALLOCA_OK
+      && gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX))
+    {
+      tree arg = gimple_call_arg (stmt, 2);
+      if (compare_tree_int (arg, max_size) <= 0)
+       ret = alloca_type_and_limit (ALLOCA_OK);
+      else
+       ret = alloca_type_and_limit (ALLOCA_BOUND_MAYBE_LARGE,
+                                    wi::to_wide (arg));
     }
 
-  if (tentative_cast_from_signed && ret.type != ALLOCA_OK)
-    return alloca_type_and_limit (ALLOCA_CAST_FROM_SIGNED);
   return ret;
 }
 
-// Return TRUE if the alloca call in STMT is in a loop, otherwise
-// return FALSE. As an exception, ignore alloca calls for VLAs that
-// occur in a loop since those will be cleaned up when they go out of
-// scope.
+// Return TRUE if STMT is in a loop, otherwise return FALSE.
 
 static bool
-in_loop_p (bool is_vla, gimple *stmt)
+in_loop_p (gimple *stmt)
 {
   basic_block bb = gimple_bb (stmt);
-  if (bb->loop_father
-      && bb->loop_father->header != ENTRY_BLOCK_PTR_FOR_FN (cfun))
-    {
-      // Do not warn on VLAs occurring in a loop, since VLAs are
-      // guaranteed to be cleaned up when they go out of scope.
-      // That is, there is a corresponding __builtin_stack_restore
-      // at the end of the scope in which the VLA occurs.
-      tree fndecl = gimple_call_fn (stmt);
-      while (TREE_CODE (fndecl) == ADDR_EXPR)
-       fndecl = TREE_OPERAND (fndecl, 0);
-      if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
-         && is_vla
-         && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA_WITH_ALIGN)
-       return false;
-
-      return true;
-    }
-  return false;
+  return
+    bb->loop_father && bb->loop_father->header != ENTRY_BLOCK_PTR_FOR_FN (cfun);
 }
 
 unsigned int
@@ -455,8 +447,8 @@ pass_walloca::execute (function *fun)
            continue;
          gcc_assert (gimple_call_num_args (stmt) >= 1);
 
-         bool is_vla = gimple_alloca_call_p (stmt)
-           && gimple_call_alloca_for_var_p (as_a <gcall *> (stmt));
+         const bool is_vla
+           = gimple_call_alloca_for_var_p (as_a <gcall *> (stmt));
 
          // Strict mode whining for VLAs is handled by the front-end,
          // so we can safely ignore this case.  Also, ignore VLAs if
@@ -476,9 +468,10 @@ pass_walloca::execute (function *fun)
          struct alloca_type_and_limit t
            = alloca_call_type (stmt, is_vla, &invalid_casted_type);
 
-         // Even if we think the alloca call is OK, make sure it's
-         // not in a loop.
-         if (t.type == ALLOCA_OK && in_loop_p (is_vla, stmt))
+         // Even if we think the alloca call is OK, make sure it's not in a
+         // loop, except for a VLA, since VLAs are guaranteed to be cleaned
+         // up when they go out of scope, including in a loop.
+         if (t.type == ALLOCA_OK && !is_vla && in_loop_p (stmt))
            t = alloca_type_and_limit (ALLOCA_IN_LOOP);
 
          enum opt_code wcode
index 79213b22c24d769e3945f32533c47c69f0f815c9..aaf1cc2060fcee5b824e2afceca89feed9adfabc 100644 (file)
@@ -369,8 +369,7 @@ gimple_build_call_from_tree (tree t)
   gimple_call_set_return_slot_opt (call, CALL_EXPR_RETURN_SLOT_OPT (t));
   if (fndecl
       && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
-      && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA
-         || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA_WITH_ALIGN))
+      && ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (fndecl)))
     gimple_call_set_alloca_for_var (call, CALL_ALLOCA_FOR_VAR_P (t));
   else
     gimple_call_set_from_thunk (call, CALL_FROM_THUNK_P (t));
index 19411c98fce26c7d6929fd1bf46923f44019be7b..2c1ec852210a413f4565951bb398604c7ffb864b 100644 (file)
@@ -1574,9 +1574,8 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
   SET_DECL_VALUE_EXPR (decl, t);
   DECL_HAS_VALUE_EXPR_P (decl) = 1;
 
-  t = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
-  t = build_call_expr (t, 2, DECL_SIZE_UNIT (decl),
-                      size_int (DECL_ALIGN (decl)));
+  t = build_alloca_call_expr (DECL_SIZE_UNIT (decl), DECL_ALIGN (decl),
+                             max_int_size_in_bytes (TREE_TYPE (decl)));
   /* The call has been built for a variable-sized object.  */
   CALL_ALLOCA_FOR_VAR_P (t) = 1;
   t = fold_convert (ptr_type, t);
@@ -3174,8 +3173,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
       && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
     switch (DECL_FUNCTION_CODE (fndecl))
       {
-      case BUILT_IN_ALLOCA:
-      case BUILT_IN_ALLOCA_WITH_ALIGN:
+      CASE_BUILT_IN_ALLOCA:
        /* If the call has been built for a variable-sized object, then we
           want to restore the stack level when the enclosing BIND_EXPR is
           exited to reclaim the allocated space; otherwise, we precisely
index b5a8c73731af4dfad2a8edf596513001ab937a1d..d89d12084eb269b719fbd8e5c4ad8e3e8ddc7758 100644 (file)
@@ -4238,12 +4238,11 @@ gen_hsa_alloca (gcall *call, hsa_bb *hbb)
 
   built_in_function fn = DECL_FUNCTION_CODE (gimple_call_fndecl (call));
 
-  gcc_checking_assert (fn == BUILT_IN_ALLOCA
-                      || fn == BUILT_IN_ALLOCA_WITH_ALIGN);
+  gcc_checking_assert (ALLOCA_FUNCTION_CODE_P (fn));
 
   unsigned bit_alignment = 0;
 
-  if (fn == BUILT_IN_ALLOCA_WITH_ALIGN)
+  if (fn != BUILT_IN_ALLOCA)
     {
       tree alignment_tree = gimple_call_arg (call, 1);
       if (TREE_CODE (alignment_tree) != INTEGER_CST)
@@ -5656,8 +5655,7 @@ gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb)
 
        break;
       }
-    case BUILT_IN_ALLOCA:
-    case BUILT_IN_ALLOCA_WITH_ALIGN:
+    CASE_BUILT_IN_ALLOCA:
       {
        gen_hsa_alloca (call, hbb);
        break;
index 915423559cb439f8c2bb2eddf50c02e5f9dd9c82..3c06e2d303328343be557e66a0f9dc32098fbef7 100644 (file)
@@ -518,8 +518,7 @@ special_builtin_state (enum pure_const_state_e *state, bool *looping,
       {
        case BUILT_IN_RETURN:
        case BUILT_IN_UNREACHABLE:
-       case BUILT_IN_ALLOCA:
-       case BUILT_IN_ALLOCA_WITH_ALIGN:
+       CASE_BUILT_IN_ALLOCA:
        case BUILT_IN_STACK_SAVE:
        case BUILT_IN_STACK_RESTORE:
        case BUILT_IN_EH_POINTER:
index 3b2f638dba7584bc110a7dd735011056c1db8be9..138899afb8211ec8ddf81aa9e0b706b6a9bb8f36 100644 (file)
@@ -1,3 +1,9 @@
+2017-10-19  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.dg/Walloca-15.c: New test.
+       * gnat.dg/stack_usage4.adb: Likewise.
+       * gnat.dg/stack_usage4_pkg.ads: New helper.
+
 2017-10-19  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/82600
diff --git a/gcc/testsuite/gcc.dg/Walloca-15.c b/gcc/testsuite/gcc.dg/Walloca-15.c
new file mode 100644 (file)
index 0000000..f34ffd9
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target alloca } */
+/* { dg-options "-Walloca-larger-than=128 -O2" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+void bar (void*);
+
+void foo1 (size_t len)
+{
+  bar (__builtin_alloca_with_align_and_max (len, 8, 128));
+}
+
+void foo2 (size_t len)
+{
+  bar (__builtin_alloca_with_align_and_max (len, 8, 256)); /* { dg-warning "may be too large" } */
+}
diff --git a/gcc/testsuite/gnat.dg/stack_usage4.adb b/gcc/testsuite/gnat.dg/stack_usage4.adb
new file mode 100644 (file)
index 0000000..24cd1a7
--- /dev/null
@@ -0,0 +1,11 @@
+-- { dg-do compile }
+-- { dg-options "-Wstack-usage=512" }
+
+with Stack_Usage4_Pkg; use Stack_Usage4_Pkg;
+
+procedure Stack_Usage4 is
+   BS : Bounded_String := Get;
+   S : String := BS.Data (BS.Data'First .. BS.Len);
+begin
+   null;
+end;
diff --git a/gcc/testsuite/gnat.dg/stack_usage4_pkg.ads b/gcc/testsuite/gnat.dg/stack_usage4_pkg.ads
new file mode 100644 (file)
index 0000000..9bad627
--- /dev/null
@@ -0,0 +1,12 @@
+package Stack_Usage4_Pkg is
+
+   subtype Name_Index_Type is Natural range 1 .. 63;
+
+   type Bounded_String is record
+      Len  : Name_Index_Type;
+      Data : String (Name_Index_Type'Range);
+   end record;
+
+   function Get return Bounded_String;
+
+end Stack_Usage4_Pkg;
index 951aec10b3ad8ce2e8fa79c3baf769eee92e27ed..025155aca72b854e7377b5b0965f03538dd158f2 100644 (file)
@@ -2276,8 +2276,7 @@ chkp_build_returned_bound (gcall *call)
      it separately.  */
   if (fndecl
       && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
-      && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA
-         || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA_WITH_ALIGN))
+      && ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (fndecl)))
     {
       tree size = gimple_call_arg (call, 0);
       gimple_stmt_iterator iter = gsi_for_stmt (call);
index a56b78a4510388f075fa2aeb23f4c4703565f944..d45f50d4173e6f040840949750aba1a7a96724e1 100644 (file)
@@ -430,8 +430,7 @@ alloc_object_size (const gcall *call, int object_size_type)
        arg2 = 1;
        /* fall through */
       case BUILT_IN_MALLOC:
-      case BUILT_IN_ALLOCA:
-      case BUILT_IN_ALLOCA_WITH_ALIGN:
+      CASE_BUILT_IN_ALLOCA:
        arg1 = 0;
       default:
        break;
index 9bbc163b1c3206c5b7a9065dbac2a96acf8e7fb3..5340fd350bc434fdf7b7b13ec5a5d8d9b0c7481a 100644 (file)
@@ -1779,8 +1779,7 @@ ref_maybe_used_by_call_p_1 (gcall *call, ao_ref *ref)
        case BUILT_IN_POSIX_MEMALIGN:
        case BUILT_IN_ALIGNED_ALLOC:
        case BUILT_IN_CALLOC:
-       case BUILT_IN_ALLOCA:
-       case BUILT_IN_ALLOCA_WITH_ALIGN:
+       CASE_BUILT_IN_ALLOCA:
        case BUILT_IN_STACK_SAVE:
        case BUILT_IN_STACK_RESTORE:
        case BUILT_IN_MEMSET:
@@ -2118,8 +2117,7 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref)
            return true;
          return false;
        case BUILT_IN_STACK_SAVE:
-       case BUILT_IN_ALLOCA:
-       case BUILT_IN_ALLOCA_WITH_ALIGN:
+       CASE_BUILT_IN_ALLOCA:
        case BUILT_IN_ASSUME_ALIGNED:
          return false;
        /* But posix_memalign stores a pointer into the memory pointed to
index 439bb0a8b40f31c5d3d4968f2715c10f83da8121..569b057094171c900b5b75ae9dc57f5bb8c8ae4f 100644 (file)
@@ -1886,11 +1886,10 @@ evaluate_stmt (gimple *stmt)
                           / BITS_PER_UNIT - 1);
              break;
 
-           case BUILT_IN_ALLOCA:
-           case BUILT_IN_ALLOCA_WITH_ALIGN:
-             align = (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA_WITH_ALIGN
-                      ? TREE_INT_CST_LOW (gimple_call_arg (stmt, 1))
-                      : BIGGEST_ALIGNMENT);
+           CASE_BUILT_IN_ALLOCA:
+             align = (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA
+                      ? BIGGEST_ALIGNMENT
+                      : TREE_INT_CST_LOW (gimple_call_arg (stmt, 1)));
              val.lattice_val = CONSTANT;
              val.value = build_int_cst (TREE_TYPE (gimple_get_lhs (stmt)), 0);
              val.mask = ~((HOST_WIDE_INT) align / BITS_PER_UNIT - 1);
@@ -2243,7 +2242,8 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
         /* The heuristic of fold_builtin_alloca_with_align differs before and
           after inlining, so we don't require the arg to be changed into a
           constant for folding, but just to be constant.  */
-        if (gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN))
+        if (gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN)
+           || gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX))
           {
             tree new_rhs = fold_builtin_alloca_with_align (stmt);
             if (new_rhs)
@@ -2535,8 +2535,7 @@ optimize_stack_restore (gimple_stmt_iterator i)
       if (!callee
          || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
          /* All regular builtins are ok, just obviously not alloca.  */
-         || DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
-         || DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA_WITH_ALIGN)
+         || ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (callee)))
        return NULL_TREE;
 
       if (DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE)
index e62afad1bea7e3c1adf42a1c323aa9fdadfc20ec..59dd3f3038a86e573dc3ce9df7394082a11cc03e 100644 (file)
@@ -231,8 +231,7 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
            case BUILT_IN_MALLOC:
            case BUILT_IN_ALIGNED_ALLOC:
            case BUILT_IN_CALLOC:
-           case BUILT_IN_ALLOCA:
-           case BUILT_IN_ALLOCA_WITH_ALIGN:
+           CASE_BUILT_IN_ALLOCA:
            case BUILT_IN_STRDUP:
            case BUILT_IN_STRNDUP:
              return;
@@ -576,8 +575,7 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED,
          case BUILT_IN_MALLOC:
          case BUILT_IN_ALIGNED_ALLOC:
          case BUILT_IN_CALLOC:
-         case BUILT_IN_ALLOCA:
-         case BUILT_IN_ALLOCA_WITH_ALIGN:
+         CASE_BUILT_IN_ALLOCA:
          case BUILT_IN_FREE:
            return false;
 
@@ -845,9 +843,7 @@ propagate_necessity (bool aggressive)
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_CALLOC
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_FREE
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_VA_END
-                     || DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
-                     || (DECL_FUNCTION_CODE (callee)
-                         == BUILT_IN_ALLOCA_WITH_ALIGN)
+                     || ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (callee))
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_SAVE
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_ASSUME_ALIGNED))
@@ -1348,9 +1344,8 @@ eliminate_unnecessary_stmts (void)
                      || (DECL_FUNCTION_CODE (call) != BUILT_IN_ALIGNED_ALLOC
                          && DECL_FUNCTION_CODE (call) != BUILT_IN_MALLOC
                          && DECL_FUNCTION_CODE (call) != BUILT_IN_CALLOC
-                         && DECL_FUNCTION_CODE (call) != BUILT_IN_ALLOCA
-                         && (DECL_FUNCTION_CODE (call)
-                             != BUILT_IN_ALLOCA_WITH_ALIGN)))
+                         && !ALLOCA_FUNCTION_CODE_P
+                             (DECL_FUNCTION_CODE (call))))
                  /* Avoid doing so for bndret calls for the same reason.  */
                  && !chkp_gimple_call_builtin_p (stmt, BUILT_IN_CHKP_BNDRET))
                {
index cd77f08a331944ee5548572f2e01f799a4daff62..1b20ad6e9e8aeb25dc939227e8dee6fcaa99636f 100644 (file)
@@ -9975,6 +9975,13 @@ build_common_builtin_nodes (void)
                        "__builtin_alloca_with_align",
                        alloca_flags);
 
+  ftype = build_function_type_list (ptr_type_node, size_type_node,
+                                   size_type_node, size_type_node, NULL_TREE);
+  local_define_builtin ("__builtin_alloca_with_align_and_max", ftype,
+                       BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX,
+                       "__builtin_alloca_with_align_and_max",
+                       alloca_flags);
+
   ftype = build_function_type_list (void_type_node,
                                    ptr_type_node, ptr_type_node,
                                    ptr_type_node, NULL_TREE);
@@ -10716,6 +10723,33 @@ maybe_build_call_expr_loc (location_t loc, combined_fn fn, tree type,
     }
 }
 
+/* Return a function call to the appropriate builtin alloca variant.
+
+   SIZE is the size to be allocated.  ALIGN, if non-zero, is the requested
+   alignment of the allocated area.  MAX_SIZE, if non-negative, is an upper
+   bound for SIZE in case it is not a fixed value.  */
+
+tree
+build_alloca_call_expr (tree size, unsigned int align, HOST_WIDE_INT max_size)
+{
+  if (max_size >= 0)
+    {
+      tree t = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX);
+      return
+       build_call_expr (t, 3, size, size_int (align), size_int (max_size));
+    }
+  else if (align > 0)
+    {
+      tree t = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
+      return build_call_expr (t, 2, size, size_int (align));
+    }
+  else
+    {
+      tree t = builtin_decl_explicit (BUILT_IN_ALLOCA);
+      return build_call_expr (t, 1, size);
+    }
+}
+
 /* Create a new constant string literal and return a char* pointer to it.
    The STRING_CST value is the LEN characters at STR.  */
 tree
index b6dfa89a17ae327e1defac352023cbbcbf35cb95..7214ae2275c9741232b7d0dff0510bfb452ca975 100644 (file)
@@ -2396,6 +2396,18 @@ extern machine_mode vector_type_mode (const_tree);
 #define DECL_FUNCTION_CODE(NODE) \
   (FUNCTION_DECL_CHECK (NODE)->function_decl.function_code)
 
+/* Test if FCODE is a function code for an alloca operation.  */
+#define ALLOCA_FUNCTION_CODE_P(FCODE)                          \
+  ((FCODE) == BUILT_IN_ALLOCA                                  \
+   || (FCODE) == BUILT_IN_ALLOCA_WITH_ALIGN                    \
+   || (FCODE) == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX)
+
+/* Generate case for an alloca operation.  */
+#define CASE_BUILT_IN_ALLOCA                   \
+  case BUILT_IN_ALLOCA:                                \
+  case BUILT_IN_ALLOCA_WITH_ALIGN:             \
+  case BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
+
 #define DECL_FUNCTION_PERSONALITY(NODE) \
   (FUNCTION_DECL_CHECK (NODE)->function_decl.personality)
 
@@ -4050,6 +4062,7 @@ extern tree build_call_expr_internal_loc_array (location_t, enum internal_fn,
                                                tree, int, const tree *);
 extern tree maybe_build_call_expr_loc (location_t, combined_fn, tree,
                                       int, ...);
+extern tree build_alloca_call_expr (tree, unsigned int, HOST_WIDE_INT);
 extern tree build_string_literal (int, const char *);
 
 /* Construct various nodes representing data types.  */
index 55fca76fab9dc0f9f8c2a77bbe13967ea15910de..d324ca034fbf844af717a4b1b4f302e7dadbba72 100644 (file)
@@ -2399,8 +2399,7 @@ incorporeal_function_p (tree decl)
       const char *name;
 
       if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
-         && (DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA
-             || DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA_WITH_ALIGN))
+         && ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (decl)))
        return true;
 
       name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));