diff options
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 431 |
1 files changed, 230 insertions, 201 deletions
diff --git a/gcc/tree.c b/gcc/tree.c index 5dfdcaf6e96..cdecd707f00 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -105,8 +105,7 @@ const char *const tree_code_class_strings[] = "binary", "statement", "vl_exp", - "expression", - "gimple_stmt" + "expression" }; /* obstack.[ch] explicitly declined to prototype this. */ @@ -132,14 +131,12 @@ static const char * const tree_node_kind_names[] = { "temp_tree_lists", "vecs", "binfos", - "phi_nodes", "ssa names", "constructors", "random kinds", "lang_decl kinds", "lang_type kinds", "omp clauses", - "gimple statements" }; #endif /* GATHER_STATISTICS */ @@ -175,6 +172,16 @@ static GTY (()) tree int_cst_node; static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node))) htab_t int_cst_hash_table; +/* Hash table for optimization flags and target option flags. Use the same + hash table for both sets of options. Nodes for building the current + optimization and target option nodes. The assumption is most of the time + the options created will already be in the hash table, so we avoid + allocating and freeing up a node repeatably. */ +static GTY (()) tree cl_optimization_node; +static GTY (()) tree cl_target_option_node; +static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node))) + htab_t cl_option_hash_table; + /* General tree->tree mapping structure for use in hash tables. */ @@ -196,6 +203,8 @@ static int type_hash_eq (const void *, const void *); static hashval_t type_hash_hash (const void *); static hashval_t int_cst_hash_hash (const void *); static int int_cst_hash_eq (const void *, const void *); +static hashval_t cl_option_hash_hash (const void *); +static int cl_option_hash_eq (const void *, const void *); static void print_type_hash_statistics (void); static void print_debug_expr_statistics (void); static void print_value_expr_statistics (void); @@ -273,6 +282,12 @@ init_ttree (void) int_cst_node = make_node (INTEGER_CST); + cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash, + cl_option_hash_eq, NULL); + + cl_optimization_node = make_node (OPTIMIZATION_NODE); + cl_target_option_node = make_node (TARGET_OPTION_NODE); + tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON] = 1; tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_NON_COMMON] = 1; tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON] = 1; @@ -422,7 +437,7 @@ decl_assembler_name_hash (const_tree asmname) /* Compute the number of bytes occupied by a tree with code CODE. This function cannot be used for nodes that have variable sizes, - including TREE_VEC, PHI_NODE, STRING_CST, and CALL_EXPR. */ + including TREE_VEC, STRING_CST, and CALL_EXPR. */ size_t tree_code_size (enum tree_code code) { @@ -470,10 +485,6 @@ tree_code_size (enum tree_code code) return (sizeof (struct tree_exp) + (TREE_CODE_LENGTH (code) - 1) * sizeof (tree)); - case tcc_gimple_stmt: - return (sizeof (struct gimple_stmt) - + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *)); - case tcc_constant: /* a constant */ switch (code) { @@ -497,14 +508,15 @@ tree_code_size (enum tree_code code) case PLACEHOLDER_EXPR: return sizeof (struct tree_common); case TREE_VEC: - case OMP_CLAUSE: - case PHI_NODE: gcc_unreachable (); + case OMP_CLAUSE: gcc_unreachable (); case SSA_NAME: return sizeof (struct tree_ssa_name); case STATEMENT_LIST: return sizeof (struct tree_statement_list); case BLOCK: return sizeof (struct tree_block); case CONSTRUCTOR: return sizeof (struct tree_constructor); + case OPTIMIZATION_NODE: return sizeof (struct tree_optimization_option); + case TARGET_OPTION_NODE: return sizeof (struct tree_target_option); default: return lang_hooks.tree_size (code); @@ -523,10 +535,6 @@ tree_size (const_tree node) const enum tree_code code = TREE_CODE (node); switch (code) { - case PHI_NODE: - return (sizeof (struct tree_phi_node) - + (PHI_ARG_CAPACITY (node) - 1) * sizeof (struct phi_arg_d)); - case TREE_BINFO: return (offsetof (struct tree_binfo, base_binfos) + VEC_embedded_size (tree, BINFO_N_BASE_BINFOS (node))); @@ -554,9 +562,8 @@ tree_size (const_tree node) /* Return a newly allocated node of code CODE. For decl and type nodes, some other fields are initialized. The rest of the node is - initialized to zero. This function cannot be used for PHI_NODE, - TREE_VEC or OMP_CLAUSE nodes, which is enforced by asserts in - tree_code_size. + initialized to zero. This function cannot be used for TREE_VEC or + OMP_CLAUSE nodes, which is enforced by asserts in tree_code_size. Achoo! I got a code in the node. */ @@ -598,10 +605,6 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) kind = c_kind; break; - case tcc_gimple_stmt: - kind = gimple_stmt_kind; - break; - case tcc_exceptional: /* something random, like an identifier. */ switch (code) { @@ -617,10 +620,6 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) kind = binfo_kind; break; - case PHI_NODE: - kind = phi_kind; - break; - case SSA_NAME: kind = ssa_name_kind; break; @@ -719,17 +718,6 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) } break; - case tcc_gimple_stmt: - switch (code) - { - case GIMPLE_MODIFY_STMT: - TREE_SIDE_EFFECTS (t) = 1; - break; - - default: - break; - } - default: /* Other classes need no special treatment. */ break; @@ -754,8 +742,7 @@ copy_node_stat (tree node MEM_STAT_DECL) t = (tree) ggc_alloc_zone_pass_stat (length, &tree_zone); memcpy (t, node, length); - if (!GIMPLE_TUPLE_P (node)) - TREE_CHAIN (t) = 0; + TREE_CHAIN (t) = 0; TREE_ASM_WRITTEN (t) = 0; TREE_VISITED (t) = 0; t->base.ann = 0; @@ -2023,10 +2010,6 @@ expr_align (const_tree t) align1 = TYPE_ALIGN (TREE_TYPE (t)); return MAX (align0, align1); - case GIMPLE_MODIFY_STMT: - /* We should never ask for the alignment of a gimple statement. */ - gcc_unreachable (); - case SAVE_EXPR: case COMPOUND_EXPR: case MODIFY_EXPR: case INIT_EXPR: case TARGET_EXPR: case WITH_CLEANUP_EXPR: case CLEANUP_POINT_EXPR: @@ -2398,8 +2381,6 @@ tree_node_structure (const_tree t) case tcc_statement: case tcc_vl_exp: return TS_EXP; - case tcc_gimple_stmt: - return TS_GIMPLE_STATEMENT; default: /* tcc_constant and tcc_exceptional */ break; } @@ -2413,13 +2394,10 @@ tree_node_structure (const_tree t) case VECTOR_CST: return TS_VECTOR; case STRING_CST: return TS_STRING; /* tcc_exceptional cases. */ - /* FIXME tuples: eventually this should be TS_BASE. For now, nothing - returns TS_BASE. */ case ERROR_MARK: return TS_COMMON; case IDENTIFIER_NODE: return TS_IDENTIFIER; case TREE_LIST: return TS_LIST; case TREE_VEC: return TS_VEC; - case PHI_NODE: return TS_PHI_NODE; case SSA_NAME: return TS_SSA_NAME; case PLACEHOLDER_EXPR: return TS_COMMON; case STATEMENT_LIST: return TS_STATEMENT_LIST; @@ -2427,6 +2405,8 @@ tree_node_structure (const_tree t) case CONSTRUCTOR: return TS_CONSTRUCTOR; case TREE_BINFO: return TS_BINFO; case OMP_CLAUSE: return TS_OMP_CLAUSE; + case OPTIMIZATION_NODE: return TS_OPTIMIZATION; + case TARGET_OPTION_NODE: return TS_TARGET_OPTION; default: gcc_unreachable (); @@ -3267,15 +3247,6 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) gcc_assert (TREE_CODE_LENGTH (code) == 2); -#if 1 - /* FIXME tuples: Statement's aren't expressions! */ - if (code == GIMPLE_MODIFY_STMT) - return build_gimple_modify_stmt_stat (arg0, arg1 PASS_MEM_STAT); -#else - /* Must use build_gimple_modify_stmt to construct GIMPLE_MODIFY_STMTs. */ - gcc_assert (code != GIMPLE_MODIFY_STMT); -#endif - if ((code == MINUS_EXPR || code == PLUS_EXPR || code == MULT_EXPR) && arg0 && arg1 && tt && POINTER_TYPE_P (tt)) gcc_assert (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST); @@ -3314,21 +3285,6 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) } -/* Build a GIMPLE_MODIFY_STMT node. This tree code doesn't have a - type, so we can't use build2 (a.k.a. build2_stat). */ - -tree -build_gimple_modify_stmt_stat (tree arg0, tree arg1 MEM_STAT_DECL) -{ - tree t; - - t = make_node_stat (GIMPLE_MODIFY_STMT PASS_MEM_STAT); - /* ?? We don't care about setting flags for tuples... */ - GIMPLE_STMT_OPERAND (t, 0) = arg0; - GIMPLE_STMT_OPERAND (t, 1) = arg1; - return t; -} - tree build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, tree arg2 MEM_STAT_DECL) @@ -3579,79 +3535,14 @@ expand_location (source_location loc) /* Source location accessor functions. */ -/* The source location of this expression. Non-tree_exp nodes such as - decls and constants can be shared among multiple locations, so - return nothing. */ -location_t -expr_location (const_tree node) -{ - if (GIMPLE_STMT_P (node)) - return GIMPLE_STMT_LOCUS (node); - return EXPR_P (node) ? node->exp.locus : UNKNOWN_LOCATION; -} - -void -set_expr_location (tree node, location_t locus) -{ - if (GIMPLE_STMT_P (node)) - GIMPLE_STMT_LOCUS (node) = locus; - else - EXPR_CHECK (node)->exp.locus = locus; -} - -bool -expr_has_location (const_tree node) -{ - return expr_location (node) != UNKNOWN_LOCATION; -} - -source_location * -expr_locus (const_tree node) -{ - if (GIMPLE_STMT_P (node)) - return CONST_CAST (source_location *, &GIMPLE_STMT_LOCUS (node)); - return (EXPR_P (node) - ? CONST_CAST (source_location *, &node->exp.locus) - : (source_location *) NULL); -} - void set_expr_locus (tree node, source_location *loc) { if (loc == NULL) - { - if (GIMPLE_STMT_P (node)) - GIMPLE_STMT_LOCUS (node) = UNKNOWN_LOCATION; - else - EXPR_CHECK (node)->exp.locus = UNKNOWN_LOCATION; - } + EXPR_CHECK (node)->exp.locus = UNKNOWN_LOCATION; else - { - if (GIMPLE_STMT_P (node)) - GIMPLE_STMT_LOCUS (node) = *loc; - else - EXPR_CHECK (node)->exp.locus = *loc; - } -} - -/* Return the file name of the location of NODE. */ -const char * -expr_filename (const_tree node) -{ - if (GIMPLE_STMT_P (node)) - return LOCATION_FILE (GIMPLE_STMT_LOCUS (node)); - return LOCATION_FILE (EXPR_CHECK (node)->exp.locus); + EXPR_CHECK (node)->exp.locus = *loc; } - -/* Return the line number of the location of NODE. */ -int -expr_lineno (const_tree node) -{ - if (GIMPLE_STMT_P (node)) - return LOCATION_LINE (GIMPLE_STMT_LOCUS (node)); - return LOCATION_LINE (EXPR_CHECK (node)->exp.locus); -} - /* Return a declaration like DDECL except that its DECL_ATTRIBUTES is ATTRIBUTE. */ @@ -5352,7 +5243,7 @@ commutative_tree_code (enum tree_code code) } /* Generate a hash value for an expression. This can be used iteratively - by passing a previous result as the "val" argument. + by passing a previous result as the VAL argument. This function is intended to produce the same hash for expressions which would compare equal using operand_equal_p. */ @@ -5480,6 +5371,29 @@ iterative_hash_expr (const_tree t, hashval_t val) break; } } + +/* Generate a hash value for a pair of expressions. This can be used + iteratively by passing a previous result as the VAL argument. + + The same hash value is always returned for a given pair of expressions, + regardless of the order in which they are presented. This is useful in + hashing the operands of commutative functions. */ + +hashval_t +iterative_hash_exprs_commutative (const_tree t1, + const_tree t2, hashval_t val) +{ + hashval_t one = iterative_hash_expr (t1, 0); + hashval_t two = iterative_hash_expr (t2, 0); + hashval_t t; + + if (one > two) + t = one, one = two, two = t; + val = iterative_hash_hashval_t (one, val); + val = iterative_hash_hashval_t (two, val); + + return val; +} /* Constructors for pointer, array and function types. (RECORD_TYPE, UNION_TYPE and ENUMERAL_TYPE nodes are @@ -6467,8 +6381,7 @@ get_type_static_bounds (const_tree type, mpz_t min, mpz_t max) } } -/* auto_var_in_fn_p is called to determine whether VAR is an automatic - variable defined in function FN. */ +/* Return true if VAR is an automatic variable defined in function FN. */ bool auto_var_in_fn_p (const_tree var, const_tree fn) @@ -7106,18 +7019,6 @@ tree_vec_elt_check_failed (int idx, int len, const char *file, int line, idx + 1, len, function, trim_filename (file), line); } -/* Similar to above, except that the check is for the bounds of a PHI_NODE's - (dynamically sized) vector. */ - -void -phi_node_elt_check_failed (int idx, int len, const char *file, int line, - const char *function) -{ - internal_error - ("tree check: accessed elt %d of phi_node with %d elts in %s, at %s:%d", - idx + 1, len, function, trim_filename (file), line); -} - /* Similar to above, except that the check is for the bounds of the operand vector of an expression node EXP. */ @@ -8668,6 +8569,10 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len)); } + case CHANGE_DYNAMIC_TYPE_EXPR: + WALK_SUBTREE (CHANGE_DYNAMIC_TYPE_NEW_TYPE (*tp)); + WALK_SUBTREE_TAIL (CHANGE_DYNAMIC_TYPE_LOCATION (*tp)); + case DECL_EXPR: /* If this is a TYPE_DECL, walk into the fields of the type that it's defining. We only want to walk into these fields of a type in this @@ -8739,8 +8644,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, /* FALLTHRU */ default: - if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) - || IS_GIMPLE_STMT_CODE_CLASS (TREE_CODE_CLASS (code))) + if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))) { int i, len; @@ -8752,8 +8656,8 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, if (len) { for (i = 0; i < len - 1; ++i) - WALK_SUBTREE (GENERIC_TREE_OPERAND (*tp, i)); - WALK_SUBTREE_TAIL (GENERIC_TREE_OPERAND (*tp, len - 1)); + WALK_SUBTREE (TREE_OPERAND (*tp, i)); + WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1)); } } /* If this is a type, walk the needed fields in the type. */ @@ -8785,31 +8689,6 @@ walk_tree_without_duplicates_1 (tree *tp, walk_tree_fn func, void *data, } -/* Return true if STMT is an empty statement or contains nothing but - empty statements. */ - -bool -empty_body_p (tree stmt) -{ - tree_stmt_iterator i; - tree body; - - if (IS_EMPTY_STMT (stmt)) - return true; - else if (TREE_CODE (stmt) == BIND_EXPR) - body = BIND_EXPR_BODY (stmt); - else if (TREE_CODE (stmt) == STATEMENT_LIST) - body = stmt; - else - return false; - - for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i)) - if (!empty_body_p (tsi_stmt (i))) - return false; - - return true; -} - tree * tree_block (tree t) { @@ -8817,28 +8696,10 @@ tree_block (tree t) if (IS_EXPR_CODE_CLASS (c)) return &t->exp.block; - else if (IS_GIMPLE_STMT_CODE_CLASS (c)) - return &GIMPLE_STMT_BLOCK (t); gcc_unreachable (); return NULL; } -tree * -generic_tree_operand (tree node, int i) -{ - if (GIMPLE_STMT_P (node)) - return &GIMPLE_STMT_OPERAND (node, i); - return &TREE_OPERAND (node, i); -} - -tree * -generic_tree_type (tree node) -{ - if (GIMPLE_STMT_P (node)) - return &void_type_node; - return &TREE_TYPE (node); -} - /* Build and return a TREE_LIST of arguments in the CALL_EXPR exp. FIXME: don't use this function. It exists for compatibility with the old representation of CALL_EXPRs where a list was used to hold the @@ -8854,6 +8715,46 @@ call_expr_arglist (tree exp) return arglist; } + +/* Create a nameless artificial label and put it in the current function + context. Returns the newly created label. */ + +tree +create_artificial_label (void) +{ + tree lab = build_decl (LABEL_DECL, NULL_TREE, void_type_node); + + DECL_ARTIFICIAL (lab) = 1; + DECL_IGNORED_P (lab) = 1; + DECL_CONTEXT (lab) = current_function_decl; + return lab; +} + +/* Given a tree, try to return a useful variable name that we can use + to prefix a temporary that is being assigned the value of the tree. + I.E. given <temp> = &A, return A. */ + +const char * +get_name (tree t) +{ + tree stripped_decl; + + stripped_decl = t; + STRIP_NOPS (stripped_decl); + if (DECL_P (stripped_decl) && DECL_NAME (stripped_decl)) + return IDENTIFIER_POINTER (DECL_NAME (stripped_decl)); + else + { + switch (TREE_CODE (stripped_decl)) + { + case ADDR_EXPR: + return get_name (TREE_OPERAND (stripped_decl, 0)); + default: + return NULL; + } + } +} + /* Return true if TYPE has a variable argument list. */ bool @@ -8942,4 +8843,132 @@ block_nonartificial_location (tree block) return ret; } +/* These are the hash table functions for the hash table of OPTIMIZATION_NODEq + nodes. */ + +/* Return the hash code code X, an OPTIMIZATION_NODE or TARGET_OPTION code. */ + +static hashval_t +cl_option_hash_hash (const void *x) +{ + const_tree const t = (const_tree) x; + const char *p; + size_t i; + size_t len = 0; + hashval_t hash = 0; + + if (TREE_CODE (t) == OPTIMIZATION_NODE) + { + p = (const char *)TREE_OPTIMIZATION (t); + len = sizeof (struct cl_optimization); + } + + else if (TREE_CODE (t) == TARGET_OPTION_NODE) + { + p = (const char *)TREE_TARGET_OPTION (t); + len = sizeof (struct cl_target_option); + } + + else + gcc_unreachable (); + + /* assume most opt flags are just 0/1, some are 2-3, and a few might be + something else. */ + for (i = 0; i < len; i++) + if (p[i]) + hash = (hash << 4) ^ ((i << 2) | p[i]); + + return hash; +} + +/* Return nonzero if the value represented by *X (an OPTIMIZATION or + TARGET_OPTION tree node) is the same as that given by *Y, which is the + same. */ + +static int +cl_option_hash_eq (const void *x, const void *y) +{ + const_tree const xt = (const_tree) x; + const_tree const yt = (const_tree) y; + const char *xp; + const char *yp; + size_t len; + + if (TREE_CODE (xt) != TREE_CODE (yt)) + return 0; + + if (TREE_CODE (xt) == OPTIMIZATION_NODE) + { + xp = (const char *)TREE_OPTIMIZATION (xt); + yp = (const char *)TREE_OPTIMIZATION (yt); + len = sizeof (struct cl_optimization); + } + + else if (TREE_CODE (xt) == TARGET_OPTION_NODE) + { + xp = (const char *)TREE_TARGET_OPTION (xt); + yp = (const char *)TREE_TARGET_OPTION (yt); + len = sizeof (struct cl_target_option); + } + + else + gcc_unreachable (); + + return (memcmp (xp, yp, len) == 0); +} + +/* Build an OPTIMIZATION_NODE based on the current options. */ + +tree +build_optimization_node (void) +{ + tree t; + void **slot; + + /* Use the cache of optimization nodes. */ + + cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node)); + + slot = htab_find_slot (cl_option_hash_table, cl_optimization_node, INSERT); + t = (tree) *slot; + if (!t) + { + /* Insert this one into the hash table. */ + t = cl_optimization_node; + *slot = t; + + /* Make a new node for next time round. */ + cl_optimization_node = make_node (OPTIMIZATION_NODE); + } + + return t; +} + +/* Build a TARGET_OPTION_NODE based on the current options. */ + +tree +build_target_option_node (void) +{ + tree t; + void **slot; + + /* Use the cache of optimization nodes. */ + + cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node)); + + slot = htab_find_slot (cl_option_hash_table, cl_target_option_node, INSERT); + t = (tree) *slot; + if (!t) + { + /* Insert this one into the hash table. */ + t = cl_target_option_node; + *slot = t; + + /* Make a new node for next time round. */ + cl_target_option_node = make_node (TARGET_OPTION_NODE); + } + + return t; +} + #include "gt-tree.h" |