builtins.c (expand_builtin_memcmp): Do not emit the call here.
* builtins.c (expand_builtin_memcmp): Do not emit the call here. (expand_builtin_trap): Emit a regular call. (set_builtin_user_assembler_name): Remove obsolete cases. * dse.c (scan_insn): Adjust. * except.c: Include calls.h. (sjlj_emit_function_enter): If DONT_USE_BUILTIN_SETJMP is defined, emit a regular call to setjmp. * expr.c (emit_block_move_hints): Call emit_block_copy_via_libcall. (block_move_libcall_safe_for_call_parm): Use memcpy builtin. (emit_block_move_via_libcall): Delete. (block_move_fn): Delete. (init_block_move_fn): Likewise. (emit_block_move_libcall_fn): Likewise. (emit_block_op_via_libcall): New function. (set_storage_via_libcall): Tidy up and use memset builtin. (block_clear_fn): Delete. (init_block_clear_fn): Likewise. (clear_storage_libcall_fn): Likewise. (expand_assignment): Call emit_block_move_via_libcall. Do not include gt-expr.h. * expr.h (emit_block_op_via_libcall): Declare. (emit_block_copy_via_libcall): New inline function. (emit_block_move_via_libcall): Likewise. (emit_block_comp_via_libcall): Likewise. (block_clear_fn): Delete. (init_block_move_fn): Likewise. (init_block_clear_fn): Likewise. (emit_block_move_via_libcall): Likewise. (set_storage_via_libcall): Add default parameter value. * libfuncs.h (enum libfunc_index): Remove obsolete values. (abort_libfunc): Delete. (memcpy_libfunc): Likewise. (memmove_libfunc): Likewise. (memcmp_libfunc): Likewise. (memset_libfunc): Likewise. (setbits_libfunc): Likewise. (setjmp_libfunc): Likewise. (longjmp_libfunc): Likewise. (profile_function_entry_libfunc): Likewise. (profile_function_exit_libfunc): Likewise. (gcov_flush_libfunc): Likewise. * optabs-libfuncs.c (build_libfunc_function): Set DECL_ARTIFICIAL and DECL_VISIBILITY on the declaration. (init_optabs): Do not initialize obsolete libfuncs. * optabs.c (prepare_cmp_insn): Call emit_block_comp_via_libcall. * tree-core.h (ECF_RET1): Define. (ECF_TM_PURE): Adjust. (ECF_TM_BUILTIN): Likewise. * tree.c (set_call_expr_flags): Deal with ECF_RET1. (build_common_builtin_nodes): Initialize abort builtin. Add ECF_RET1 on memcpy, memmove and memset builtins. Pass final flags for alloca and alloca_with_align builtins. * config/alpha/alpha.c (alpha_init_libfuncs): Do not initialize obsolete builtins. * config/ia64/ia64.c (ia64_vms_init_libfuncs): Likewise. * config/i386/i386.c (ix86_expand_set_or_movmem): Adjust call to set_storage_via_libcall and call emit_block_copy_via_libcall. From-SVN: r236195
This commit is contained in:
parent
fff9b5ddb7
commit
ee516de9b3
@ -1,3 +1,63 @@
|
||||
2016-05-13 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* builtins.c (expand_builtin_memcmp): Do not emit the call here.
|
||||
(expand_builtin_trap): Emit a regular call.
|
||||
(set_builtin_user_assembler_name): Remove obsolete cases.
|
||||
* dse.c (scan_insn): Adjust.
|
||||
* except.c: Include calls.h.
|
||||
(sjlj_emit_function_enter): If DONT_USE_BUILTIN_SETJMP is defined,
|
||||
emit a regular call to setjmp.
|
||||
* expr.c (emit_block_move_hints): Call emit_block_copy_via_libcall.
|
||||
(block_move_libcall_safe_for_call_parm): Use memcpy builtin.
|
||||
(emit_block_move_via_libcall): Delete.
|
||||
(block_move_fn): Delete.
|
||||
(init_block_move_fn): Likewise.
|
||||
(emit_block_move_libcall_fn): Likewise.
|
||||
(emit_block_op_via_libcall): New function.
|
||||
(set_storage_via_libcall): Tidy up and use memset builtin.
|
||||
(block_clear_fn): Delete.
|
||||
(init_block_clear_fn): Likewise.
|
||||
(clear_storage_libcall_fn): Likewise.
|
||||
(expand_assignment): Call emit_block_move_via_libcall.
|
||||
Do not include gt-expr.h.
|
||||
* expr.h (emit_block_op_via_libcall): Declare.
|
||||
(emit_block_copy_via_libcall): New inline function.
|
||||
(emit_block_move_via_libcall): Likewise.
|
||||
(emit_block_comp_via_libcall): Likewise.
|
||||
(block_clear_fn): Delete.
|
||||
(init_block_move_fn): Likewise.
|
||||
(init_block_clear_fn): Likewise.
|
||||
(emit_block_move_via_libcall): Likewise.
|
||||
(set_storage_via_libcall): Add default parameter value.
|
||||
* libfuncs.h (enum libfunc_index): Remove obsolete values.
|
||||
(abort_libfunc): Delete.
|
||||
(memcpy_libfunc): Likewise.
|
||||
(memmove_libfunc): Likewise.
|
||||
(memcmp_libfunc): Likewise.
|
||||
(memset_libfunc): Likewise.
|
||||
(setbits_libfunc): Likewise.
|
||||
(setjmp_libfunc): Likewise.
|
||||
(longjmp_libfunc): Likewise.
|
||||
(profile_function_entry_libfunc): Likewise.
|
||||
(profile_function_exit_libfunc): Likewise.
|
||||
(gcov_flush_libfunc): Likewise.
|
||||
* optabs-libfuncs.c (build_libfunc_function): Set DECL_ARTIFICIAL
|
||||
and DECL_VISIBILITY on the declaration.
|
||||
(init_optabs): Do not initialize obsolete libfuncs.
|
||||
* optabs.c (prepare_cmp_insn): Call emit_block_comp_via_libcall.
|
||||
* tree-core.h (ECF_RET1): Define.
|
||||
(ECF_TM_PURE): Adjust.
|
||||
(ECF_TM_BUILTIN): Likewise.
|
||||
* tree.c (set_call_expr_flags): Deal with ECF_RET1.
|
||||
(build_common_builtin_nodes): Initialize abort builtin.
|
||||
Add ECF_RET1 on memcpy, memmove and memset builtins.
|
||||
Pass final flags for alloca and alloca_with_align builtins.
|
||||
* config/alpha/alpha.c (alpha_init_libfuncs): Do not initialize
|
||||
obsolete builtins.
|
||||
* config/ia64/ia64.c (ia64_vms_init_libfuncs): Likewise.
|
||||
* config/i386/i386.c (ix86_expand_set_or_movmem): Adjust call to
|
||||
set_storage_via_libcall and call emit_block_copy_via_libcall.
|
||||
|
||||
2016-05-12 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
* config/i386/i386.md (*call_got_x32): Change operand 0 to
|
||||
|
@ -3757,20 +3757,7 @@ expand_builtin_memcmp (tree exp, rtx target)
|
||||
return convert_to_mode (mode, result, 0);
|
||||
}
|
||||
|
||||
result = target;
|
||||
if (! (result != 0
|
||||
&& REG_P (result) && GET_MODE (result) == mode
|
||||
&& REGNO (result) >= FIRST_PSEUDO_REGISTER))
|
||||
result = gen_reg_rtx (mode);
|
||||
|
||||
emit_library_call_value (memcmp_libfunc, result, LCT_PURE,
|
||||
TYPE_MODE (integer_type_node), 3,
|
||||
XEXP (arg1_rtx, 0), Pmode,
|
||||
XEXP (arg2_rtx, 0), Pmode,
|
||||
convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
|
||||
TYPE_UNSIGNED (sizetype)),
|
||||
TYPE_MODE (sizetype));
|
||||
return result;
|
||||
return NULL_RTX;
|
||||
}
|
||||
|
||||
/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
|
||||
@ -4455,7 +4442,12 @@ expand_builtin_trap (void)
|
||||
add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta));
|
||||
}
|
||||
else
|
||||
emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
|
||||
{
|
||||
tree fn = builtin_decl_implicit (BUILT_IN_ABORT);
|
||||
tree call_expr = build_call_expr (fn, 0);
|
||||
expand_call (call_expr, NULL_RTX, false);
|
||||
}
|
||||
|
||||
emit_barrier ();
|
||||
}
|
||||
|
||||
@ -9888,42 +9880,19 @@ fold_call_stmt (gcall *stmt, bool ignore)
|
||||
void
|
||||
set_builtin_user_assembler_name (tree decl, const char *asmspec)
|
||||
{
|
||||
tree builtin;
|
||||
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
|
||||
&& DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
|
||||
&& asmspec != 0);
|
||||
|
||||
builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
|
||||
tree builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
|
||||
set_user_assembler_name (builtin, asmspec);
|
||||
switch (DECL_FUNCTION_CODE (decl))
|
||||
|
||||
if (DECL_FUNCTION_CODE (decl) == BUILT_IN_FFS
|
||||
&& INT_TYPE_SIZE < BITS_PER_WORD)
|
||||
{
|
||||
case BUILT_IN_MEMCPY:
|
||||
init_block_move_fn (asmspec);
|
||||
memcpy_libfunc = set_user_assembler_libfunc ("memcpy", asmspec);
|
||||
break;
|
||||
case BUILT_IN_MEMSET:
|
||||
init_block_clear_fn (asmspec);
|
||||
memset_libfunc = set_user_assembler_libfunc ("memset", asmspec);
|
||||
break;
|
||||
case BUILT_IN_MEMMOVE:
|
||||
memmove_libfunc = set_user_assembler_libfunc ("memmove", asmspec);
|
||||
break;
|
||||
case BUILT_IN_MEMCMP:
|
||||
memcmp_libfunc = set_user_assembler_libfunc ("memcmp", asmspec);
|
||||
break;
|
||||
case BUILT_IN_ABORT:
|
||||
abort_libfunc = set_user_assembler_libfunc ("abort", asmspec);
|
||||
break;
|
||||
case BUILT_IN_FFS:
|
||||
if (INT_TYPE_SIZE < BITS_PER_WORD)
|
||||
{
|
||||
set_user_assembler_libfunc ("ffs", asmspec);
|
||||
set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE,
|
||||
MODE_INT, 0), "ffs");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
set_user_assembler_libfunc ("ffs", asmspec);
|
||||
set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE, MODE_INT, 0),
|
||||
"ffs");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9752,8 +9752,6 @@ alpha_init_libfuncs (void)
|
||||
set_optab_libfunc (smod_optab, DImode, "OTS$REM_L");
|
||||
set_optab_libfunc (umod_optab, SImode, "OTS$REM_UI");
|
||||
set_optab_libfunc (umod_optab, DImode, "OTS$REM_UL");
|
||||
abort_libfunc = init_one_libfunc ("decc$abort");
|
||||
memcmp_libfunc = init_one_libfunc ("decc$memcmp");
|
||||
#ifdef MEM_LIBFUNCS_INIT
|
||||
MEM_LIBFUNCS_INIT;
|
||||
#endif
|
||||
|
@ -26908,7 +26908,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
|
||||
{
|
||||
if (UINTVAL (count_exp) >= (unsigned HOST_WIDE_INT)dynamic_check)
|
||||
{
|
||||
emit_block_move_via_libcall (dst, src, count_exp, false);
|
||||
emit_block_copy_via_libcall (dst, src, count_exp);
|
||||
count_exp = const0_rtx;
|
||||
goto epilogue;
|
||||
}
|
||||
@ -26923,9 +26923,9 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
|
||||
1, hot_label);
|
||||
predict_jump (REG_BR_PROB_BASE * 90 / 100);
|
||||
if (issetmem)
|
||||
set_storage_via_libcall (dst, count_exp, val_exp, false);
|
||||
set_storage_via_libcall (dst, count_exp, val_exp);
|
||||
else
|
||||
emit_block_move_via_libcall (dst, src, count_exp, false);
|
||||
emit_block_copy_via_libcall (dst, src, count_exp);
|
||||
emit_jump (jump_around_label);
|
||||
emit_label (hot_label);
|
||||
}
|
||||
|
@ -10624,8 +10624,6 @@ ia64_vms_init_libfuncs (void)
|
||||
set_optab_libfunc (smod_optab, DImode, "OTS$REM_L");
|
||||
set_optab_libfunc (umod_optab, SImode, "OTS$REM_UI");
|
||||
set_optab_libfunc (umod_optab, DImode, "OTS$REM_UL");
|
||||
abort_libfunc = init_one_libfunc ("decc$abort");
|
||||
memcmp_libfunc = init_one_libfunc ("decc$memcmp");
|
||||
#ifdef MEM_LIBFUNCS_INIT
|
||||
MEM_LIBFUNCS_INIT;
|
||||
#endif
|
||||
|
29
gcc/dse.c
29
gcc/dse.c
@ -2269,6 +2269,7 @@ scan_insn (bb_info_t bb_info, rtx_insn *insn)
|
||||
if (CALL_P (insn))
|
||||
{
|
||||
bool const_call;
|
||||
rtx call, sym;
|
||||
tree memset_call = NULL_TREE;
|
||||
|
||||
insn_info->cannot_delete = true;
|
||||
@ -2278,24 +2279,16 @@ scan_insn (bb_info_t bb_info, rtx_insn *insn)
|
||||
been pushed onto the stack.
|
||||
memset and bzero don't read memory either. */
|
||||
const_call = RTL_CONST_CALL_P (insn);
|
||||
if (!const_call)
|
||||
{
|
||||
rtx call = get_call_rtx_from (insn);
|
||||
if (call && GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF)
|
||||
{
|
||||
rtx symbol = XEXP (XEXP (call, 0), 0);
|
||||
if (SYMBOL_REF_DECL (symbol)
|
||||
&& TREE_CODE (SYMBOL_REF_DECL (symbol)) == FUNCTION_DECL)
|
||||
{
|
||||
if ((DECL_BUILT_IN_CLASS (SYMBOL_REF_DECL (symbol))
|
||||
== BUILT_IN_NORMAL
|
||||
&& (DECL_FUNCTION_CODE (SYMBOL_REF_DECL (symbol))
|
||||
== BUILT_IN_MEMSET))
|
||||
|| SYMBOL_REF_DECL (symbol) == block_clear_fn)
|
||||
memset_call = SYMBOL_REF_DECL (symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!const_call
|
||||
&& (call = get_call_rtx_from (insn))
|
||||
&& (sym = XEXP (XEXP (call, 0), 0))
|
||||
&& GET_CODE (sym) == SYMBOL_REF
|
||||
&& SYMBOL_REF_DECL (sym)
|
||||
&& TREE_CODE (SYMBOL_REF_DECL (sym)) == FUNCTION_DECL
|
||||
&& DECL_BUILT_IN_CLASS (SYMBOL_REF_DECL (sym)) == BUILT_IN_NORMAL
|
||||
&& DECL_FUNCTION_CODE (SYMBOL_REF_DECL (sym)) == BUILT_IN_MEMSET)
|
||||
memset_call = SYMBOL_REF_DECL (sym);
|
||||
|
||||
if (const_call || memset_call)
|
||||
{
|
||||
insn_info_t i_ptr = active_local_stores;
|
||||
|
19
gcc/except.c
19
gcc/except.c
@ -130,6 +130,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "explow.h"
|
||||
#include "stmt.h"
|
||||
#include "expr.h"
|
||||
#include "calls.h"
|
||||
#include "libfuncs.h"
|
||||
#include "except.h"
|
||||
#include "output.h"
|
||||
@ -1173,20 +1174,22 @@ sjlj_emit_function_enter (rtx_code_label *dispatch_label)
|
||||
|
||||
if (dispatch_label)
|
||||
{
|
||||
rtx addr = plus_constant (Pmode, XEXP (fc, 0), sjlj_fc_jbuf_ofs);
|
||||
|
||||
#ifdef DONT_USE_BUILTIN_SETJMP
|
||||
rtx x;
|
||||
x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_RETURNS_TWICE,
|
||||
TYPE_MODE (integer_type_node), 1,
|
||||
plus_constant (Pmode, XEXP (fc, 0),
|
||||
sjlj_fc_jbuf_ofs), Pmode);
|
||||
addr = copy_addr_to_reg (addr);
|
||||
addr = convert_memory_address (ptr_mode, addr);
|
||||
tree addr_tree = make_tree (ptr_type_node, addr);
|
||||
|
||||
tree fn = builtin_decl_implicit (BUILT_IN_SETJMP);
|
||||
tree call_expr = build_call_expr (fn, 1, addr_tree);
|
||||
rtx x = expand_call (call_expr, NULL_RTX, false);
|
||||
|
||||
emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
|
||||
TYPE_MODE (integer_type_node), 0,
|
||||
dispatch_label, REG_BR_PROB_BASE / 100);
|
||||
#else
|
||||
expand_builtin_setjmp_setup (plus_constant (Pmode, XEXP (fc, 0),
|
||||
sjlj_fc_jbuf_ofs),
|
||||
dispatch_label);
|
||||
expand_builtin_setjmp_setup (addr, dispatch_label);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
227
gcc/expr.c
227
gcc/expr.c
@ -109,14 +109,12 @@ static bool block_move_libcall_safe_for_call_parm (void);
|
||||
static bool emit_block_move_via_movmem (rtx, rtx, rtx, unsigned, unsigned, HOST_WIDE_INT,
|
||||
unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
|
||||
unsigned HOST_WIDE_INT);
|
||||
static tree emit_block_move_libcall_fn (int);
|
||||
static void emit_block_move_via_loop (rtx, rtx, rtx, unsigned);
|
||||
static rtx clear_by_pieces_1 (void *, HOST_WIDE_INT, machine_mode);
|
||||
static void clear_by_pieces (rtx, unsigned HOST_WIDE_INT, unsigned int);
|
||||
static void store_by_pieces_1 (struct store_by_pieces_d *, unsigned int);
|
||||
static void store_by_pieces_2 (insn_gen_fn, machine_mode,
|
||||
struct store_by_pieces_d *);
|
||||
static tree clear_storage_libcall_fn (int);
|
||||
static rtx_insn *compress_float_constant (rtx, rtx);
|
||||
static rtx get_subtarget (rtx);
|
||||
static void store_constructor_field (rtx, unsigned HOST_WIDE_INT,
|
||||
@ -1132,7 +1130,7 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method,
|
||||
mark_addressable (y_expr);
|
||||
if (x_expr)
|
||||
mark_addressable (x_expr);
|
||||
retval = emit_block_move_via_libcall (x, y, size,
|
||||
retval = emit_block_copy_via_libcall (x, y, size,
|
||||
method == BLOCK_OP_TAILCALL);
|
||||
}
|
||||
|
||||
@ -1175,7 +1173,7 @@ block_move_libcall_safe_for_call_parm (void)
|
||||
/* If registers go on the stack anyway, any argument is sure to clobber
|
||||
an outgoing argument. */
|
||||
#if defined (REG_PARM_STACK_SPACE)
|
||||
fn = emit_block_move_libcall_fn (false);
|
||||
fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
|
||||
/* Avoid set but not used warning if *REG_PARM_STACK_SPACE doesn't
|
||||
depend on its argument. */
|
||||
(void) fn;
|
||||
@ -1191,7 +1189,7 @@ block_move_libcall_safe_for_call_parm (void)
|
||||
cumulative_args_t args_so_far;
|
||||
tree fn, arg;
|
||||
|
||||
fn = emit_block_move_libcall_fn (false);
|
||||
fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
|
||||
INIT_CUMULATIVE_ARGS (args_so_far_v, TREE_TYPE (fn), NULL_RTX, 0, 3);
|
||||
args_so_far = pack_cumulative_args (&args_so_far_v);
|
||||
|
||||
@ -1310,106 +1308,6 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* A subroutine of emit_block_move. Expand a call to memcpy.
|
||||
Return the return value from memcpy, 0 otherwise. */
|
||||
|
||||
rtx
|
||||
emit_block_move_via_libcall (rtx dst, rtx src, rtx size, bool tailcall)
|
||||
{
|
||||
rtx dst_addr, src_addr;
|
||||
tree call_expr, fn, src_tree, dst_tree, size_tree;
|
||||
machine_mode size_mode;
|
||||
rtx retval;
|
||||
|
||||
/* Emit code to copy the addresses of DST and SRC and SIZE into new
|
||||
pseudos. We can then place those new pseudos into a VAR_DECL and
|
||||
use them later. */
|
||||
|
||||
dst_addr = copy_addr_to_reg (XEXP (dst, 0));
|
||||
src_addr = copy_addr_to_reg (XEXP (src, 0));
|
||||
|
||||
dst_addr = convert_memory_address (ptr_mode, dst_addr);
|
||||
src_addr = convert_memory_address (ptr_mode, src_addr);
|
||||
|
||||
dst_tree = make_tree (ptr_type_node, dst_addr);
|
||||
src_tree = make_tree (ptr_type_node, src_addr);
|
||||
|
||||
size_mode = TYPE_MODE (sizetype);
|
||||
|
||||
size = convert_to_mode (size_mode, size, 1);
|
||||
size = copy_to_mode_reg (size_mode, size);
|
||||
|
||||
/* It is incorrect to use the libcall calling conventions to call
|
||||
memcpy in this context. This could be a user call to memcpy and
|
||||
the user may wish to examine the return value from memcpy. For
|
||||
targets where libcalls and normal calls have different conventions
|
||||
for returning pointers, we could end up generating incorrect code. */
|
||||
|
||||
size_tree = make_tree (sizetype, size);
|
||||
|
||||
fn = emit_block_move_libcall_fn (true);
|
||||
call_expr = build_call_expr (fn, 3, dst_tree, src_tree, size_tree);
|
||||
CALL_EXPR_TAILCALL (call_expr) = tailcall;
|
||||
|
||||
retval = expand_normal (call_expr);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* A subroutine of emit_block_move_via_libcall. Create the tree node
|
||||
for the function we use for block copies. */
|
||||
|
||||
static GTY(()) tree block_move_fn;
|
||||
|
||||
void
|
||||
init_block_move_fn (const char *asmspec)
|
||||
{
|
||||
if (!block_move_fn)
|
||||
{
|
||||
tree args, fn, attrs, attr_args;
|
||||
|
||||
fn = get_identifier ("memcpy");
|
||||
args = build_function_type_list (ptr_type_node, ptr_type_node,
|
||||
const_ptr_type_node, sizetype,
|
||||
NULL_TREE);
|
||||
|
||||
fn = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, fn, args);
|
||||
DECL_EXTERNAL (fn) = 1;
|
||||
TREE_PUBLIC (fn) = 1;
|
||||
DECL_ARTIFICIAL (fn) = 1;
|
||||
TREE_NOTHROW (fn) = 1;
|
||||
DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
|
||||
DECL_VISIBILITY_SPECIFIED (fn) = 1;
|
||||
|
||||
attr_args = build_tree_list (NULL_TREE, build_string (1, "1"));
|
||||
attrs = tree_cons (get_identifier ("fn spec"), attr_args, NULL);
|
||||
|
||||
decl_attributes (&fn, attrs, ATTR_FLAG_BUILT_IN);
|
||||
|
||||
block_move_fn = fn;
|
||||
}
|
||||
|
||||
if (asmspec)
|
||||
set_user_assembler_name (block_move_fn, asmspec);
|
||||
}
|
||||
|
||||
static tree
|
||||
emit_block_move_libcall_fn (int for_call)
|
||||
{
|
||||
static bool emitted_extern;
|
||||
|
||||
if (!block_move_fn)
|
||||
init_block_move_fn (NULL);
|
||||
|
||||
if (for_call && !emitted_extern)
|
||||
{
|
||||
emitted_extern = true;
|
||||
make_decl_rtl (block_move_fn);
|
||||
}
|
||||
|
||||
return block_move_fn;
|
||||
}
|
||||
|
||||
/* A subroutine of emit_block_move. Copy the data via an explicit
|
||||
loop. This is used only when libcalls are forbidden. */
|
||||
/* ??? It'd be nice to copy in hunks larger than QImode. */
|
||||
@ -1464,6 +1362,39 @@ emit_block_move_via_loop (rtx x, rtx y, rtx size,
|
||||
true, top_label, REG_BR_PROB_BASE * 90 / 100);
|
||||
}
|
||||
|
||||
/* Expand a call to memcpy or memmove or memcmp, and return the result.
|
||||
TAILCALL is true if this is a tail call. */
|
||||
|
||||
rtx
|
||||
emit_block_op_via_libcall (enum built_in_function fncode, rtx dst, rtx src,
|
||||
rtx size, bool tailcall)
|
||||
{
|
||||
rtx dst_addr, src_addr;
|
||||
tree call_expr, dst_tree, src_tree, size_tree;
|
||||
machine_mode size_mode;
|
||||
|
||||
dst_addr = copy_addr_to_reg (XEXP (dst, 0));
|
||||
dst_addr = convert_memory_address (ptr_mode, dst_addr);
|
||||
dst_tree = make_tree (ptr_type_node, dst_addr);
|
||||
|
||||
src_addr = copy_addr_to_reg (XEXP (src, 0));
|
||||
src_addr = convert_memory_address (ptr_mode, src_addr);
|
||||
src_tree = make_tree (ptr_type_node, src_addr);
|
||||
|
||||
size_mode = TYPE_MODE (sizetype);
|
||||
size = convert_to_mode (size_mode, size, 1);
|
||||
size = copy_to_mode_reg (size_mode, size);
|
||||
size_tree = make_tree (sizetype, size);
|
||||
|
||||
/* It is incorrect to use the libcall calling conventions for calls to
|
||||
memcpy/memmove/memcmp because they can be provided by the user. */
|
||||
tree fn = builtin_decl_implicit (fncode);
|
||||
call_expr = build_call_expr (fn, 3, dst_tree, src_tree, size_tree);
|
||||
CALL_EXPR_TAILCALL (call_expr) = tailcall;
|
||||
|
||||
return expand_call (call_expr, NULL_RTX, false);
|
||||
}
|
||||
|
||||
/* Copy all or part of a value X into registers starting at REGNO.
|
||||
The number of registers to be filled is NREGS. */
|
||||
|
||||
@ -2784,85 +2715,26 @@ set_storage_via_libcall (rtx object, rtx size, rtx val, bool tailcall)
|
||||
{
|
||||
tree call_expr, fn, object_tree, size_tree, val_tree;
|
||||
machine_mode size_mode;
|
||||
rtx retval;
|
||||
|
||||
/* Emit code to copy OBJECT and SIZE into new pseudos. We can then
|
||||
place those into new pseudos into a VAR_DECL and use them later. */
|
||||
|
||||
object = copy_addr_to_reg (XEXP (object, 0));
|
||||
object_tree = make_tree (ptr_type_node, object);
|
||||
|
||||
if (!CONST_INT_P (val))
|
||||
val = convert_to_mode (TYPE_MODE (integer_type_node), val, 1);
|
||||
val_tree = make_tree (integer_type_node, val);
|
||||
|
||||
size_mode = TYPE_MODE (sizetype);
|
||||
size = convert_to_mode (size_mode, size, 1);
|
||||
size = copy_to_mode_reg (size_mode, size);
|
||||
|
||||
/* It is incorrect to use the libcall calling conventions to call
|
||||
memset in this context. This could be a user call to memset and
|
||||
the user may wish to examine the return value from memset. For
|
||||
targets where libcalls and normal calls have different conventions
|
||||
for returning pointers, we could end up generating incorrect code. */
|
||||
|
||||
object_tree = make_tree (ptr_type_node, object);
|
||||
if (!CONST_INT_P (val))
|
||||
val = convert_to_mode (TYPE_MODE (integer_type_node), val, 1);
|
||||
size_tree = make_tree (sizetype, size);
|
||||
val_tree = make_tree (integer_type_node, val);
|
||||
|
||||
fn = clear_storage_libcall_fn (true);
|
||||
/* It is incorrect to use the libcall calling conventions for calls to
|
||||
memset because it can be provided by the user. */
|
||||
fn = builtin_decl_implicit (BUILT_IN_MEMSET);
|
||||
call_expr = build_call_expr (fn, 3, object_tree, val_tree, size_tree);
|
||||
CALL_EXPR_TAILCALL (call_expr) = tailcall;
|
||||
|
||||
retval = expand_normal (call_expr);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* A subroutine of set_storage_via_libcall. Create the tree node
|
||||
for the function we use for block clears. */
|
||||
|
||||
tree block_clear_fn;
|
||||
|
||||
void
|
||||
init_block_clear_fn (const char *asmspec)
|
||||
{
|
||||
if (!block_clear_fn)
|
||||
{
|
||||
tree fn, args;
|
||||
|
||||
fn = get_identifier ("memset");
|
||||
args = build_function_type_list (ptr_type_node, ptr_type_node,
|
||||
integer_type_node, sizetype,
|
||||
NULL_TREE);
|
||||
|
||||
fn = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, fn, args);
|
||||
DECL_EXTERNAL (fn) = 1;
|
||||
TREE_PUBLIC (fn) = 1;
|
||||
DECL_ARTIFICIAL (fn) = 1;
|
||||
TREE_NOTHROW (fn) = 1;
|
||||
DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
|
||||
DECL_VISIBILITY_SPECIFIED (fn) = 1;
|
||||
|
||||
block_clear_fn = fn;
|
||||
}
|
||||
|
||||
if (asmspec)
|
||||
set_user_assembler_name (block_clear_fn, asmspec);
|
||||
}
|
||||
|
||||
static tree
|
||||
clear_storage_libcall_fn (int for_call)
|
||||
{
|
||||
static bool emitted_extern;
|
||||
|
||||
if (!block_clear_fn)
|
||||
init_block_clear_fn (NULL);
|
||||
|
||||
if (for_call && !emitted_extern)
|
||||
{
|
||||
emitted_extern = true;
|
||||
make_decl_rtl (block_clear_fn);
|
||||
}
|
||||
|
||||
return block_clear_fn;
|
||||
return expand_call (call_expr, NULL_RTX, false);
|
||||
}
|
||||
|
||||
/* Expand a setmem pattern; return true if successful. */
|
||||
@ -5157,12 +5029,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
|
||||
size = expr_size (from);
|
||||
from_rtx = expand_normal (from);
|
||||
|
||||
emit_library_call (memmove_libfunc, LCT_NORMAL,
|
||||
VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
|
||||
XEXP (from_rtx, 0), Pmode,
|
||||
convert_to_mode (TYPE_MODE (sizetype),
|
||||
size, TYPE_UNSIGNED (sizetype)),
|
||||
TYPE_MODE (sizetype));
|
||||
emit_block_move_via_libcall (XEXP (to_rtx, 0), XEXP (from_rtx, 0), size);
|
||||
|
||||
preserve_temp_slots (to_rtx);
|
||||
pop_temp_slots ();
|
||||
@ -11653,5 +11520,3 @@ int_expr_size (tree exp)
|
||||
|
||||
return tree_to_shwi (size);
|
||||
}
|
||||
|
||||
#include "gt-expr.h"
|
||||
|
30
gcc/expr.h
30
gcc/expr.h
@ -71,8 +71,29 @@ extern rtx convert_to_mode (machine_mode, rtx, int);
|
||||
/* Convert an rtx to MODE from OLDMODE and return the result. */
|
||||
extern rtx convert_modes (machine_mode, machine_mode, rtx, int);
|
||||
|
||||
/* Emit code to move a block Y to a block X. */
|
||||
/* Expand a call to memcpy or memmove or memcmp, and return the result. */
|
||||
extern rtx emit_block_op_via_libcall (enum built_in_function, rtx, rtx, rtx,
|
||||
bool);
|
||||
|
||||
static inline rtx
|
||||
emit_block_copy_via_libcall (rtx dst, rtx src, rtx size, bool tailcall = false)
|
||||
{
|
||||
return emit_block_op_via_libcall (BUILT_IN_MEMCPY, dst, src, size, tailcall);
|
||||
}
|
||||
|
||||
static inline rtx
|
||||
emit_block_move_via_libcall (rtx dst, rtx src, rtx size, bool tailcall = false)
|
||||
{
|
||||
return emit_block_op_via_libcall (BUILT_IN_MEMMOVE, dst, src, size, tailcall);
|
||||
}
|
||||
|
||||
static inline rtx
|
||||
emit_block_comp_via_libcall (rtx dst, rtx src, rtx size, bool tailcall = false)
|
||||
{
|
||||
return emit_block_op_via_libcall (BUILT_IN_MEMCMP, dst, src, size, tailcall);
|
||||
}
|
||||
|
||||
/* Emit code to move a block Y to a block X. */
|
||||
enum block_op_methods
|
||||
{
|
||||
BLOCK_OP_NORMAL,
|
||||
@ -82,12 +103,7 @@ enum block_op_methods
|
||||
BLOCK_OP_TAILCALL
|
||||
};
|
||||
|
||||
extern GTY(()) tree block_clear_fn;
|
||||
extern void init_block_move_fn (const char *);
|
||||
extern void init_block_clear_fn (const char *);
|
||||
|
||||
extern rtx emit_block_move (rtx, rtx, rtx, enum block_op_methods);
|
||||
extern rtx emit_block_move_via_libcall (rtx, rtx, rtx, bool);
|
||||
extern rtx emit_block_move_hints (rtx, rtx, rtx, enum block_op_methods,
|
||||
unsigned int, HOST_WIDE_INT,
|
||||
unsigned HOST_WIDE_INT,
|
||||
@ -166,7 +182,7 @@ extern rtx clear_storage_hints (rtx, rtx, enum block_op_methods,
|
||||
unsigned HOST_WIDE_INT,
|
||||
unsigned HOST_WIDE_INT);
|
||||
/* The same, but always output an library call. */
|
||||
rtx set_storage_via_libcall (rtx, rtx, rtx, bool);
|
||||
extern rtx set_storage_via_libcall (rtx, rtx, rtx, bool = false);
|
||||
|
||||
/* Expand a setmem pattern; return true if successful. */
|
||||
extern bool set_storage_via_setmem (rtx, rtx, rtx, unsigned int,
|
||||
|
@ -24,25 +24,9 @@ along with GCC; see the file COPYING3. If not see
|
||||
/* Enumeration of indexes into libfunc_table. */
|
||||
enum libfunc_index
|
||||
{
|
||||
LTI_abort,
|
||||
LTI_memcpy,
|
||||
LTI_memmove,
|
||||
LTI_memcmp,
|
||||
LTI_memset,
|
||||
LTI_setbits,
|
||||
|
||||
LTI_setjmp,
|
||||
LTI_longjmp,
|
||||
LTI_unwind_sjlj_register,
|
||||
LTI_unwind_sjlj_unregister,
|
||||
|
||||
LTI_profile_function_entry,
|
||||
LTI_profile_function_exit,
|
||||
|
||||
LTI_synchronize,
|
||||
|
||||
LTI_gcov_flush,
|
||||
|
||||
LTI_MAX
|
||||
};
|
||||
|
||||
@ -89,26 +73,11 @@ extern struct target_libfuncs *this_target_libfuncs;
|
||||
|
||||
/* Accessor macros for libfunc_table. */
|
||||
|
||||
#define abort_libfunc (libfunc_table[LTI_abort])
|
||||
#define memcpy_libfunc (libfunc_table[LTI_memcpy])
|
||||
#define memmove_libfunc (libfunc_table[LTI_memmove])
|
||||
#define memcmp_libfunc (libfunc_table[LTI_memcmp])
|
||||
#define memset_libfunc (libfunc_table[LTI_memset])
|
||||
#define setbits_libfunc (libfunc_table[LTI_setbits])
|
||||
|
||||
#define setjmp_libfunc (libfunc_table[LTI_setjmp])
|
||||
#define longjmp_libfunc (libfunc_table[LTI_longjmp])
|
||||
#define unwind_sjlj_register_libfunc (libfunc_table[LTI_unwind_sjlj_register])
|
||||
#define unwind_sjlj_unregister_libfunc \
|
||||
(libfunc_table[LTI_unwind_sjlj_unregister])
|
||||
|
||||
#define profile_function_entry_libfunc (libfunc_table[LTI_profile_function_entry])
|
||||
#define profile_function_exit_libfunc (libfunc_table[LTI_profile_function_exit])
|
||||
|
||||
#define synchronize_libfunc (libfunc_table[LTI_synchronize])
|
||||
|
||||
#define gcov_flush_libfunc (libfunc_table[LTI_gcov_flush])
|
||||
|
||||
/* In explow.c */
|
||||
extern void set_stack_check_libfunc (const char *);
|
||||
|
||||
|
@ -731,14 +731,15 @@ static GTY (()) hash_table<libfunc_decl_hasher> *libfunc_decls;
|
||||
tree
|
||||
build_libfunc_function (const char *name)
|
||||
{
|
||||
/* ??? We don't have any type information; pretend this is "int foo ()". */
|
||||
tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
|
||||
get_identifier (name),
|
||||
build_function_type (integer_type_node, NULL_TREE));
|
||||
/* ??? We don't have any type information except for this is
|
||||
a function. Pretend this is "int foo ()". */
|
||||
DECL_ARTIFICIAL (decl) = 1;
|
||||
DECL_EXTERNAL (decl) = 1;
|
||||
TREE_PUBLIC (decl) = 1;
|
||||
DECL_ARTIFICIAL (decl) = 1;
|
||||
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
|
||||
DECL_VISIBILITY_SPECIFIED (decl) = 1;
|
||||
gcc_assert (DECL_ASSEMBLER_NAME (decl));
|
||||
|
||||
/* Zap the nonsensical SYMBOL_REF_DECL for this. What we're left with
|
||||
@ -887,32 +888,10 @@ init_optabs (void)
|
||||
set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node),
|
||||
"cabs");
|
||||
|
||||
abort_libfunc = init_one_libfunc ("abort");
|
||||
memcpy_libfunc = init_one_libfunc ("memcpy");
|
||||
memmove_libfunc = init_one_libfunc ("memmove");
|
||||
memcmp_libfunc = init_one_libfunc ("memcmp");
|
||||
memset_libfunc = init_one_libfunc ("memset");
|
||||
setbits_libfunc = init_one_libfunc ("__setbits");
|
||||
|
||||
#ifndef DONT_USE_BUILTIN_SETJMP
|
||||
setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
|
||||
longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
|
||||
#else
|
||||
setjmp_libfunc = init_one_libfunc ("setjmp");
|
||||
longjmp_libfunc = init_one_libfunc ("longjmp");
|
||||
#endif
|
||||
unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
|
||||
unwind_sjlj_unregister_libfunc
|
||||
= init_one_libfunc ("_Unwind_SjLj_Unregister");
|
||||
|
||||
/* For function entry/exit instrumentation. */
|
||||
profile_function_entry_libfunc
|
||||
= init_one_libfunc ("__cyg_profile_func_enter");
|
||||
profile_function_exit_libfunc
|
||||
= init_one_libfunc ("__cyg_profile_func_exit");
|
||||
|
||||
gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");
|
||||
|
||||
/* Allow the target to add more libcalls or rename some, etc. */
|
||||
targetm.init_libfuncs ();
|
||||
}
|
||||
|
18
gcc/optabs.c
18
gcc/optabs.c
@ -3776,8 +3776,6 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
|
||||
{
|
||||
machine_mode result_mode;
|
||||
enum insn_code cmp_code;
|
||||
tree length_type;
|
||||
rtx libfunc;
|
||||
rtx result;
|
||||
rtx opalign
|
||||
= GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
|
||||
@ -3818,22 +3816,12 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
|
||||
if (methods != OPTAB_LIB && methods != OPTAB_LIB_WIDEN)
|
||||
goto fail;
|
||||
|
||||
/* Otherwise call a library function, memcmp. */
|
||||
libfunc = memcmp_libfunc;
|
||||
length_type = sizetype;
|
||||
result_mode = TYPE_MODE (integer_type_node);
|
||||
cmp_mode = TYPE_MODE (length_type);
|
||||
size = convert_to_mode (TYPE_MODE (length_type), size,
|
||||
TYPE_UNSIGNED (length_type));
|
||||
/* Otherwise call a library function. */
|
||||
result = emit_block_comp_via_libcall (XEXP (x, 0), XEXP (y, 0), size);
|
||||
|
||||
result = emit_library_call_value (libfunc, 0, LCT_PURE,
|
||||
result_mode, 3,
|
||||
XEXP (x, 0), Pmode,
|
||||
XEXP (y, 0), Pmode,
|
||||
size, cmp_mode);
|
||||
x = result;
|
||||
y = const0_rtx;
|
||||
mode = result_mode;
|
||||
mode = TYPE_MODE (integer_type_node);
|
||||
methods = OPTAB_LIB_WIDEN;
|
||||
unsignedp = false;
|
||||
}
|
||||
|
@ -81,11 +81,14 @@ struct die_struct;
|
||||
/* The function does not lead to calls within current function unit. */
|
||||
#define ECF_LEAF (1 << 10)
|
||||
|
||||
/* Nonzero if this call returns its first argument. */
|
||||
#define ECF_RET1 (1 << 11)
|
||||
|
||||
/* Nonzero if this call does not affect transactions. */
|
||||
#define ECF_TM_PURE (1 << 11)
|
||||
#define ECF_TM_PURE (1 << 12)
|
||||
|
||||
/* Nonzero if this call is into the transaction runtime library. */
|
||||
#define ECF_TM_BUILTIN (1 << 12)
|
||||
#define ECF_TM_BUILTIN (1 << 13)
|
||||
|
||||
/* Call argument flags. */
|
||||
/* Nonzero if the argument is not dereferenced recursively, thus only
|
||||
|
43
gcc/tree.c
43
gcc/tree.c
@ -10451,6 +10451,11 @@ set_call_expr_flags (tree decl, int flags)
|
||||
if (flags & ECF_LEAF)
|
||||
DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"),
|
||||
NULL, DECL_ATTRIBUTES (decl));
|
||||
if (flags & ECF_RET1)
|
||||
DECL_ATTRIBUTES (decl)
|
||||
= tree_cons (get_identifier ("fn spec"),
|
||||
build_tree_list (NULL_TREE, build_string (1, "1")),
|
||||
DECL_ATTRIBUTES (decl));
|
||||
if ((flags & ECF_TM_PURE) && flag_tm)
|
||||
apply_tm_attr (decl, get_identifier ("transaction_pure"));
|
||||
/* Looping const or pure is implied by noreturn.
|
||||
@ -10486,13 +10491,20 @@ build_common_builtin_nodes (void)
|
||||
tree tmp, ftype;
|
||||
int ecf_flags;
|
||||
|
||||
if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE))
|
||||
if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE)
|
||||
|| !builtin_decl_explicit_p (BUILT_IN_ABORT))
|
||||
{
|
||||
ftype = build_function_type (void_type_node, void_list_node);
|
||||
local_define_builtin ("__builtin_unreachable", ftype, BUILT_IN_UNREACHABLE,
|
||||
"__builtin_unreachable",
|
||||
ECF_NOTHROW | ECF_LEAF | ECF_NORETURN
|
||||
| ECF_CONST);
|
||||
if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE))
|
||||
local_define_builtin ("__builtin_unreachable", ftype,
|
||||
BUILT_IN_UNREACHABLE,
|
||||
"__builtin_unreachable",
|
||||
ECF_NOTHROW | ECF_LEAF | ECF_NORETURN
|
||||
| ECF_CONST);
|
||||
if (!builtin_decl_explicit_p (BUILT_IN_ABORT))
|
||||
local_define_builtin ("__builtin_abort", ftype, BUILT_IN_ABORT,
|
||||
"abort",
|
||||
ECF_LEAF | ECF_NORETURN | ECF_CONST);
|
||||
}
|
||||
|
||||
if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY)
|
||||
@ -10504,10 +10516,10 @@ build_common_builtin_nodes (void)
|
||||
|
||||
if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY))
|
||||
local_define_builtin ("__builtin_memcpy", ftype, BUILT_IN_MEMCPY,
|
||||
"memcpy", ECF_NOTHROW | ECF_LEAF);
|
||||
"memcpy", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
|
||||
if (!builtin_decl_explicit_p (BUILT_IN_MEMMOVE))
|
||||
local_define_builtin ("__builtin_memmove", ftype, BUILT_IN_MEMMOVE,
|
||||
"memmove", ECF_NOTHROW | ECF_LEAF);
|
||||
"memmove", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
|
||||
}
|
||||
|
||||
if (!builtin_decl_explicit_p (BUILT_IN_MEMCMP))
|
||||
@ -10525,15 +10537,19 @@ build_common_builtin_nodes (void)
|
||||
ptr_type_node, integer_type_node,
|
||||
size_type_node, NULL_TREE);
|
||||
local_define_builtin ("__builtin_memset", ftype, BUILT_IN_MEMSET,
|
||||
"memset", ECF_NOTHROW | ECF_LEAF);
|
||||
"memset", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
|
||||
}
|
||||
|
||||
/* If we're checking the stack, `alloca' can throw. */
|
||||
const int alloca_flags
|
||||
= ECF_MALLOC | ECF_LEAF | (flag_stack_check ? 0 : ECF_NOTHROW);
|
||||
|
||||
if (!builtin_decl_explicit_p (BUILT_IN_ALLOCA))
|
||||
{
|
||||
ftype = build_function_type_list (ptr_type_node,
|
||||
size_type_node, NULL_TREE);
|
||||
local_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA,
|
||||
"alloca", ECF_MALLOC | ECF_NOTHROW | ECF_LEAF);
|
||||
"alloca", alloca_flags);
|
||||
}
|
||||
|
||||
ftype = build_function_type_list (ptr_type_node, size_type_node,
|
||||
@ -10541,14 +10557,7 @@ build_common_builtin_nodes (void)
|
||||
local_define_builtin ("__builtin_alloca_with_align", ftype,
|
||||
BUILT_IN_ALLOCA_WITH_ALIGN,
|
||||
"__builtin_alloca_with_align",
|
||||
ECF_MALLOC | ECF_NOTHROW | ECF_LEAF);
|
||||
|
||||
/* If we're checking the stack, `alloca' can throw. */
|
||||
if (flag_stack_check)
|
||||
{
|
||||
TREE_NOTHROW (builtin_decl_explicit (BUILT_IN_ALLOCA)) = 0;
|
||||
TREE_NOTHROW (builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN)) = 0;
|
||||
}
|
||||
alloca_flags);
|
||||
|
||||
ftype = build_function_type_list (void_type_node,
|
||||
ptr_type_node, ptr_type_node,
|
||||
|
Loading…
x
Reference in New Issue
Block a user