gcc/gcc/tree-iterator.c
Richard Biener 726a989a8b backport: ChangeLog.tuples: ChangeLog from gimple-tuples-branch.
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.

From-SVN: r138207
2008-07-28 14:33:56 +00:00

379 lines
8.6 KiB
C

/* Iterator routines for manipulating GENERIC and GIMPLE tree statements.
Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@redhat.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
#include "gimple.h"
#include "tree-iterator.h"
#include "ggc.h"
/* This is a cache of STATEMENT_LIST nodes. We create and destroy them
fairly often during gimplification. */
static GTY ((deletable (""))) tree stmt_list_cache;
tree
alloc_stmt_list (void)
{
tree list = stmt_list_cache;
if (list)
{
stmt_list_cache = TREE_CHAIN (list);
gcc_assert (stmt_list_cache != list);
memset (list, 0, sizeof(struct tree_common));
TREE_SET_CODE (list, STATEMENT_LIST);
}
else
list = make_node (STATEMENT_LIST);
TREE_TYPE (list) = void_type_node;
return list;
}
void
free_stmt_list (tree t)
{
gcc_assert (!STATEMENT_LIST_HEAD (t));
gcc_assert (!STATEMENT_LIST_TAIL (t));
/* If this triggers, it's a sign that the same list is being freed
twice. */
gcc_assert (t != stmt_list_cache || stmt_list_cache == NULL);
TREE_CHAIN (t) = stmt_list_cache;
stmt_list_cache = t;
}
/* Links a statement, or a chain of statements, before the current stmt. */
void
tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
{
struct tree_statement_list_node *head, *tail, *cur;
/* Die on looping. */
gcc_assert (t != i->container);
if (TREE_CODE (t) == STATEMENT_LIST)
{
head = STATEMENT_LIST_HEAD (t);
tail = STATEMENT_LIST_TAIL (t);
STATEMENT_LIST_HEAD (t) = NULL;
STATEMENT_LIST_TAIL (t) = NULL;
free_stmt_list (t);
/* Empty statement lists need no work. */
if (!head || !tail)
{
gcc_assert (head == tail);
return;
}
}
else
{
head = GGC_NEW (struct tree_statement_list_node);
head->prev = NULL;
head->next = NULL;
head->stmt = t;
tail = head;
}
TREE_SIDE_EFFECTS (i->container) = 1;
cur = i->ptr;
/* Link it into the list. */
if (cur)
{
head->prev = cur->prev;
if (head->prev)
head->prev->next = head;
else
STATEMENT_LIST_HEAD (i->container) = head;
tail->next = cur;
cur->prev = tail;
}
else
{
head->prev = STATEMENT_LIST_TAIL (i->container);
if (head->prev)
head->prev->next = head;
else
STATEMENT_LIST_HEAD (i->container) = head;
STATEMENT_LIST_TAIL (i->container) = tail;
}
/* Update the iterator, if requested. */
switch (mode)
{
case TSI_NEW_STMT:
case TSI_CONTINUE_LINKING:
case TSI_CHAIN_START:
i->ptr = head;
break;
case TSI_CHAIN_END:
i->ptr = tail;
break;
case TSI_SAME_STMT:
break;
}
}
/* Links a statement, or a chain of statements, after the current stmt. */
void
tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
{
struct tree_statement_list_node *head, *tail, *cur;
/* Die on looping. */
gcc_assert (t != i->container);
if (TREE_CODE (t) == STATEMENT_LIST)
{
head = STATEMENT_LIST_HEAD (t);
tail = STATEMENT_LIST_TAIL (t);
STATEMENT_LIST_HEAD (t) = NULL;
STATEMENT_LIST_TAIL (t) = NULL;
free_stmt_list (t);
/* Empty statement lists need no work. */
if (!head || !tail)
{
gcc_assert (head == tail);
return;
}
}
else
{
head = GGC_NEW (struct tree_statement_list_node);
head->prev = NULL;
head->next = NULL;
head->stmt = t;
tail = head;
}
TREE_SIDE_EFFECTS (i->container) = 1;
cur = i->ptr;
/* Link it into the list. */
if (cur)
{
tail->next = cur->next;
if (tail->next)
tail->next->prev = tail;
else
STATEMENT_LIST_TAIL (i->container) = tail;
head->prev = cur;
cur->next = head;
}
else
{
gcc_assert (!STATEMENT_LIST_TAIL (i->container));
STATEMENT_LIST_HEAD (i->container) = head;
STATEMENT_LIST_TAIL (i->container) = tail;
}
/* Update the iterator, if requested. */
switch (mode)
{
case TSI_NEW_STMT:
case TSI_CHAIN_START:
i->ptr = head;
break;
case TSI_CONTINUE_LINKING:
case TSI_CHAIN_END:
i->ptr = tail;
break;
case TSI_SAME_STMT:
gcc_assert (cur);
break;
}
}
/* Remove a stmt from the tree list. The iterator is updated to point to
the next stmt. */
void
tsi_delink (tree_stmt_iterator *i)
{
struct tree_statement_list_node *cur, *next, *prev;
cur = i->ptr;
next = cur->next;
prev = cur->prev;
if (prev)
prev->next = next;
else
STATEMENT_LIST_HEAD (i->container) = next;
if (next)
next->prev = prev;
else
STATEMENT_LIST_TAIL (i->container) = prev;
if (!next && !prev)
TREE_SIDE_EFFECTS (i->container) = 0;
i->ptr = next;
}
/* Move all statements in the statement list after I to a new
statement list. I itself is unchanged. */
tree
tsi_split_statement_list_after (const tree_stmt_iterator *i)
{
struct tree_statement_list_node *cur, *next;
tree old_sl, new_sl;
cur = i->ptr;
/* How can we possibly split after the end, or before the beginning? */
gcc_assert (cur);
next = cur->next;
old_sl = i->container;
new_sl = alloc_stmt_list ();
TREE_SIDE_EFFECTS (new_sl) = 1;
STATEMENT_LIST_HEAD (new_sl) = next;
STATEMENT_LIST_TAIL (new_sl) = STATEMENT_LIST_TAIL (old_sl);
STATEMENT_LIST_TAIL (old_sl) = cur;
cur->next = NULL;
next->prev = NULL;
return new_sl;
}
/* Move all statements in the statement list before I to a new
statement list. I is set to the head of the new list. */
tree
tsi_split_statement_list_before (tree_stmt_iterator *i)
{
struct tree_statement_list_node *cur, *prev;
tree old_sl, new_sl;
cur = i->ptr;
/* How can we possibly split after the end, or before the beginning? */
gcc_assert (cur);
prev = cur->prev;
old_sl = i->container;
new_sl = alloc_stmt_list ();
TREE_SIDE_EFFECTS (new_sl) = 1;
i->container = new_sl;
STATEMENT_LIST_HEAD (new_sl) = cur;
STATEMENT_LIST_TAIL (new_sl) = STATEMENT_LIST_TAIL (old_sl);
STATEMENT_LIST_TAIL (old_sl) = prev;
cur->prev = NULL;
if (prev)
prev->next = NULL;
else
STATEMENT_LIST_HEAD (old_sl) = NULL;
return new_sl;
}
/* Return the first expression in a sequence of COMPOUND_EXPRs,
or in a STATEMENT_LIST. */
tree
expr_first (tree expr)
{
if (expr == NULL_TREE)
return expr;
if (TREE_CODE (expr) == STATEMENT_LIST)
{
struct tree_statement_list_node *n = STATEMENT_LIST_HEAD (expr);
return n ? n->stmt : NULL_TREE;
}
while (TREE_CODE (expr) == COMPOUND_EXPR)
expr = TREE_OPERAND (expr, 0);
return expr;
}
/* Return the last expression in a sequence of COMPOUND_EXPRs,
or in a STATEMENT_LIST. */
#define EXPR_LAST_BODY do { \
if (expr == NULL_TREE) \
return expr;\
if (TREE_CODE (expr) == STATEMENT_LIST) \
{ \
struct tree_statement_list_node *n = STATEMENT_LIST_TAIL (expr); \
return n ? n->stmt : NULL_TREE; \
} \
while (TREE_CODE (expr) == COMPOUND_EXPR) \
expr = TREE_OPERAND (expr, 1); \
return expr; \
} while (0)
tree
expr_last (tree expr)
{
if (expr == NULL_TREE)
return expr;
if (TREE_CODE (expr) == STATEMENT_LIST)
{
struct tree_statement_list_node *n = STATEMENT_LIST_TAIL (expr);
return n ? n->stmt : NULL_TREE;
}
while (TREE_CODE (expr) == COMPOUND_EXPR)
expr = TREE_OPERAND (expr, 1);
return expr;
}
/* If EXPR is a single statement return it. If EXPR is a
STATEMENT_LIST containing exactly one statement S, return S.
Otherwise, return NULL. */
tree
expr_only (tree expr)
{
if (expr == NULL_TREE)
return NULL_TREE;
if (TREE_CODE (expr) == STATEMENT_LIST)
{
struct tree_statement_list_node *n = STATEMENT_LIST_TAIL (expr);
if (n && STATEMENT_LIST_HEAD (expr) == n)
return n->stmt;
else
return NULL_TREE;
}
if (TREE_CODE (expr) == COMPOUND_EXPR)
return NULL_TREE;
return expr;
}
#include "gt-tree-iterator.h"