asan.c (handle_builtin_alloca): Deal with all alloca variants.
* 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. c-family/ * c-common.c (check_builtin_function_arguments): Also check arguments of __builtin_alloca_with_align_and_max. From-SVN: r253901
This commit is contained in:
parent
d969783705
commit
9e878cf1ba
29 changed files with 288 additions and 137 deletions
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
25
gcc/calls.c
25
gcc/calls.c
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
15
gcc/explow.c
15
gcc/explow.c
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
17
gcc/testsuite/gcc.dg/Walloca-15.c
Normal file
17
gcc/testsuite/gcc.dg/Walloca-15.c
Normal file
|
@ -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" } */
|
||||
}
|
11
gcc/testsuite/gnat.dg/stack_usage4.adb
Normal file
11
gcc/testsuite/gnat.dg/stack_usage4.adb
Normal file
|
@ -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;
|
12
gcc/testsuite/gnat.dg/stack_usage4_pkg.ads
Normal file
12
gcc/testsuite/gnat.dg/stack_usage4_pkg.ads
Normal file
|
@ -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;
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
34
gcc/tree.c
34
gcc/tree.c
|
@ -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
|
||||
|
|
13
gcc/tree.h
13
gcc/tree.h
|
@ -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. */
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Add table
Reference in a new issue