aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-flow-inline.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-flow-inline.h')
-rw-r--r--gcc/tree-flow-inline.h688
1 files changed, 688 insertions, 0 deletions
diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h
new file mode 100644
index 00000000000..e68e63eb8ed
--- /dev/null
+++ b/gcc/tree-flow-inline.h
@@ -0,0 +1,688 @@
+/* Inline functions for tree-flow.h
+ Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+ Contributed by Diego Novillo <dnovillo@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 2, 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 COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef _TREE_FLOW_INLINE_H
+#define _TREE_FLOW_INLINE_H 1
+
+/* Inline functions for manipulating various data structures defined in
+ tree-flow.h. See tree-flow.h for documentation. */
+
+/* Return the variable annotation for T, which must be a _DECL node.
+ Return NULL if the variable annotation doesn't already exist. */
+static inline var_ann_t
+var_ann (tree t)
+{
+#if defined ENABLE_CHECKING
+ if (t == NULL_TREE
+ || !DECL_P (t)
+ || (t->common.ann
+ && t->common.ann->common.type != VAR_ANN))
+ abort ();
+#endif
+
+ return (var_ann_t) t->common.ann;
+}
+
+/* Return the variable annotation for T, which must be a _DECL node.
+ Create the variable annotation if it doesn't exist. */
+static inline var_ann_t
+get_var_ann (tree var)
+{
+ var_ann_t ann = var_ann (var);
+ return (ann) ? ann : create_var_ann (var);
+}
+
+/* Return the statement annotation for T, which must be a statement
+ node. Return NULL if the statement annotation doesn't exist. */
+static inline stmt_ann_t
+stmt_ann (tree t)
+{
+#if defined ENABLE_CHECKING
+ if (!is_gimple_stmt (t))
+ abort ();
+#endif
+
+ return (stmt_ann_t) t->common.ann;
+}
+
+/* Return the statement annotation for T, which must be a statement
+ node. Create the statement annotation if it doesn't exist. */
+static inline stmt_ann_t
+get_stmt_ann (tree stmt)
+{
+ stmt_ann_t ann = stmt_ann (stmt);
+ return (ann) ? ann : create_stmt_ann (stmt);
+}
+
+
+/* Return the annotation type for annotation ANN. */
+static inline enum tree_ann_type
+ann_type (tree_ann_t ann)
+{
+ return ann->common.type;
+}
+
+/* Return the basic block for statement T. */
+static inline basic_block
+bb_for_stmt (tree t)
+{
+ stmt_ann_t ann = stmt_ann (t);
+ return ann ? ann->bb : NULL;
+}
+
+/* Return the may_aliases varray for variable VAR, or NULL if it has
+ no may aliases. */
+static inline varray_type
+may_aliases (tree var)
+{
+ var_ann_t ann = var_ann (var);
+ return ann ? ann->may_aliases : NULL;
+}
+
+/* Return true if VAR has a hidden use, false if it does not. */
+static inline bool
+has_hidden_use (tree var)
+{
+ var_ann_t ann = var_ann (var);
+ return ann ? ann->has_hidden_use : false;
+}
+
+/* Set the hidden use flag on VAR. */
+static inline void
+set_has_hidden_use (tree var)
+{
+ var_ann_t ann = var_ann (var);
+ if (ann == NULL)
+ ann = create_var_ann (var);
+ ann->has_hidden_use = 1;
+}
+
+/* Return the line number for EXPR, or return -1 if we have no line
+ number information for it. */
+static inline int
+get_lineno (tree expr)
+{
+ if (expr == NULL_TREE)
+ return -1;
+
+ if (TREE_CODE (expr) == COMPOUND_EXPR)
+ expr = TREE_OPERAND (expr, 0);
+
+ if (! EXPR_HAS_LOCATION (expr))
+ return -1;
+
+ return EXPR_LINENO (expr);
+}
+
+/* Return the file name for EXPR, or return "???" if we have no
+ filename information. */
+static inline const char *
+get_filename (tree expr)
+{
+ const char *filename;
+ if (expr == NULL_TREE)
+ return "???";
+
+ if (TREE_CODE (expr) == COMPOUND_EXPR)
+ expr = TREE_OPERAND (expr, 0);
+
+ if (EXPR_HAS_LOCATION (expr) && (filename = EXPR_FILENAME (expr)))
+ return filename;
+ else
+ return "???";
+}
+
+/* Mark statement T as modified. */
+static inline void
+modify_stmt (tree t)
+{
+ stmt_ann_t ann = stmt_ann (t);
+ if (ann == NULL)
+ ann = create_stmt_ann (t);
+ ann->modified = 1;
+}
+
+/* Mark statement T as unmodified. */
+static inline void
+unmodify_stmt (tree t)
+{
+ stmt_ann_t ann = stmt_ann (t);
+ if (ann == NULL)
+ ann = create_stmt_ann (t);
+ ann->modified = 0;
+}
+
+/* Return true if T is marked as modified, false otherwise. */
+static inline bool
+stmt_modified_p (tree t)
+{
+ stmt_ann_t ann = stmt_ann (t);
+
+ /* Note that if the statement doesn't yet have an annotation, we consider it
+ modified. This will force the next call to get_stmt_operands to scan the
+ statement. */
+ return ann ? ann->modified : true;
+}
+
+/* Return the definitions present in ANN, a statement annotation.
+ Return NULL if this annotation contains no definitions. */
+static inline def_optype
+get_def_ops (stmt_ann_t ann)
+{
+ return ann ? ann->def_ops : NULL;
+}
+
+/* Return the uses present in ANN, a statement annotation.
+ Return NULL if this annotation contains no uses. */
+static inline use_optype
+get_use_ops (stmt_ann_t ann)
+{
+ return ann ? ann->use_ops : NULL;
+}
+
+/* Return the virtual may-defs present in ANN, a statement
+ annotation.
+ Return NULL if this annotation contains no virtual may-defs. */
+static inline v_may_def_optype
+get_v_may_def_ops (stmt_ann_t ann)
+{
+ return ann ? ann->v_may_def_ops : NULL;
+}
+
+/* Return the virtual uses present in ANN, a statement annotation.
+ Return NULL if this annotation contains no virtual uses. */
+static inline vuse_optype
+get_vuse_ops (stmt_ann_t ann)
+{
+ return ann ? ann->vuse_ops : NULL;
+}
+
+/* Return the virtual must-defs present in ANN, a statement
+ annotation. Return NULL if this annotation contains no must-defs.*/
+static inline v_must_def_optype
+get_v_must_def_ops (stmt_ann_t ann)
+{
+ return ann ? ann->v_must_def_ops : NULL;
+}
+
+/* Return the tree pointer to by USE. */
+static inline tree
+get_use_from_ptr (use_operand_p use)
+{
+ return *(use.use);
+}
+
+/* Return the tree pointer to by DEF. */
+static inline tree
+get_def_from_ptr (def_operand_p def)
+{
+ return *(def.def);
+}
+
+/* Return a pointer to the tree that is at INDEX in the USES array. */
+static inline use_operand_p
+get_use_op_ptr (use_optype uses, unsigned int index)
+{
+#ifdef ENABLE_CHECKING
+ if (index >= uses->num_uses)
+ abort();
+#endif
+ return uses->uses[index];
+}
+
+/* Return a def_operand_p pointer for element INDEX of DEFS. */
+static inline def_operand_p
+get_def_op_ptr (def_optype defs, unsigned int index)
+{
+#ifdef ENABLE_CHECKING
+ if (index >= defs->num_defs)
+ abort();
+#endif
+ return defs->defs[index];
+}
+
+
+/* Return the def_operand_p that is the V_MAY_DEF_RESULT for the V_MAY_DEF
+ at INDEX in the V_MAY_DEFS array. */
+static inline def_operand_p
+get_v_may_def_result_ptr(v_may_def_optype v_may_defs, unsigned int index)
+{
+ def_operand_p op;
+#ifdef ENABLE_CHECKING
+ if (index >= v_may_defs->num_v_may_defs)
+ abort();
+#endif
+ op.def = &(v_may_defs->v_may_defs[index * 2]);
+ return op;
+}
+
+/* Return a use_operand_p that is the V_MAY_DEF_OP for the V_MAY_DEF at
+ INDEX in the V_MAY_DEFS array. */
+static inline use_operand_p
+get_v_may_def_op_ptr(v_may_def_optype v_may_defs, unsigned int index)
+{
+ use_operand_p op;
+#ifdef ENABLE_CHECKING
+ if (index >= v_may_defs->num_v_may_defs)
+ abort();
+#endif
+ op.use = &(v_may_defs->v_may_defs[index * 2 + 1]);
+ return op;
+}
+
+/* Return a use_operand_p that is at INDEX in the VUSES array. */
+static inline use_operand_p
+get_vuse_op_ptr(vuse_optype vuses, unsigned int index)
+{
+ use_operand_p op;
+#ifdef ENABLE_CHECKING
+ if (index >= vuses->num_vuses)
+ abort();
+#endif
+ op.use = &(vuses->vuses[index]);
+ return op;
+}
+
+/* Return a def_operand_p that is the V_MUST_DEF_OP for the
+ V_MUST_DEF at INDEX in the V_MUST_DEFS array. */
+static inline def_operand_p
+get_v_must_def_op_ptr (v_must_def_optype v_must_defs, unsigned int index)
+{
+ def_operand_p op;
+#ifdef ENABLE_CHECKING
+ if (index >= v_must_defs->num_v_must_defs)
+ abort();
+#endif
+ op.def = &(v_must_defs->v_must_defs[index]);
+ return op;
+}
+
+/* Return a def_operand_p pointer for the result of PHI. */
+static inline def_operand_p
+get_phi_result_ptr (tree phi)
+{
+ def_operand_p op;
+ op.def = &(PHI_RESULT_TREE (phi));
+ return op;
+}
+
+/* Return a use_operand_p pointer for argument I of phinode PHI. */
+static inline use_operand_p
+get_phi_arg_def_ptr (tree phi, int i)
+{
+ use_operand_p op;
+ op.use = &(PHI_ARG_DEF_TREE (phi, i));
+ return op;
+}
+
+/* Mark the beginning of changes to the SSA operands for STMT. */
+static inline void
+start_ssa_stmt_operands (tree stmt ATTRIBUTE_UNUSED)
+{
+#ifdef ENABLE_CHECKING
+ verify_start_operands (stmt);
+#endif
+}
+
+/* Return the bitmap of addresses taken by STMT, or NULL if it takes
+ no addresses. */
+static inline bitmap
+addresses_taken (tree stmt)
+{
+ stmt_ann_t ann = stmt_ann (stmt);
+ return ann ? ann->addresses_taken : NULL;
+}
+
+/* Return the immediate uses of STMT, or NULL if this information is
+ not computed. */
+static dataflow_t
+get_immediate_uses (tree stmt)
+{
+ stmt_ann_t ann = stmt_ann (stmt);
+ return ann ? ann->df : NULL;
+}
+
+/* Return the number of immediate uses present in the dataflow
+ information at DF. */
+static inline int
+num_immediate_uses (dataflow_t df)
+{
+ varray_type imm;
+
+ if (!df)
+ return 0;
+
+ imm = df->immediate_uses;
+ if (!imm)
+ return df->uses[1] ? 2 : 1;
+
+ return VARRAY_ACTIVE_SIZE (imm) + 2;
+}
+
+/* Return the tree that is at NUM in the immediate use DF array. */
+static inline tree
+immediate_use (dataflow_t df, int num)
+{
+ if (!df)
+ return NULL_TREE;
+
+#ifdef ENABLE_CHECKING
+ if (num >= num_immediate_uses (df))
+ abort ();
+#endif
+ if (num < 2)
+ return df->uses[num];
+ return VARRAY_TREE (df->immediate_uses, num - 2);
+}
+
+/* Return the basic_block annotation for BB. */
+static inline bb_ann_t
+bb_ann (basic_block bb)
+{
+ return (bb_ann_t)bb->tree_annotations;
+}
+
+/* Return the PHI nodes for basic block BB, or NULL if there are no
+ PHI nodes. */
+static inline tree
+phi_nodes (basic_block bb)
+{
+ if (bb->index < 0)
+ return NULL;
+ return bb_ann (bb)->phi_nodes;
+}
+
+/* Set list of phi nodes of a basic block BB to L. */
+
+static inline void
+set_phi_nodes (basic_block bb, tree l)
+{
+ tree phi;
+
+ bb_ann (bb)->phi_nodes = l;
+ for (phi = l; phi; phi = PHI_CHAIN (phi))
+ set_bb_for_stmt (phi, bb);
+}
+
+/* Return the phi index number for an edge. */
+static inline int
+phi_arg_from_edge (tree phi, edge e)
+{
+ int i;
+#if defined ENABLE_CHECKING
+ if (!phi || TREE_CODE (phi) != PHI_NODE)
+ abort();
+#endif
+
+ for (i = 0; i < PHI_NUM_ARGS (phi); i++)
+ if (PHI_ARG_EDGE (phi, i) == e)
+ return i;
+
+ return -1;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* Return true if T is an executable statement. */
+static inline bool
+is_exec_stmt (tree t)
+{
+ return (t && !IS_EMPTY_STMT (t) && t != error_mark_node);
+}
+
+
+/* Return true if this stmt can be the target of a control transfer stmt such
+ as a goto. */
+static inline bool
+is_label_stmt (tree t)
+{
+ if (t)
+ switch (TREE_CODE (t))
+ {
+ case LABEL_DECL:
+ case LABEL_EXPR:
+ case CASE_LABEL_EXPR:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
+/* Set the default definition for VAR to DEF. */
+static inline void
+set_default_def (tree var, tree def)
+{
+ var_ann_t ann = var_ann (var);
+ if (ann == NULL)
+ ann = create_var_ann (var);
+ ann->default_def = def;
+}
+
+/* Return the default definition for variable VAR, or NULL if none
+ exists. */
+static inline tree
+default_def (tree var)
+{
+ var_ann_t ann = var_ann (var);
+ return ann ? ann->default_def : NULL_TREE;
+}
+
+/* PHI nodes should contain only ssa_names and invariants. A test
+ for ssa_name is definitely simpler; don't let invalid contents
+ slip in in the meantime. */
+
+static inline bool
+phi_ssa_name_p (tree t)
+{
+ if (TREE_CODE (t) == SSA_NAME)
+ return true;
+#ifdef ENABLE_CHECKING
+ if (!is_gimple_min_invariant (t))
+ abort ();
+#endif
+ return false;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* Return a block_stmt_iterator that points to beginning of basic
+ block BB. */
+static inline block_stmt_iterator
+bsi_start (basic_block bb)
+{
+ block_stmt_iterator bsi;
+ if (bb->stmt_list)
+ bsi.tsi = tsi_start (bb->stmt_list);
+ else
+ {
+#ifdef ENABLE_CHECKING
+ if (bb->index >= 0)
+ abort ();
+#endif
+ bsi.tsi.ptr = NULL;
+ bsi.tsi.container = NULL;
+ }
+ bsi.bb = bb;
+ return bsi;
+}
+
+/* Return a block statement iterator that points to the last label in
+ block BB. */
+
+static inline block_stmt_iterator
+bsi_after_labels (basic_block bb)
+{
+ block_stmt_iterator bsi;
+ tree_stmt_iterator next;
+
+ bsi.bb = bb;
+
+ if (!bb->stmt_list)
+ {
+#ifdef ENABLE_CHECKING
+ if (bb->index >= 0)
+ abort ();
+#endif
+ bsi.tsi.ptr = NULL;
+ bsi.tsi.container = NULL;
+ return bsi;
+ }
+
+ bsi.tsi = tsi_start (bb->stmt_list);
+ if (tsi_end_p (bsi.tsi))
+ return bsi;
+
+ /* Ensure that there are some labels. The rationale is that we want
+ to insert after the bsi that is returned, and these insertions should
+ be placed at the start of the basic block. This would not work if the
+ first statement was not label; rather fail here than enable the user
+ proceed in wrong way. */
+ if (TREE_CODE (tsi_stmt (bsi.tsi)) != LABEL_EXPR)
+ abort ();
+
+ next = bsi.tsi;
+ tsi_next (&next);
+
+ while (!tsi_end_p (next)
+ && TREE_CODE (tsi_stmt (next)) == LABEL_EXPR)
+ {
+ bsi.tsi = next;
+ tsi_next (&next);
+ }
+
+ return bsi;
+}
+
+/* Return a block statement iterator that points to the end of basic
+ block BB. */
+static inline block_stmt_iterator
+bsi_last (basic_block bb)
+{
+ block_stmt_iterator bsi;
+ if (bb->stmt_list)
+ bsi.tsi = tsi_last (bb->stmt_list);
+ else
+ {
+#ifdef ENABLE_CHECKING
+ if (bb->index >= 0)
+ abort ();
+#endif
+ bsi.tsi.ptr = NULL;
+ bsi.tsi.container = NULL;
+ }
+ bsi.bb = bb;
+ return bsi;
+}
+
+/* Return true if block statement iterator I has reached the end of
+ the basic block. */
+static inline bool
+bsi_end_p (block_stmt_iterator i)
+{
+ return tsi_end_p (i.tsi);
+}
+
+/* Modify block statement iterator I so that it is at the next
+ statement in the basic block. */
+static inline void
+bsi_next (block_stmt_iterator *i)
+{
+ tsi_next (&i->tsi);
+}
+
+/* Modify block statement iterator I so that it is at the previous
+ statement in the basic block. */
+static inline void
+bsi_prev (block_stmt_iterator *i)
+{
+ tsi_prev (&i->tsi);
+}
+
+/* Return the statement that block statement iterator I is currently
+ at. */
+static inline tree
+bsi_stmt (block_stmt_iterator i)
+{
+ return tsi_stmt (i.tsi);
+}
+
+/* Return a pointer to the statement that block statement iterator I
+ is currently at. */
+static inline tree *
+bsi_stmt_ptr (block_stmt_iterator i)
+{
+ return tsi_stmt_ptr (i.tsi);
+}
+
+/* Return true if VAR may be aliased. */
+static inline bool
+may_be_aliased (tree var)
+{
+ return (TREE_ADDRESSABLE (var)
+ || decl_function_context (var) != current_function_decl);
+}
+
+/* Return true if VAR is a clobbered by function calls. */
+static inline bool
+is_call_clobbered (tree var)
+{
+ return needs_to_live_in_memory (var)
+ || bitmap_bit_p (call_clobbered_vars, var_ann (var)->uid);
+}
+
+/* Mark variable VAR as being clobbered by function calls. */
+static inline void
+mark_call_clobbered (tree var)
+{
+ var_ann_t ann = var_ann (var);
+ /* Call-clobbered variables need to live in memory. */
+ DECL_NEEDS_TO_LIVE_IN_MEMORY_INTERNAL (var) = 1;
+ bitmap_set_bit (call_clobbered_vars, ann->uid);
+}
+
+/* Mark variable VAR as being non-addressable. */
+static inline void
+mark_non_addressable (tree var)
+{
+ bitmap_clear_bit (call_clobbered_vars, var_ann (var)->uid);
+ DECL_NEEDS_TO_LIVE_IN_MEMORY_INTERNAL (var) = 0;
+ TREE_ADDRESSABLE (var) = 0;
+}
+
+/* Return the common annotation for T. Return NULL if the annotation
+ doesn't already exist. */
+static inline tree_ann_t
+tree_ann (tree t)
+{
+ return t->common.ann;
+}
+
+/* Return a common annotation for T. Create the constant annotation if it
+ doesn't exist. */
+static inline tree_ann_t
+get_tree_ann (tree t)
+{
+ tree_ann_t ann = tree_ann (t);
+ return (ann) ? ann : create_tree_ann (t);
+}
+
+#endif /* _TREE_FLOW_INLINE_H */