summaryrefslogtreecommitdiff
path: root/gcc/ipa-type-escape.c
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2008-07-28 14:33:56 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2008-07-28 14:33:56 +0000
commit75a70cf95f65fe9204b15ad9aba31c571381d224 (patch)
tree2926705dd533a8904679724ab1cec40dfee45094 /gcc/ipa-type-escape.c
parentd0a9db40355cf570989e2aca92ab2060df234926 (diff)
downloadgcc-75a70cf95f65fe9204b15ad9aba31c571381d224.tar.gz
2008-07-28 Richard Guenther <rguenther@suse.de>
Merge from gimple-tuples-branch. * ChangeLog.tuples: ChangeLog from gimple-tuples-branch. * gimple.def: New file. * gsstruct.def: Likewise. * gimple-iterator.c: Likewise. * gimple-pretty-print.c: Likewise. * tree-gimple.c: Removed. Merged into ... * gimple.c: ... here. New file. * tree-gimple.h: Removed. Merged into ... * gimple.h: ... here. New file. * Makefile.in: Add dependencies on GIMPLE_H and tree-iterator.h. * configure.ac: Added support for ENABLE_GIMPLE_CHECKING and the --enable-checking=gimple flag. * config.in: Likewise. * configure: Regenerated. * tree-ssa-operands.h: Tuplified. * tree-vrp.c: Likewise. * tree-loop-linear.c: Likewise. * tree-into-ssa.c: Likewise. * tree-ssa-loop-im.c: Likewise. * tree-dump.c: Likewise. * tree-complex.c: Likewise. * cgraphbuild.c: Likewise. * tree-ssa-threadupdate.c: Likewise. * tree-ssa-loop-niter.c: Likewise. * tree-pretty-print.c: Likewise. * tracer.c: Likewise. * gengtype.c: Likewise. * tree-loop-distribution.c: Likewise. * tree-ssa-loop-unswitch.c: Likewise. * cgraph.c: Likewise. * cgraph.h: Likewise. * tree-ssa-loop-manip.c: Likewise. * value-prof.c: Likewise. * tree-ssa-loop-ch.c: Likewise. * tree-tailcall.c: Likewise. * value-prof.h: Likewise. * tree.c: Likewise. * tree.h: Likewise. * tree-pass.h: Likewise. * ipa-cp.c: Likewise. * tree-scalar-evolution.c: Likewise. * tree-scalar-evolution.h: Likewise. * target.h: Likewise. * lambda-mat.c: Likewise. * tree-phinodes.c: Likewise. * diagnostic.h: Likewise. * builtins.c: Likewise. * tree-ssa-alias-warnings.c: Likewise. * cfghooks.c: Likewise. * fold-const.c: Likewise. * cfghooks.h: Likewise. * omp-low.c: Likewise. * tree-ssa-dse.c: Likewise. * ipa-reference.c: Likewise. * tree-ssa-uncprop.c: Likewise. * toplev.c: Likewise. * tree-gimple.c: Likewise. * tree-gimple.h: Likewise. * tree-chrec.c: Likewise. * tree-chrec.h: Likewise. * tree-ssa-sccvn.c: Likewise. * tree-ssa-sccvn.h: Likewise. * cgraphunit.c: Likewise. * tree-ssa-copyrename.c: Likewise. * tree-ssa-ccp.c: Likewise. * tree-ssa-loop-ivopts.c: Likewise. * tree-nomudflap.c: Likewise. * tree-call-cdce.c: Likewise. * ipa-pure-const.c: Likewise. * c-format.c: Likewise. * tree-stdarg.c: Likewise. * tree-ssa-math-opts.c: Likewise. * tree-ssa-dom.c: Likewise. * tree-nrv.c: Likewise. * tree-ssa-propagate.c: Likewise. * ipa-utils.c: Likewise. * tree-ssa-propagate.h: Likewise. * tree-ssa-alias.c: Likewise. * gimple-low.c: Likewise. * tree-ssa-sink.c: Likewise. * ipa-inline.c: Likewise. * c-semantics.c: Likewise. * dwarf2out.c: Likewise. * expr.c: Likewise. * tree-ssa-loop-ivcanon.c: Likewise. * predict.c: Likewise. * tree-ssa-loop.c: Likewise. * tree-parloops.c: Likewise. * tree-ssa-address.c: Likewise. * tree-ssa-ifcombine.c: Likewise. * matrix-reorg.c: Likewise. * c-decl.c: Likewise. * tree-eh.c: Likewise. * c-pretty-print.c: Likewise. * lambda-trans.c: Likewise. * function.c: Likewise. * langhooks.c: Likewise. * ebitmap.h: Likewise. * tree-vectorizer.c: Likewise. * function.h: Likewise. * langhooks.h: Likewise. * tree-vectorizer.h: Likewise. * ipa-type-escape.c: Likewise. * ipa-type-escape.h: Likewise. * domwalk.c: Likewise. * tree-if-conv.c: Likewise. * profile.c: Likewise. * domwalk.h: Likewise. * tree-data-ref.c: Likewise. * tree-data-ref.h: Likewise. * tree-flow-inline.h: Likewise. * tree-affine.c: Likewise. * tree-vect-analyze.c: Likewise. * c-typeck.c: Likewise. * gimplify.c: Likewise. * coretypes.h: Likewise. * tree-ssa-phiopt.c: Likewise. * calls.c: Likewise. * tree-ssa-coalesce.c: Likewise. * tree.def: Likewise. * tree-dfa.c: Likewise. * except.c: Likewise. * except.h: Likewise. * cfgexpand.c: Likewise. * tree-cfgcleanup.c: Likewise. * tree-ssa-pre.c: Likewise. * tree-ssa-live.c: Likewise. * tree-sra.c: Likewise. * tree-ssa-live.h: Likewise. * tree-predcom.c: Likewise. * lambda.h: Likewise. * tree-mudflap.c: Likewise. * ipa-prop.c: Likewise. * print-tree.c: Likewise. * tree-ssa-copy.c: Likewise. * ipa-prop.h: Likewise. * tree-ssa-forwprop.c: Likewise. * ggc-page.c: Likewise. * c-omp.c: Likewise. * tree-ssa-dce.c: Likewise. * tree-vect-patterns.c: Likewise. * tree-ssa-ter.c: Likewise. * tree-nested.c: Likewise. * tree-ssa.c: Likewise. * lambda-code.c: Likewise. * tree-ssa-loop-prefetch.c: Likewise. * tree-inline.c: Likewise. * tree-inline.h: Likewise. * tree-iterator.c: Likewise. * tree-optimize.c: Likewise. * tree-ssa-phiprop.c: Likewise. * tree-vect-transform.c: Likewise. * tree-object-size.c: Likewise. * tree-outof-ssa.c: Likewise. * cfgloop.c: Likewise. * system.h: Likewise. * tree-profile.c: Likewise. * cfgloop.h: Likewise. * c-gimplify.c: Likewise. * c-common.c: Likewise. * tree-vect-generic.c: Likewise. * tree-flow.h: Likewise. * c-common.h: Likewise. * basic-block.h: Likewise. * tree-ssa-structalias.c: Likewise. * tree-switch-conversion.c: Likewise. * tree-ssa-structalias.h: Likewise. * tree-cfg.c: Likewise. * passes.c: Likewise. * ipa-struct-reorg.c: Likewise. * ipa-struct-reorg.h: Likewise. * tree-ssa-reassoc.c: Likewise. * cfgrtl.c: Likewise. * varpool.c: Likewise. * stmt.c: Likewise. * tree-ssanames.c: Likewise. * tree-ssa-threadedge.c: Likewise. * langhooks-def.h: Likewise. * tree-ssa-operands.c: Likewise. * config/alpha/alpha.c: Likewise. * config/frv/frv.c: Likewise. * config/s390/s390.c: Likewise. * config/m32c/m32c.c: Likewise. * config/m32c/m32c-protos.h: Likewise. * config/spu/spu.c: Likewise. * config/sparc/sparc.c: Likewise. * config/i386/i386.c: Likewise. * config/sh/sh.c: Likewise. * config/xtensa/xtensa.c: Likewise. * config/stormy16/stormy16.c: Likewise. * config/ia64/ia64.c: Likewise. * config/rs6000/rs6000.c: Likewise. * config/pa/pa.c: Likewise. * config/mips/mips.c: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@138207 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-type-escape.c')
-rw-r--r--gcc/ipa-type-escape.c517
1 files changed, 220 insertions, 297 deletions
diff --git a/gcc/ipa-type-escape.c b/gcc/ipa-type-escape.c
index 81e6ddb635b..48d95049b4f 100644
--- a/gcc/ipa-type-escape.c
+++ b/gcc/ipa-type-escape.c
@@ -47,7 +47,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-utils.h"
#include "ipa-type-escape.h"
#include "c-common.h"
-#include "tree-gimple.h"
+#include "gimple.h"
#include "cgraph.h"
#include "output.h"
#include "flags.h"
@@ -136,8 +136,8 @@ static bitmap_obstack ipa_obstack;
/* Static functions from this file that are used
before being defined. */
-static unsigned int look_for_casts (tree lhs ATTRIBUTE_UNUSED, tree);
-static bool is_cast_from_non_pointer (tree, tree, void *);
+static unsigned int look_for_casts (tree);
+static bool is_cast_from_non_pointer (tree, gimple, void *);
/* Get the name of TYPE or return the string "<UNNAMED>". */
static const char*
@@ -308,7 +308,7 @@ get_canon_type (tree type, bool see_thru_ptrs, bool see_thru_arrays)
while (POINTER_TYPE_P (type))
type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- result = splay_tree_lookup(type_to_canon_type, (splay_tree_key) type);
+ result = splay_tree_lookup (type_to_canon_type, (splay_tree_key) type);
if (result == NULL)
return discover_unique_type (type);
@@ -663,9 +663,7 @@ check_cast_type (tree to_type, tree from_type)
static bool
is_malloc_result (tree var)
{
- tree def_stmt;
- tree rhs;
- int flags;
+ gimple def_stmt;
if (!var)
return false;
@@ -675,20 +673,13 @@ is_malloc_result (tree var)
def_stmt = SSA_NAME_DEF_STMT (var);
- if (TREE_CODE (def_stmt) != GIMPLE_MODIFY_STMT)
+ if (!is_gimple_call (def_stmt))
return false;
- if (var != GIMPLE_STMT_OPERAND (def_stmt, 0))
+ if (var != gimple_call_lhs (def_stmt))
return false;
- rhs = get_call_expr_in (def_stmt);
-
- if (!rhs)
- return false;
-
- flags = call_expr_flags (rhs);
-
- return ((flags & ECF_MALLOC) != 0);
+ return ((gimple_call_flags (def_stmt) & ECF_MALLOC) != 0);
}
@@ -769,115 +760,98 @@ check_cast (tree to_type, tree from)
return cast;
}
-typedef struct cast
-{
- int type;
- tree stmt;
-}cast_t;
-
-/* This function is a callback for walk_tree called from
- is_cast_from_non_pointer. The data->type is set to be:
- 0 - if there is no cast
- number - the number of casts from non-pointer type
- -1 - if there is a cast that makes the type to escape
+/* Scan assignment statement S to see if there are any casts within it. */
- If data->type = number, then data->stmt will contain the
- last casting stmt met in traversing. */
-
-static tree
-is_cast_from_non_pointer_1 (tree *tp, int *walk_subtrees, void *data)
+static unsigned int
+look_for_casts_stmt (gimple s)
{
- tree def_stmt = *tp;
+ unsigned int cast = 0;
+ gcc_assert (is_gimple_assign (s));
- if (pointer_set_insert (visited_stmts, def_stmt))
+ if (gimple_assign_cast_p (s))
{
- *walk_subtrees = 0;
- return NULL;
+ tree castfromvar = gimple_assign_rhs1 (s);
+ cast |= check_cast (TREE_TYPE (gimple_assign_lhs (s)), castfromvar);
}
-
- switch (TREE_CODE (def_stmt))
+ else
{
- case GIMPLE_MODIFY_STMT:
- {
- use_operand_p use_p;
- ssa_op_iter iter;
- tree lhs = GIMPLE_STMT_OPERAND (def_stmt, 0);
- tree rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
-
- unsigned int cast = look_for_casts (lhs, rhs);
- /* Check that only one cast happened, and it's of
- non-pointer type. */
- if ((cast & CT_FROM_NON_P) == (CT_FROM_NON_P)
- && (cast & ~(CT_FROM_NON_P)) == 0)
- {
- ((cast_t *)data)->stmt = def_stmt;
- ((cast_t *)data)->type++;
-
- FOR_EACH_SSA_USE_OPERAND (use_p, def_stmt, iter, SSA_OP_ALL_USES)
- {
- walk_use_def_chains (USE_FROM_PTR (use_p), is_cast_from_non_pointer,
- data, false);
- if (((cast_t*)data)->type == -1)
- return def_stmt;
- }
- }
-
- /* Check that there is no cast, or cast is not harmful. */
- else if ((cast & CT_NO_CAST) == (CT_NO_CAST)
- || (cast & CT_DOWN) == (CT_DOWN)
- || (cast & CT_UP) == (CT_UP)
- || (cast & CT_USELESS) == (CT_USELESS)
- || (cast & CT_FROM_MALLOC) == (CT_FROM_MALLOC))
- {
- FOR_EACH_SSA_USE_OPERAND (use_p, def_stmt, iter, SSA_OP_ALL_USES)
- {
- walk_use_def_chains (USE_FROM_PTR (use_p), is_cast_from_non_pointer,
- data, false);
- if (((cast_t*)data)->type == -1)
- return def_stmt;
- }
- }
+ size_t i;
+ for (i = 0; i < gimple_num_ops (s); i++)
+ cast |= look_for_casts (gimple_op (s, i));
+ }
- /* The cast is harmful. */
- else
- {
- ((cast_t *)data)->type = -1;
- return def_stmt;
- }
+ if (!cast)
+ cast = CT_NO_CAST;
- *walk_subtrees = 0;
- }
- break;
+ return cast;
+}
- default:
- {
- *walk_subtrees = 0;
- break;
- }
- }
- return NULL;
-}
+typedef struct cast
+{
+ int type;
+ gimple stmt;
+} cast_t;
/* This function is a callback for walk_use_def_chains function called
from is_array_access_through_pointer_and_index. */
static bool
-is_cast_from_non_pointer (tree var, tree def_stmt, void *data)
+is_cast_from_non_pointer (tree var, gimple def_stmt, void *data)
{
-
if (!def_stmt || !var)
return false;
- if (TREE_CODE (def_stmt) == PHI_NODE)
+ if (gimple_code (def_stmt) == GIMPLE_PHI)
return false;
if (SSA_NAME_IS_DEFAULT_DEF (var))
return false;
- walk_tree (&def_stmt, is_cast_from_non_pointer_1, data, NULL);
+ if (is_gimple_assign (def_stmt))
+ {
+ use_operand_p use_p;
+ ssa_op_iter iter;
+ unsigned int cast = look_for_casts_stmt (def_stmt);
+
+ /* Check that only one cast happened, and it's of non-pointer
+ type. */
+ if ((cast & CT_FROM_NON_P) == (CT_FROM_NON_P)
+ && (cast & ~(CT_FROM_NON_P)) == 0)
+ {
+ ((cast_t *)data)->stmt = def_stmt;
+ ((cast_t *)data)->type++;
+
+ FOR_EACH_SSA_USE_OPERAND (use_p, def_stmt, iter, SSA_OP_ALL_USES)
+ {
+ walk_use_def_chains (USE_FROM_PTR (use_p),
+ is_cast_from_non_pointer, data, false);
+ if (((cast_t*)data)->type == -1)
+ break;
+ }
+ }
+ /* Check that there is no cast, or cast is not harmful. */
+ else if ((cast & CT_NO_CAST) == (CT_NO_CAST)
+ || (cast & CT_DOWN) == (CT_DOWN)
+ || (cast & CT_UP) == (CT_UP)
+ || (cast & CT_USELESS) == (CT_USELESS)
+ || (cast & CT_FROM_MALLOC) == (CT_FROM_MALLOC))
+ {
+ FOR_EACH_SSA_USE_OPERAND (use_p, def_stmt, iter, SSA_OP_ALL_USES)
+ {
+ walk_use_def_chains (USE_FROM_PTR (use_p),
+ is_cast_from_non_pointer, data, false);
+ if (((cast_t*)data)->type == -1)
+ break;
+ }
+ }
+ /* The cast is harmful. */
+ else
+ ((cast_t *)data)->type = -1;
+ }
+
if (((cast_t*)data)->type == -1)
return true;
@@ -930,9 +904,10 @@ is_cast_from_non_pointer (tree var, tree def_stmt, void *data)
bool
is_array_access_through_pointer_and_index (enum tree_code code, tree op0,
tree op1, tree *base, tree *offset,
- tree *offset_cast_stmt)
+ gimple *offset_cast_stmt)
{
- tree before_cast, before_cast_def_stmt;
+ tree before_cast;
+ gimple before_cast_def_stmt;
cast_t op0_cast, op1_cast;
*base = NULL;
@@ -1014,26 +989,23 @@ is_array_access_through_pointer_and_index (enum tree_code code, tree op0,
/* before_cast_def_stmt should be of the form:
D.1605_6 = i.1_5 * 16; */
- if (TREE_CODE (before_cast_def_stmt) == GIMPLE_MODIFY_STMT)
+ if (is_gimple_assign (before_cast_def_stmt))
{
- tree lhs = GIMPLE_STMT_OPERAND (before_cast_def_stmt,0);
- tree rhs = GIMPLE_STMT_OPERAND (before_cast_def_stmt,1);
-
/* We expect temporary here. */
- if (!is_gimple_reg (lhs))
+ if (!is_gimple_reg (gimple_assign_lhs (before_cast_def_stmt)))
return false;
- if (TREE_CODE (rhs) == MULT_EXPR)
+ if (gimple_assign_rhs_code (before_cast_def_stmt) == MULT_EXPR)
{
- tree arg0 = TREE_OPERAND (rhs, 0);
- tree arg1 = TREE_OPERAND (rhs, 1);
+ tree arg0 = gimple_assign_rhs1 (before_cast_def_stmt);
+ tree arg1 = gimple_assign_rhs2 (before_cast_def_stmt);
tree unit_size =
TYPE_SIZE_UNIT (TREE_TYPE (TYPE_MAIN_VARIANT (TREE_TYPE (op0))));
if (!(CONSTANT_CLASS_P (arg0)
- && simple_cst_equal (arg0,unit_size))
+ && simple_cst_equal (arg0, unit_size))
&& !(CONSTANT_CLASS_P (arg1)
- && simple_cst_equal (arg1,unit_size)))
+ && simple_cst_equal (arg1, unit_size)))
return false;
}
else
@@ -1173,7 +1145,11 @@ check_tree (tree t)
check_tree (TREE_OPERAND (t, 0));
if (SSA_VAR_P (t) || (TREE_CODE (t) == FUNCTION_DECL))
- check_operand (t);
+ {
+ check_operand (t);
+ if (DECL_P (t) && DECL_INITIAL (t))
+ check_tree (DECL_INITIAL (t));
+ }
}
/* Create an address_of edge FROM_TYPE.TO_TYPE. */
@@ -1260,15 +1236,13 @@ look_for_address_of (tree t)
}
-/* Scan tree T to see if there are any casts within it.
- LHS Is the LHS of the expression involving the cast. */
+/* Scan tree T to see if there are any casts within it. */
static unsigned int
-look_for_casts (tree lhs ATTRIBUTE_UNUSED, tree t)
+look_for_casts (tree t)
{
unsigned int cast = 0;
-
if (is_gimple_cast (t) || TREE_CODE (t) == VIEW_CONVERT_EXPR)
{
tree castfromvar = TREE_OPERAND (t, 0);
@@ -1302,7 +1276,7 @@ static void
check_rhs_var (tree t)
{
look_for_address_of (t);
- check_tree(t);
+ check_tree (t);
}
/* Check to see if T is an assignment to a static var we are
@@ -1311,7 +1285,7 @@ check_rhs_var (tree t)
static void
check_lhs_var (tree t)
{
- check_tree(t);
+ check_tree (t);
}
/* This is a scaled down version of get_asm_expr_operands from
@@ -1322,35 +1296,15 @@ check_lhs_var (tree t)
analyzed and STMT is the actual asm statement. */
static void
-get_asm_expr_operands (tree stmt)
+check_asm (gimple stmt)
{
- int noutputs = list_length (ASM_OUTPUTS (stmt));
- const char **oconstraints
- = (const char **) alloca ((noutputs) * sizeof (const char *));
- int i;
- tree link;
- const char *constraint;
- bool allows_mem, allows_reg, is_inout;
-
- for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
- {
- oconstraints[i] = constraint
- = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
- parse_output_constraint (&constraint, i, 0, 0,
- &allows_mem, &allows_reg, &is_inout);
-
- check_lhs_var (TREE_VALUE (link));
- }
+ size_t i;
- for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
- {
- constraint
- = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
- parse_input_constraint (&constraint, 0, 0, noutputs, 0,
- oconstraints, &allows_mem, &allows_reg);
-
- check_rhs_var (TREE_VALUE (link));
- }
+ for (i = 0; i < gimple_asm_noutputs (stmt); i++)
+ check_lhs_var (gimple_asm_output_op (stmt, i));
+
+ for (i = 0; i < gimple_asm_ninputs (stmt); i++)
+ check_rhs_var (gimple_asm_input_op (stmt, i));
/* There is no code here to check for asm memory clobbers. The
casual maintainer might think that such code would be necessary,
@@ -1360,22 +1314,22 @@ get_asm_expr_operands (tree stmt)
assumed to already escape. So, we are protected here. */
}
-/* Check the parameters of a function call to CALL_EXPR to mark the
+
+/* Check the parameters of function call to CALL to mark the
types that pass across the function boundary. Also check to see if
this is either an indirect call, a call outside the compilation
unit. */
static void
-check_call (tree call_expr)
+check_call (gimple call)
{
- tree operand;
- tree callee_t = get_callee_fndecl (call_expr);
+ tree callee_t = gimple_call_fndecl (call);
struct cgraph_node* callee;
enum availability avail = AVAIL_NOT_AVAILABLE;
- call_expr_arg_iterator iter;
+ size_t i;
- FOR_EACH_CALL_EXPR_ARG (operand, iter, call_expr)
- check_rhs_var (operand);
+ for (i = 0; i < gimple_call_num_args (call); i++)
+ check_rhs_var (gimple_call_arg (call, i));
if (callee_t)
{
@@ -1388,12 +1342,11 @@ check_call (tree call_expr)
parameters. */
if (TYPE_ARG_TYPES (TREE_TYPE (callee_t)))
{
- for (arg_type = TYPE_ARG_TYPES (TREE_TYPE (callee_t)),
- operand = first_call_expr_arg (call_expr, &iter);
+ for (arg_type = TYPE_ARG_TYPES (TREE_TYPE (callee_t)), i = 0;
arg_type && TREE_VALUE (arg_type) != void_type_node;
- arg_type = TREE_CHAIN (arg_type),
- operand = next_call_expr_arg (&iter))
+ arg_type = TREE_CHAIN (arg_type), i++)
{
+ tree operand = gimple_call_arg (call, i);
if (operand)
{
last_arg_type = TREE_VALUE(arg_type);
@@ -1411,15 +1364,14 @@ check_call (tree call_expr)
/* FIXME - According to Geoff Keating, we should never
have to do this; the front ends should always process
the arg list from the TYPE_ARG_LIST. */
- for (arg_type = DECL_ARGUMENTS (callee_t),
- operand = first_call_expr_arg (call_expr, &iter);
+ for (arg_type = DECL_ARGUMENTS (callee_t), i = 0;
arg_type;
- arg_type = TREE_CHAIN (arg_type),
- operand = next_call_expr_arg (&iter))
+ arg_type = TREE_CHAIN (arg_type), i++)
{
+ tree operand = gimple_call_arg (call, i);
if (operand)
{
- last_arg_type = TREE_TYPE(arg_type);
+ last_arg_type = TREE_TYPE (arg_type);
check_cast (last_arg_type, operand);
}
else
@@ -1433,10 +1385,9 @@ check_call (tree call_expr)
/* In the case where we have a var_args function, we need to
check the remaining parameters against the last argument. */
arg_type = last_arg_type;
- for (;
- operand != NULL_TREE;
- operand = next_call_expr_arg (&iter))
+ for ( ; i < gimple_call_num_args (call); i++)
{
+ tree operand = gimple_call_arg (call, i);
if (arg_type)
check_cast (arg_type, operand);
else
@@ -1457,16 +1408,16 @@ check_call (tree call_expr)
are any bits available for the callee (such as by declaration or
because it is builtin) and process solely on the basis of those
bits. */
-
if (avail == AVAIL_NOT_AVAILABLE || avail == AVAIL_OVERWRITABLE)
{
/* If this is a direct call to an external function, mark all of
the parameter and return types. */
- FOR_EACH_CALL_EXPR_ARG (operand, iter, call_expr)
+ for (i = 0; i < gimple_call_num_args (call); i++)
{
+ tree operand = gimple_call_arg (call, i);
tree type = get_canon_type (TREE_TYPE (operand), false, false);
mark_interesting_type (type, EXPOSED_PARAMETER);
- }
+ }
if (callee_t)
{
@@ -1494,7 +1445,8 @@ okay_pointer_operation (enum tree_code code, tree op0, tree op1)
case PLUS_EXPR:
case POINTER_PLUS_EXPR:
{
- tree base, offset, offset_cast_stmt;
+ tree base, offset;
+ gimple offset_cast_stmt;
if (POINTER_TYPE_P (op0type)
&& TREE_CODE (op0) == SSA_NAME
@@ -1528,150 +1480,124 @@ okay_pointer_operation (enum tree_code code, tree op0, tree op1)
return false;
}
-/* TP is the part of the tree currently under the microscope.
- WALK_SUBTREES is part of the walk_tree api but is unused here.
- DATA is cgraph_node of the function being walked. */
-/* FIXME: When this is converted to run over SSA form, this code
- should be converted to use the operand scanner. */
-static tree
-scan_for_refs (tree *tp, int *walk_subtrees, void *data)
+/* Helper for scan_for_refs. Check the operands of an assignment to
+ mark types that may escape. */
+
+static void
+check_assign (gimple t)
{
- struct cgraph_node *fn = (struct cgraph_node *) data;
- tree t = *tp;
+ /* First look on the lhs and see what variable is stored to */
+ check_lhs_var (gimple_assign_lhs (t));
+
+ /* For the purposes of figuring out what the cast affects */
- switch (TREE_CODE (t))
+ /* Next check the operands on the rhs to see if they are ok. */
+ switch (TREE_CODE_CLASS (gimple_assign_rhs_code (t)))
{
- case VAR_DECL:
- if (DECL_INITIAL (t))
- walk_tree (&DECL_INITIAL (t), scan_for_refs, fn, visited_nodes);
- *walk_subtrees = 0;
+ case tcc_binary:
+ {
+ tree op0 = gimple_assign_rhs1 (t);
+ tree type0 = get_canon_type (TREE_TYPE (op0), false, false);
+ tree op1 = gimple_assign_rhs2 (t);
+ tree type1 = get_canon_type (TREE_TYPE (op1), false, false);
+
+ /* If this is pointer arithmetic of any bad sort, then
+ we need to mark the types as bad. For binary
+ operations, no binary operator we currently support
+ is always "safe" in regard to what it would do to
+ pointers for purposes of determining which types
+ escape, except operations of the size of the type.
+ It is possible that min and max under the right set
+ of circumstances and if the moon is in the correct
+ place could be safe, but it is hard to see how this
+ is worth the effort. */
+ if (type0 && POINTER_TYPE_P (type0)
+ && !okay_pointer_operation (gimple_assign_rhs_code (t), op0, op1))
+ mark_interesting_type (type0, FULL_ESCAPE);
+
+ if (type1 && POINTER_TYPE_P (type1)
+ && !okay_pointer_operation (gimple_assign_rhs_code (t), op1, op0))
+ mark_interesting_type (type1, FULL_ESCAPE);
+
+ look_for_casts (op0);
+ look_for_casts (op1);
+ check_rhs_var (op0);
+ check_rhs_var (op1);
+ }
break;
- case GIMPLE_MODIFY_STMT:
+ case tcc_unary:
{
- /* First look on the lhs and see what variable is stored to */
- tree lhs = GIMPLE_STMT_OPERAND (t, 0);
- tree rhs = GIMPLE_STMT_OPERAND (t, 1);
+ tree op0 = gimple_assign_rhs1 (t);
+ tree type0 = get_canon_type (TREE_TYPE (op0), false, false);
+
+ /* For unary operations, if the operation is NEGATE or ABS on
+ a pointer, this is also considered pointer arithmetic and
+ thus, bad for business. */
+ if (type0
+ && POINTER_TYPE_P (type0)
+ && (TREE_CODE (op0) == NEGATE_EXPR
+ || TREE_CODE (op0) == ABS_EXPR))
+ mark_interesting_type (type0, FULL_ESCAPE);
+
+ check_rhs_var (op0);
+ look_for_casts (op0);
+ }
+ break;
- check_lhs_var (lhs);
- check_cast (TREE_TYPE (lhs), rhs);
+ case tcc_reference:
+ look_for_casts (gimple_assign_rhs1 (t));
+ check_rhs_var (gimple_assign_rhs1 (t));
+ break;
- /* For the purposes of figuring out what the cast affects */
+ case tcc_declaration:
+ check_rhs_var (gimple_assign_rhs1 (t));
+ break;
- /* Next check the operands on the rhs to see if they are ok. */
- switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
- {
- case tcc_binary:
- {
- tree op0 = TREE_OPERAND (rhs, 0);
- tree type0 = get_canon_type (TREE_TYPE (op0), false, false);
- tree op1 = TREE_OPERAND (rhs, 1);
- tree type1 = get_canon_type (TREE_TYPE (op1), false, false);
-
- /* If this is pointer arithmetic of any bad sort, then
- we need to mark the types as bad. For binary
- operations, no binary operator we currently support
- is always "safe" in regard to what it would do to
- pointers for purposes of determining which types
- escape, except operations of the size of the type.
- It is possible that min and max under the right set
- of circumstances and if the moon is in the correct
- place could be safe, but it is hard to see how this
- is worth the effort. */
-
- if (type0 && POINTER_TYPE_P (type0)
- && !okay_pointer_operation (TREE_CODE (rhs), op0, op1))
- mark_interesting_type (type0, FULL_ESCAPE);
- if (type1 && POINTER_TYPE_P (type1)
- && !okay_pointer_operation (TREE_CODE (rhs), op1, op0))
- mark_interesting_type (type1, FULL_ESCAPE);
-
- look_for_casts (lhs, op0);
- look_for_casts (lhs, op1);
- check_rhs_var (op0);
- check_rhs_var (op1);
- }
- break;
- case tcc_unary:
- {
- tree op0 = TREE_OPERAND (rhs, 0);
- tree type0 = get_canon_type (TREE_TYPE (op0), false, false);
- /* For unary operations, if the operation is NEGATE or
- ABS on a pointer, this is also considered pointer
- arithmetic and thus, bad for business. */
- if (type0 && (TREE_CODE (op0) == NEGATE_EXPR
- || TREE_CODE (op0) == ABS_EXPR)
- && POINTER_TYPE_P (type0))
- {
- mark_interesting_type (type0, FULL_ESCAPE);
- }
- check_rhs_var (op0);
- look_for_casts (lhs, op0);
- look_for_casts (lhs, rhs);
- }
+ case tcc_expression:
+ if (gimple_assign_rhs_code (t) == ADDR_EXPR)
+ {
+ tree rhs = gimple_assign_rhs1 (t);
+ look_for_casts (TREE_OPERAND (rhs, 0));
+ check_rhs_var (rhs);
+ }
+ break;
- break;
- case tcc_reference:
- look_for_casts (lhs, rhs);
- check_rhs_var (rhs);
- break;
- case tcc_declaration:
- check_rhs_var (rhs);
- break;
- case tcc_expression:
- switch (TREE_CODE (rhs))
- {
- case ADDR_EXPR:
- look_for_casts (lhs, TREE_OPERAND (rhs, 0));
- check_rhs_var (rhs);
- break;
- default:
- break;
- }
- break;
- case tcc_vl_exp:
- switch (TREE_CODE (rhs))
- {
- case CALL_EXPR:
- /* If this is a call to malloc, squirrel away the
- result so we do mark the resulting cast as being
- bad. */
- check_call (rhs);
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- *walk_subtrees = 0;
- }
+ default:
break;
+ }
+}
+
- case ADDR_EXPR:
- /* This case is here to find addresses on rhs of constructors in
- decl_initial of static variables. */
- check_rhs_var (t);
- *walk_subtrees = 0;
+/* Scan statement T for references to types and mark anything
+ interesting. */
+
+static void
+scan_for_refs (gimple t)
+{
+ switch (gimple_code (t))
+ {
+ case GIMPLE_ASSIGN:
+ check_assign (t);
break;
- case CALL_EXPR:
+ case GIMPLE_CALL:
+ /* If this is a call to malloc, squirrel away the result so we
+ do mark the resulting cast as being bad. */
check_call (t);
- *walk_subtrees = 0;
break;
- case ASM_EXPR:
- get_asm_expr_operands (t);
- *walk_subtrees = 0;
+ case GIMPLE_ASM:
+ check_asm (t);
break;
default:
break;
}
- return NULL;
+
+ return;
}
@@ -1721,7 +1647,7 @@ analyze_variable (struct varpool_node *vnode)
gcc_assert (TREE_CODE (global) == VAR_DECL);
if (DECL_INITIAL (global))
- walk_tree (&DECL_INITIAL (global), scan_for_refs, NULL, visited_nodes);
+ check_tree (DECL_INITIAL (global));
}
/* This is the main routine for finding the reference patterns for
@@ -1742,10 +1668,9 @@ analyze_function (struct cgraph_node *fn)
FOR_EACH_BB_FN (this_block, this_cfun)
{
- block_stmt_iterator bsi;
- for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
- walk_tree (bsi_stmt_ptr (bsi), scan_for_refs,
- fn, visited_nodes);
+ gimple_stmt_iterator gsi;
+ for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
+ scan_for_refs (gsi_stmt (gsi));
}
}
@@ -1761,8 +1686,7 @@ analyze_function (struct cgraph_node *fn)
if (TREE_CODE (var) == VAR_DECL
&& DECL_INITIAL (var)
&& !TREE_STATIC (var))
- walk_tree (&DECL_INITIAL (var), scan_for_refs,
- fn, visited_nodes);
+ check_tree (DECL_INITIAL (var));
get_canon_type (TREE_TYPE (var), false, false);
}
}
@@ -2215,4 +2139,3 @@ struct simple_ipa_opt_pass pass_ipa_type_escape =
0 /* todo_flags_finish */
}
};
-