c-common.c (struct c_common_attributes): Add fnspec attribute.
2010-05-10 Richard Guenther <rguenther@suse.de> * c-common.c (struct c_common_attributes): Add fnspec attribute. (handle_fnspec_attribute): New function. * gimple.h (gimple_call_return_flags): Declare. (gimple_call_arg_flags): Likewise. * gimple.c (gimple_call_arg_flags): New function. (gimple_call_return_flags): Likewise. * tree.h (EAF_DIRECT, EAF_NOCLOBBER, EAF_NOESCAPE, EAF_UNUSED): New argument flags. (ERF_RETURN_ARG_MASK, ERF_RETURNS_ARG, ERF_NOALIAS): New function return value flags. * tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Skip unused args. * tree-ssa-structalias.c (make_constraint_from_heapvar): Split main work to ... (make_heapvar_for): ... this new function. (handle_rhs_call): Handle fnspec attribute argument specifiers. (handle_lhs_call): Likewise. (find_func_aliases): Adjust. fortran/ * trans-decl.c (gfc_build_library_function_decl): Split out worker to ... (build_library_function_decl_1): ... this new function. Set a fnspec attribute if a specification was provided. (gfc_build_library_function_decl_with_spec): New function. (gfc_build_intrinsic_function_decls): Annotate internal_pack and internal_unpack. From-SVN: r159215
This commit is contained in:
parent
1755aad094
commit
0b7b376d89
|
@ -1,3 +1,23 @@
|
|||
2010-05-10 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
* c-common.c (struct c_common_attributes): Add fnspec attribute.
|
||||
(handle_fnspec_attribute): New function.
|
||||
* gimple.h (gimple_call_return_flags): Declare.
|
||||
(gimple_call_arg_flags): Likewise.
|
||||
* gimple.c (gimple_call_arg_flags): New function.
|
||||
(gimple_call_return_flags): Likewise.
|
||||
* tree.h (EAF_DIRECT, EAF_NOCLOBBER, EAF_NOESCAPE, EAF_UNUSED):
|
||||
New argument flags.
|
||||
(ERF_RETURN_ARG_MASK, ERF_RETURNS_ARG, ERF_NOALIAS): New function
|
||||
return value flags.
|
||||
* tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Skip unused args.
|
||||
* tree-ssa-structalias.c (make_constraint_from_heapvar): Split
|
||||
main work to ...
|
||||
(make_heapvar_for): ... this new function.
|
||||
(handle_rhs_call): Handle fnspec attribute argument specifiers.
|
||||
(handle_lhs_call): Likewise.
|
||||
(find_func_aliases): Adjust.
|
||||
|
||||
2010-05-10 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/44050
|
||||
|
|
|
@ -529,6 +529,7 @@ static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
|
|||
static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_target_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
|
||||
|
||||
static void check_function_nonnull (tree, int, tree *);
|
||||
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
|
||||
|
@ -829,6 +830,10 @@ const struct attribute_spec c_common_attribute_table[] =
|
|||
handle_target_attribute },
|
||||
{ "optimize", 1, -1, true, false, false,
|
||||
handle_optimize_attribute },
|
||||
/* For internal use (marking of builtins and runtime functions) only.
|
||||
The name contains space to prevent its usage in source code. */
|
||||
{ "fn spec", 1, 1, false, true, true,
|
||||
handle_fnspec_attribute },
|
||||
{ NULL, 0, 0, false, false, false, NULL }
|
||||
};
|
||||
|
||||
|
@ -7138,6 +7143,20 @@ handle_alloc_size_attribute (tree *node, tree ARG_UNUSED (name), tree args,
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Handle a "fn spec" attribute; arguments as in
|
||||
struct attribute_spec.handler. */
|
||||
|
||||
static tree
|
||||
handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
|
||||
tree args, int ARG_UNUSED (flags),
|
||||
bool *no_add_attrs ATTRIBUTE_UNUSED)
|
||||
{
|
||||
gcc_assert (args
|
||||
&& TREE_CODE (TREE_VALUE (args)) == STRING_CST
|
||||
&& !TREE_CHAIN (args));
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Handle a "returns_twice" attribute; arguments as in
|
||||
struct attribute_spec.handler. */
|
||||
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
2010-05-10 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
* trans-decl.c (gfc_build_library_function_decl): Split out
|
||||
worker to ...
|
||||
(build_library_function_decl_1): ... this new function.
|
||||
Set a fnspec attribute if a specification was provided.
|
||||
(gfc_build_library_function_decl_with_spec): New function.
|
||||
(gfc_build_intrinsic_function_decls): Annotate internal_pack
|
||||
and internal_unpack.
|
||||
|
||||
2010-05-07 Daniel Franke <franke.daniel@gmail.com>
|
||||
|
||||
PR fortran/40728
|
||||
|
|
|
@ -2317,22 +2317,19 @@ gfc_get_fake_result_decl (gfc_symbol * sym, int parent_flag)
|
|||
/* Builds a function decl. The remaining parameters are the types of the
|
||||
function arguments. Negative nargs indicates a varargs function. */
|
||||
|
||||
tree
|
||||
gfc_build_library_function_decl (tree name, tree rettype, int nargs, ...)
|
||||
static tree
|
||||
build_library_function_decl_1 (tree name, const char *spec,
|
||||
tree rettype, int nargs, va_list p)
|
||||
{
|
||||
tree arglist;
|
||||
tree argtype;
|
||||
tree fntype;
|
||||
tree fndecl;
|
||||
va_list p;
|
||||
int n;
|
||||
|
||||
/* Library functions must be declared with global scope. */
|
||||
gcc_assert (current_function_decl == NULL_TREE);
|
||||
|
||||
va_start (p, nargs);
|
||||
|
||||
|
||||
/* Create a list of the argument types. */
|
||||
for (arglist = NULL_TREE, n = abs (nargs); n > 0; n--)
|
||||
{
|
||||
|
@ -2348,6 +2345,14 @@ gfc_build_library_function_decl (tree name, tree rettype, int nargs, ...)
|
|||
|
||||
/* Build the function type and decl. */
|
||||
fntype = build_function_type (rettype, arglist);
|
||||
if (spec)
|
||||
{
|
||||
tree attr_args = build_tree_list (NULL_TREE,
|
||||
build_string (strlen (spec), spec));
|
||||
tree attrs = tree_cons (get_identifier ("fn spec"),
|
||||
attr_args, TYPE_ATTRIBUTES (fntype));
|
||||
fntype = build_type_attribute_variant (fntype, attrs);
|
||||
}
|
||||
fndecl = build_decl (input_location,
|
||||
FUNCTION_DECL, name, fntype);
|
||||
|
||||
|
@ -2355,8 +2360,6 @@ gfc_build_library_function_decl (tree name, tree rettype, int nargs, ...)
|
|||
DECL_EXTERNAL (fndecl) = 1;
|
||||
TREE_PUBLIC (fndecl) = 1;
|
||||
|
||||
va_end (p);
|
||||
|
||||
pushdecl (fndecl);
|
||||
|
||||
rest_of_decl_compilation (fndecl, 1, 0);
|
||||
|
@ -2364,6 +2367,37 @@ gfc_build_library_function_decl (tree name, tree rettype, int nargs, ...)
|
|||
return fndecl;
|
||||
}
|
||||
|
||||
/* Builds a function decl. The remaining parameters are the types of the
|
||||
function arguments. Negative nargs indicates a varargs function. */
|
||||
|
||||
tree
|
||||
gfc_build_library_function_decl (tree name, tree rettype, int nargs, ...)
|
||||
{
|
||||
tree ret;
|
||||
va_list args;
|
||||
va_start (args, nargs);
|
||||
ret = build_library_function_decl_1 (name, NULL, rettype, nargs, args);
|
||||
va_end (args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Builds a function decl. The remaining parameters are the types of the
|
||||
function arguments. Negative nargs indicates a varargs function.
|
||||
The SPEC parameter specifies the function argument and return type
|
||||
specification according to the fnspec function type attribute. */
|
||||
|
||||
static tree
|
||||
gfc_build_library_function_decl_with_spec (tree name, const char *spec,
|
||||
tree rettype, int nargs, ...)
|
||||
{
|
||||
tree ret;
|
||||
va_list args;
|
||||
va_start (args, nargs);
|
||||
ret = build_library_function_decl_1 (name, spec, rettype, nargs, args);
|
||||
va_end (args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
gfc_build_intrinsic_function_decls (void)
|
||||
{
|
||||
|
@ -2821,12 +2855,12 @@ gfc_build_builtin_function_decls (void)
|
|||
gfc_build_library_function_decl (get_identifier (PREFIX("set_max_subrecord_length")),
|
||||
void_type_node, 1, integer_type_node);
|
||||
|
||||
gfor_fndecl_in_pack = gfc_build_library_function_decl (
|
||||
get_identifier (PREFIX("internal_pack")),
|
||||
gfor_fndecl_in_pack = gfc_build_library_function_decl_with_spec (
|
||||
get_identifier (PREFIX("internal_pack")), ".r",
|
||||
pvoid_type_node, 1, pvoid_type_node);
|
||||
|
||||
gfor_fndecl_in_unpack = gfc_build_library_function_decl (
|
||||
get_identifier (PREFIX("internal_unpack")),
|
||||
gfor_fndecl_in_unpack = gfc_build_library_function_decl_with_spec (
|
||||
get_identifier (PREFIX("internal_unpack")), ".wR",
|
||||
void_type_node, 2, pvoid_type_node, pvoid_type_node);
|
||||
|
||||
gfor_fndecl_associated =
|
||||
|
|
74
gcc/gimple.c
74
gcc/gimple.c
|
@ -1756,6 +1756,80 @@ gimple_call_flags (const_gimple stmt)
|
|||
return flags;
|
||||
}
|
||||
|
||||
/* Detects argument flags for argument number ARG on call STMT. */
|
||||
|
||||
int
|
||||
gimple_call_arg_flags (const_gimple stmt, unsigned arg)
|
||||
{
|
||||
tree type = TREE_TYPE (TREE_TYPE (gimple_call_fn (stmt)));
|
||||
tree attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
|
||||
if (!attr)
|
||||
return 0;
|
||||
|
||||
attr = TREE_VALUE (TREE_VALUE (attr));
|
||||
if (1 + arg >= (unsigned) TREE_STRING_LENGTH (attr))
|
||||
return 0;
|
||||
|
||||
switch (TREE_STRING_POINTER (attr)[1 + arg])
|
||||
{
|
||||
case 'x':
|
||||
case 'X':
|
||||
return EAF_UNUSED;
|
||||
|
||||
case 'R':
|
||||
return EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE;
|
||||
|
||||
case 'r':
|
||||
return EAF_NOCLOBBER | EAF_NOESCAPE;
|
||||
|
||||
case 'W':
|
||||
return EAF_DIRECT | EAF_NOESCAPE;
|
||||
|
||||
case 'w':
|
||||
return EAF_NOESCAPE;
|
||||
|
||||
case '.':
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Detects return flags for the call STMT. */
|
||||
|
||||
int
|
||||
gimple_call_return_flags (const_gimple stmt)
|
||||
{
|
||||
tree type;
|
||||
tree attr = NULL_TREE;
|
||||
|
||||
if (gimple_call_flags (stmt) & ECF_MALLOC)
|
||||
return ERF_NOALIAS;
|
||||
|
||||
type = TREE_TYPE (TREE_TYPE (gimple_call_fn (stmt)));
|
||||
attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
|
||||
if (!attr)
|
||||
return 0;
|
||||
|
||||
attr = TREE_VALUE (TREE_VALUE (attr));
|
||||
if (TREE_STRING_LENGTH (attr) < 1)
|
||||
return 0;
|
||||
|
||||
switch (TREE_STRING_POINTER (attr)[0])
|
||||
{
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
return ERF_RETURNS_ARG | (TREE_STRING_POINTER (attr)[0] - '1');
|
||||
|
||||
case 'm':
|
||||
return ERF_NOALIAS;
|
||||
|
||||
case '.':
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true if GS is a copy assignment. */
|
||||
|
||||
|
|
|
@ -857,6 +857,8 @@ void gimple_seq_free (gimple_seq);
|
|||
void gimple_seq_add_seq (gimple_seq *, gimple_seq);
|
||||
gimple_seq gimple_seq_copy (gimple_seq);
|
||||
int gimple_call_flags (const_gimple);
|
||||
int gimple_call_return_flags (const_gimple);
|
||||
int gimple_call_arg_flags (const_gimple, unsigned);
|
||||
void gimple_call_reset_alias_info (gimple);
|
||||
bool gimple_assign_copy_p (gimple);
|
||||
bool gimple_assign_ssa_name_copy_p (gimple);
|
||||
|
|
|
@ -1097,6 +1097,10 @@ process_args:
|
|||
for (i = 0; i < gimple_call_num_args (call); ++i)
|
||||
{
|
||||
tree op = gimple_call_arg (call, i);
|
||||
int flags = gimple_call_arg_flags (call, i);
|
||||
|
||||
if (flags & EAF_UNUSED)
|
||||
continue;
|
||||
|
||||
if (TREE_CODE (op) == WITH_SIZE_EXPR)
|
||||
op = TREE_OPERAND (op, 0);
|
||||
|
|
|
@ -3599,11 +3599,11 @@ make_transitive_closure_constraints (varinfo_t vi)
|
|||
process_constraint (new_constraint (lhs, rhs));
|
||||
}
|
||||
|
||||
/* Create a new artificial heap variable with NAME and make a
|
||||
constraint from it to LHS. Return the created variable. */
|
||||
/* Create a new artificial heap variable with NAME.
|
||||
Return the created variable. */
|
||||
|
||||
static varinfo_t
|
||||
make_constraint_from_heapvar (varinfo_t lhs, const char *name)
|
||||
make_heapvar_for (varinfo_t lhs, const char *name)
|
||||
{
|
||||
varinfo_t vi;
|
||||
tree heapvar = heapvar_lookup (lhs->decl, lhs->offset);
|
||||
|
@ -3635,6 +3635,16 @@ make_constraint_from_heapvar (varinfo_t lhs, const char *name)
|
|||
vi->is_full_var = true;
|
||||
insert_vi_for_tree (heapvar, vi);
|
||||
|
||||
return vi;
|
||||
}
|
||||
|
||||
/* Create a new artificial heap variable with NAME and make a
|
||||
constraint from it to LHS. Return the created variable. */
|
||||
|
||||
static varinfo_t
|
||||
make_constraint_from_heapvar (varinfo_t lhs, const char *name)
|
||||
{
|
||||
varinfo_t vi = make_heapvar_for (lhs, name);
|
||||
make_constraint_from (lhs, vi->id);
|
||||
|
||||
return vi;
|
||||
|
@ -3709,17 +3719,61 @@ handle_rhs_call (gimple stmt, VEC(ce_s, heap) **results)
|
|||
{
|
||||
struct constraint_expr rhsc;
|
||||
unsigned i;
|
||||
bool returns_uses = false;
|
||||
|
||||
for (i = 0; i < gimple_call_num_args (stmt); ++i)
|
||||
{
|
||||
tree arg = gimple_call_arg (stmt, i);
|
||||
int flags = gimple_call_arg_flags (stmt, i);
|
||||
|
||||
/* Find those pointers being passed, and make sure they end up
|
||||
pointing to anything. */
|
||||
if (could_have_pointers (arg))
|
||||
/* If the argument is not used or it does not contain pointers
|
||||
we can ignore it. */
|
||||
if ((flags & EAF_UNUSED)
|
||||
|| !could_have_pointers (arg))
|
||||
continue;
|
||||
|
||||
/* As we compute ESCAPED context-insensitive we do not gain
|
||||
any precision with just EAF_NOCLOBBER but not EAF_NOESCAPE
|
||||
set. The argument would still get clobbered through the
|
||||
escape solution.
|
||||
??? We might get away with less (and more precise) constraints
|
||||
if using a temporary for transitively closing things. */
|
||||
if ((flags & EAF_NOCLOBBER)
|
||||
&& (flags & EAF_NOESCAPE))
|
||||
{
|
||||
varinfo_t uses = get_call_use_vi (stmt);
|
||||
if (!(flags & EAF_DIRECT))
|
||||
make_transitive_closure_constraints (uses);
|
||||
make_constraint_to (uses->id, arg);
|
||||
returns_uses = true;
|
||||
}
|
||||
else if (flags & EAF_NOESCAPE)
|
||||
{
|
||||
varinfo_t uses = get_call_use_vi (stmt);
|
||||
varinfo_t clobbers = get_call_clobber_vi (stmt);
|
||||
if (!(flags & EAF_DIRECT))
|
||||
{
|
||||
make_transitive_closure_constraints (uses);
|
||||
make_transitive_closure_constraints (clobbers);
|
||||
}
|
||||
make_constraint_to (uses->id, arg);
|
||||
make_constraint_to (clobbers->id, arg);
|
||||
returns_uses = true;
|
||||
}
|
||||
else
|
||||
make_escape_constraint (arg);
|
||||
}
|
||||
|
||||
/* If we added to the calls uses solution make sure we account for
|
||||
pointers to it to be returned. */
|
||||
if (returns_uses)
|
||||
{
|
||||
rhsc.var = get_call_use_vi (stmt)->id;
|
||||
rhsc.offset = 0;
|
||||
rhsc.type = SCALAR;
|
||||
VEC_safe_push (ce_s, heap, *results, &rhsc);
|
||||
}
|
||||
|
||||
/* The static chain escapes as well. */
|
||||
if (gimple_call_chain (stmt))
|
||||
make_escape_constraint (gimple_call_chain (stmt));
|
||||
|
@ -3752,44 +3806,63 @@ handle_rhs_call (gimple stmt, VEC(ce_s, heap) **results)
|
|||
the LHS point to global and escaped variables. */
|
||||
|
||||
static void
|
||||
handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc, tree fndecl)
|
||||
handle_lhs_call (gimple stmt, tree lhs, int flags, VEC(ce_s, heap) *rhsc,
|
||||
tree fndecl)
|
||||
{
|
||||
VEC(ce_s, heap) *lhsc = NULL;
|
||||
|
||||
get_constraint_for (lhs, &lhsc);
|
||||
/* If the store is to a global decl make sure to
|
||||
add proper escape constraints. */
|
||||
lhs = get_base_address (lhs);
|
||||
if (lhs
|
||||
&& DECL_P (lhs)
|
||||
&& is_global_var (lhs))
|
||||
{
|
||||
struct constraint_expr tmpc;
|
||||
tmpc.var = escaped_id;
|
||||
tmpc.offset = 0;
|
||||
tmpc.type = SCALAR;
|
||||
VEC_safe_push (ce_s, heap, lhsc, &tmpc);
|
||||
}
|
||||
|
||||
if (flags & ECF_MALLOC)
|
||||
/* If the call returns an argument unmodified override the rhs
|
||||
constraints. */
|
||||
flags = gimple_call_return_flags (stmt);
|
||||
if (flags & ERF_RETURNS_ARG
|
||||
&& (flags & ERF_RETURN_ARG_MASK) < gimple_call_num_args (stmt))
|
||||
{
|
||||
tree arg;
|
||||
rhsc = NULL;
|
||||
arg = gimple_call_arg (stmt, flags & ERF_RETURN_ARG_MASK);
|
||||
get_constraint_for (arg, &rhsc);
|
||||
process_all_all_constraints (lhsc, rhsc);
|
||||
VEC_free (ce_s, heap, rhsc);
|
||||
}
|
||||
else if (flags & ERF_NOALIAS)
|
||||
{
|
||||
varinfo_t vi;
|
||||
vi = make_constraint_from_heapvar (get_vi_for_tree (lhs), "HEAP");
|
||||
struct constraint_expr tmpc;
|
||||
rhsc = NULL;
|
||||
vi = make_heapvar_for (get_vi_for_tree (lhs), "HEAP");
|
||||
/* We delay marking allocated storage global until we know if
|
||||
it escapes. */
|
||||
DECL_EXTERNAL (vi->decl) = 0;
|
||||
vi->is_global_var = 0;
|
||||
/* If this is not a real malloc call assume the memory was
|
||||
initialized and thus may point to global memory. All
|
||||
initialized and thus may point to global memory. All
|
||||
builtin functions with the malloc attribute behave in a sane way. */
|
||||
if (!fndecl
|
||||
|| DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
|
||||
make_constraint_from (vi, nonlocal_id);
|
||||
tmpc.var = vi->id;
|
||||
tmpc.offset = 0;
|
||||
tmpc.type = ADDRESSOF;
|
||||
VEC_safe_push (ce_s, heap, rhsc, &tmpc);
|
||||
}
|
||||
else if (VEC_length (ce_s, rhsc) > 0)
|
||||
{
|
||||
/* If the store is to a global decl make sure to
|
||||
add proper escape constraints. */
|
||||
lhs = get_base_address (lhs);
|
||||
if (lhs
|
||||
&& DECL_P (lhs)
|
||||
&& is_global_var (lhs))
|
||||
{
|
||||
struct constraint_expr tmpc;
|
||||
tmpc.var = escaped_id;
|
||||
tmpc.offset = 0;
|
||||
tmpc.type = SCALAR;
|
||||
VEC_safe_push (ce_s, heap, lhsc, &tmpc);
|
||||
}
|
||||
process_all_all_constraints (lhsc, rhsc);
|
||||
}
|
||||
|
||||
process_all_all_constraints (lhsc, rhsc);
|
||||
|
||||
VEC_free (ce_s, heap, lhsc);
|
||||
}
|
||||
|
||||
|
@ -4202,7 +4275,7 @@ find_func_aliases (gimple origt)
|
|||
handle_rhs_call (t, &rhsc);
|
||||
if (gimple_call_lhs (t)
|
||||
&& could_have_pointers (gimple_call_lhs (t)))
|
||||
handle_lhs_call (gimple_call_lhs (t), flags, rhsc, fndecl);
|
||||
handle_lhs_call (t, gimple_call_lhs (t), flags, rhsc, fndecl);
|
||||
VEC_free (ce_s, heap, rhsc);
|
||||
}
|
||||
else
|
||||
|
|
24
gcc/tree.h
24
gcc/tree.h
|
@ -5169,6 +5169,30 @@ extern tree build_duplicate_type (tree);
|
|||
extern int flags_from_decl_or_type (const_tree);
|
||||
extern int call_expr_flags (const_tree);
|
||||
|
||||
/* Call argument flags. */
|
||||
|
||||
/* Nonzero if the argument is not dereferenced recursively, thus only
|
||||
directly reachable memory is read or written. */
|
||||
#define EAF_DIRECT (1 << 0)
|
||||
/* Nonzero if memory reached by the argument is not clobbered. */
|
||||
#define EAF_NOCLOBBER (1 << 1)
|
||||
/* Nonzero if the argument does not escape. */
|
||||
#define EAF_NOESCAPE (1 << 2)
|
||||
/* Nonzero if the argument is not used by the function. */
|
||||
#define EAF_UNUSED (1 << 3)
|
||||
|
||||
/* Call return flags. */
|
||||
|
||||
/* Mask for the argument number that is returned. Lower two bits of
|
||||
the return flags, encodes argument slots zero to three. */
|
||||
#define ERF_RETURN_ARG_MASK (3)
|
||||
/* Nonzero if the return value is equal to the argument number
|
||||
flags & ERF_RETURN_ARG_MASK. */
|
||||
#define ERF_RETURNS_ARG (1 << 2)
|
||||
/* Nonzero if the return value does not alias with anything. Functions
|
||||
with the malloc attribute have this set on their return value. */
|
||||
#define ERF_NOALIAS (1 << 3)
|
||||
|
||||
extern int setjmp_call_p (const_tree);
|
||||
extern bool gimple_alloca_call_p (const_gimple);
|
||||
extern bool alloca_call_p (const_tree);
|
||||
|
|
Loading…
Reference in New Issue