summaryrefslogtreecommitdiff
path: root/gcc/tree.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree.h')
-rw-r--r--gcc/tree.h162
1 files changed, 144 insertions, 18 deletions
diff --git a/gcc/tree.h b/gcc/tree.h
index ed0379c7a87..2df9aabc8f3 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -64,6 +64,8 @@ enum tree_code_class {
tcc_binary, /* A binary arithmetic expression. */
tcc_statement, /* A statement expression, which have side effects
but usually no interesting value. */
+ tcc_vl_exp, /* A function call or other expression with a
+ variable-length operand vector. */
tcc_expression, /* Any other expression. */
tcc_gimple_stmt /* A GIMPLE statement. */
};
@@ -149,6 +151,12 @@ extern const enum tree_code_class tree_code_type[];
#define STATEMENT_CLASS_P(CODE)\
(TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_statement)
+/* Nonzero if CODE represents a function call-like expression with a
+ variable-length operand vector. */
+
+#define VL_EXP_CLASS_P(CODE)\
+ (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_vl_exp)
+
/* Nonzero if CODE represents any other expression. */
#define EXPRESSION_CLASS_P(CODE)\
@@ -779,8 +787,8 @@ enum tree_node_structure_enum {
const int __i = (I); \
if (GIMPLE_TUPLE_P (__t)) \
gcc_unreachable (); \
- if (__i < 0 || __i >= TREE_CODE_LENGTH (TREE_CODE (__t))) \
- tree_operand_check_failed (__i, TREE_CODE (__t), \
+ if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t)) \
+ tree_operand_check_failed (__i, __t, \
__FILE__, __LINE__, __FUNCTION__); \
&__t->exp.operands[__i]; }))
@@ -789,8 +797,8 @@ enum tree_node_structure_enum {
const int __i = (I); \
if (TREE_CODE (__t) != CODE) \
tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, (CODE), 0);\
- if (__i < 0 || __i >= TREE_CODE_LENGTH (CODE)) \
- tree_operand_check_failed (__i, (CODE), \
+ if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t)) \
+ tree_operand_check_failed (__i, __t, \
__FILE__, __LINE__, __FUNCTION__); \
&__t->exp.operands[__i]; }))
@@ -798,8 +806,8 @@ enum tree_node_structure_enum {
#define GIMPLE_STMT_OPERAND_CHECK(T, I) __extension__ \
(*({const tree __t = GIMPLE_STMT_CHECK (T); \
const int __i = (I); \
- if (__i < 0 || __i >= TREE_CODE_LENGTH (TREE_CODE (__t))) \
- tree_operand_check_failed (__i, TREE_CODE (__t), \
+ if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t)) \
+ tree_operand_check_failed (__i, __t, \
__FILE__, __LINE__, __FUNCTION__); \
&__t->gstmt.operands[__i]; }))
@@ -809,8 +817,8 @@ enum tree_node_structure_enum {
const int __i = (I); \
if (TREE_CODE (__t) != (CODE)) \
tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, (CODE), 0); \
- if (__i < 0 || __i >= TREE_CODE_LENGTH ((CODE))) \
- tree_operand_check_failed (__i, (CODE), \
+ if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t)) \
+ tree_operand_check_failed (__i, __t, \
__FILE__, __LINE__, __FUNCTION__); \
&__t->exp.operands[__i]; }))
@@ -864,7 +872,7 @@ extern void tree_vec_elt_check_failed (int, int, const char *,
extern void phi_node_elt_check_failed (int, int, const char *,
int, const char *)
ATTRIBUTE_NORETURN;
-extern void tree_operand_check_failed (int, enum tree_code,
+extern void tree_operand_check_failed (int, tree,
const char *, int, const char *)
ATTRIBUTE_NORETURN;
extern void omp_clause_check_failed (const tree, const char *, int,
@@ -924,6 +932,7 @@ extern void omp_clause_range_check_failed (const tree, const char *, int,
#define DECL_NON_COMMON_CHECK(T) CONTAINS_STRUCT_CHECK (T, TS_DECL_NON_COMMON)
#define CST_CHECK(T) TREE_CLASS_CHECK (T, tcc_constant)
#define STMT_CHECK(T) TREE_CLASS_CHECK (T, tcc_statement)
+#define VL_EXP_CHECK(T) TREE_CLASS_CHECK (T, tcc_vl_exp)
#define FUNC_OR_METHOD_CHECK(T) TREE_CHECK2 (T, FUNCTION_TYPE, METHOD_TYPE)
#define PTR_OR_REF_CHECK(T) TREE_CHECK2 (T, POINTER_TYPE, REFERENCE_TYPE)
@@ -1497,8 +1506,17 @@ struct tree_constructor GTY(())
&& integer_zerop (TREE_OPERAND (NODE, 0)))
/* In ordinary expression nodes. */
+#define TREE_OPERAND_LENGTH(NODE) tree_operand_length (NODE)
#define TREE_OPERAND(NODE, I) TREE_OPERAND_CHECK (NODE, I)
+/* In a tcc_vl_exp node, operand 0 is an INT_CST node holding the operand
+ length. Its value includes the length operand itself; that is,
+ the minimum valid length is 1.
+ Note that we have to bypass the use of TREE_OPERAND to access
+ that field to avoid infinite recursion in expanding the macros. */
+#define VL_EXP_OPERAND_LENGTH(NODE) \
+ ((int)TREE_INT_CST_LOW (VL_EXP_CHECK (NODE)->exp.operands[0]))
+
/* In gimple statements. */
#define GIMPLE_STMT_OPERAND(NODE, I) GIMPLE_STMT_OPERAND_CHECK (NODE, I)
#define GIMPLE_STMT_LOCUS(NODE) (GIMPLE_STMT_CHECK (NODE)->gstmt.locus)
@@ -1613,6 +1631,23 @@ struct tree_constructor GTY(())
#define ASSERT_EXPR_VAR(NODE) TREE_OPERAND (ASSERT_EXPR_CHECK (NODE), 0)
#define ASSERT_EXPR_COND(NODE) TREE_OPERAND (ASSERT_EXPR_CHECK (NODE), 1)
+/* CALL_EXPR accessors.
+ */
+#define CALL_EXPR_FN(NODE) TREE_OPERAND (CALL_EXPR_CHECK (NODE), 1)
+#define CALL_EXPR_STATIC_CHAIN(NODE) TREE_OPERAND (CALL_EXPR_CHECK (NODE), 2)
+#define CALL_EXPR_ARGS(NODE) call_expr_arglist (NODE)
+#define CALL_EXPR_ARG(NODE, I) TREE_OPERAND (CALL_EXPR_CHECK (NODE), (I) + 3)
+#define call_expr_nargs(NODE) (VL_EXP_OPERAND_LENGTH(NODE) - 3)
+
+/* CALL_EXPR_ARGP returns a pointer to the argument vector for NODE.
+ We can't use &CALL_EXPR_ARG (NODE, 0) because that will complain if
+ the argument count is zero when checking is enabled. Instead, do
+ the pointer arithmetic to advance past the 3 fixed operands in a
+ CALL_EXPR. That produces a valid pointer to just past the end of the
+ operand array, even if it's not valid to dereference it. */
+#define CALL_EXPR_ARGP(NODE) \
+ (&(TREE_OPERAND (CALL_EXPR_CHECK (NODE), 0)) + 3)
+
/* OpenMP directive and clause accessors. */
#define OMP_BODY(NODE) \
@@ -3641,6 +3676,7 @@ extern tree maybe_get_identifier (const char *);
/* Construct various types of nodes. */
extern tree build_nt (enum tree_code, ...);
+extern tree build_nt_call_list (tree, tree);
extern tree build0_stat (enum tree_code, tree MEM_STAT_DECL);
#define build0(c,t) build0_stat (c,t MEM_STAT_INFO)
@@ -3691,6 +3727,14 @@ extern void annotate_with_locus (tree, location_t);
extern tree build_empty_stmt (void);
extern tree build_omp_clause (enum omp_clause_code);
+extern tree build_vl_exp_stat (enum tree_code, int MEM_STAT_DECL);
+#define build_vl_exp(c,n) build_vl_exp_stat (c,n MEM_STAT_INFO)
+
+extern tree build_call_list (tree, tree, tree);
+extern tree build_call_nary (tree, tree, int, ...);
+extern tree build_call_valist (tree, tree, int, va_list);
+extern tree build_call_array (tree, tree, int, tree*);
+
/* Construct various nodes representing data types. */
extern tree make_signed_type (int);
@@ -4288,6 +4332,9 @@ extern tree upper_bound_in_type (tree, tree);
extern tree lower_bound_in_type (tree, tree);
extern int operand_equal_for_phi_arg_p (tree, tree);
extern bool empty_body_p (tree);
+extern tree call_expr_arg (tree, int);
+extern tree *call_expr_argp (tree, int);
+extern tree call_expr_arglist (tree);
/* In stmt.c */
@@ -4329,6 +4376,8 @@ extern tree fold_build3_stat (enum tree_code, tree, tree, tree, tree MEM_STAT_DE
extern tree fold_build1_initializer (enum tree_code, tree, tree);
extern tree fold_build2_initializer (enum tree_code, tree, tree, tree);
extern tree fold_build3_initializer (enum tree_code, tree, tree, tree, tree);
+extern tree fold_build_call_list (tree, tree, tree);
+extern tree fold_build_call_list_initializer (tree, tree, tree);
extern tree fold_convert (tree, tree);
extern tree fold_single_bit_test (enum tree_code, tree, tree, tree);
extern tree fold_ignored_result (tree);
@@ -4413,26 +4462,30 @@ extern bool tree_expr_nonzero_p (tree);
extern bool tree_expr_nonzero_warnv_p (tree, bool *);
/* In builtins.c */
-extern tree fold_builtin (tree, tree, bool);
-extern tree fold_builtin_fputs (tree, bool, bool, tree);
-extern tree fold_builtin_strcpy (tree, tree, tree);
-extern tree fold_builtin_strncpy (tree, tree, tree);
-extern tree fold_builtin_memory_chk (tree, tree, tree, bool,
+extern tree fold_call_expr (tree, bool);
+extern tree fold_builtin_fputs (tree, tree, bool, bool, tree);
+extern tree fold_builtin_strcpy (tree, tree, tree, tree);
+extern tree fold_builtin_strncpy (tree, tree, tree, tree, tree);
+extern tree fold_builtin_memory_chk (tree, tree, tree, tree, tree, tree, bool,
enum built_in_function);
-extern tree fold_builtin_stxcpy_chk (tree, tree, tree, bool,
+extern tree fold_builtin_stxcpy_chk (tree, tree, tree, tree, tree, bool,
enum built_in_function);
-extern tree fold_builtin_strncpy_chk (tree, tree);
+extern tree fold_builtin_strncpy_chk (tree, tree, tree, tree, tree);
extern tree fold_builtin_snprintf_chk (tree, tree, enum built_in_function);
-extern bool fold_builtin_next_arg (tree);
+extern bool fold_builtin_next_arg (tree, bool);
extern enum built_in_function builtin_mathfn_code (tree);
extern tree build_function_call_expr (tree, tree);
+extern tree fold_build_call_expr (tree, tree, tree, tree);
+extern tree fold_builtin_call_list (tree, tree, tree);
+extern tree fold_builtin_call_valist (tree, tree, int, va_list);
+extern tree build_call_expr (tree, int, ...);
extern tree mathfn_built_in (tree, enum built_in_function fn);
extern tree strip_float_extensions (tree);
extern tree c_strlen (tree, int);
extern tree std_gimplify_va_arg_expr (tree, tree, tree *, tree *);
extern tree build_va_arg_indirect_ref (tree);
extern tree build_string_literal (int, const char *);
-extern int validate_arglist (tree, ...);
+extern bool validate_arglist (tree, ...);
extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
extern int get_pointer_alignment (tree, unsigned int);
@@ -4786,4 +4839,77 @@ extern unsigned HOST_WIDE_INT highest_pow2_factor (tree);
void init_inline_once (void);
+/* Compute the number of operands in an expression node NODE. For
+ tcc_vl_exp nodes like CALL_EXPRs, this is stored in the node itself,
+ otherwise it is looked up from the node's code. */
+static inline int
+tree_operand_length (tree node)
+{
+ if (VL_EXP_CLASS_P (node))
+ return VL_EXP_OPERAND_LENGTH (node);
+ else
+ return TREE_CODE_LENGTH (TREE_CODE (node));
+}
+
+/* Abstract iterators for CALL_EXPRs. These static inline definitions
+ have to go towards the end of tree.h so that union tree_node is fully
+ defined by this point. */
+
+/* Structure containing iterator state. */
+typedef struct call_expr_arg_iterator_d GTY (())
+{
+ tree t; /* the call_expr */
+ int n; /* argument count */
+ int i; /* next argument index */
+} call_expr_arg_iterator;
+
+/* Initialize the abstract argument list iterator object ITER with the
+ arguments from CALL_EXPR node EXP. */
+static inline void
+init_call_expr_arg_iterator (tree exp, call_expr_arg_iterator *iter)
+{
+ iter->t = exp;
+ iter->n = call_expr_nargs (exp);
+ iter->i = 0;
+}
+
+/* Return the next argument from abstract argument list iterator object ITER,
+ and advance its state. Return NULL_TREE if there are no more arguments. */
+static inline tree
+next_call_expr_arg (call_expr_arg_iterator *iter)
+{
+ tree result;
+ if (iter->i >= iter->n)
+ return NULL_TREE;
+ result = CALL_EXPR_ARG (iter->t, iter->i);
+ iter->i++;
+ return result;
+}
+
+/* Initialize the abstract argument list iterator object ITER, then advance
+ past and return the first argument. Useful in for expressions, e.g.
+ for (arg = first_call_expr_arg (exp, &iter); arg;
+ arg = next_call_expr_arg (&iter)) */
+static inline tree
+first_call_expr_arg (tree exp, call_expr_arg_iterator *iter)
+{
+ init_call_expr_arg_iterator (exp, iter);
+ return next_call_expr_arg (iter);
+}
+
+/* Test whether there are more arguments in abstract argument list iterator
+ ITER, without changing its state. */
+static inline bool
+more_call_expr_args_p (const call_expr_arg_iterator *iter)
+{
+ return (iter->i < iter->n);
+}
+
+
+/* Iterate through each argument ARG of CALL_EXPR CALL, using variable ITER
+ (of type call_expr_arg_iterator) to hold the iteration state. */
+#define FOR_EACH_CALL_EXPR_ARG(arg, iter, call) \
+ for ((arg) = first_call_expr_arg ((call), &(iter)); (arg); \
+ (arg) = next_call_expr_arg (&(iter)))
+
#endif /* GCC_TREE_H */