| /* Language-independent node constructors for parse phase of GNU compiler. |
| Copyright (C) 1987-2015 Free Software Foundation, Inc. |
| |
| 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/>. */ |
| |
| /* This file contains the low level primitives for operating on tree nodes, |
| including allocation, list operations, interning of identifiers, |
| construction of data type nodes and statement nodes, |
| and construction of type conversion nodes. It also contains |
| tables index by tree code that describe how to take apart |
| nodes of that code. |
| |
| It is intended to be language-independent, but occasionally |
| calls language-dependent routines defined (for C) in typecheck.c. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include "coretypes.h" |
| #include "tm.h" |
| #include "flags.h" |
| #include "hash-set.h" |
| #include "machmode.h" |
| #include "vec.h" |
| #include "double-int.h" |
| #include "input.h" |
| #include "alias.h" |
| #include "symtab.h" |
| #include "wide-int.h" |
| #include "inchash.h" |
| #include "tree.h" |
| #include "fold-const.h" |
| #include "stor-layout.h" |
| #include "calls.h" |
| #include "attribs.h" |
| #include "varasm.h" |
| #include "tm_p.h" |
| #include "hashtab.h" |
| #include "hard-reg-set.h" |
| #include "function.h" |
| #include "obstack.h" |
| #include "toplev.h" /* get_random_seed */ |
| #include "filenames.h" |
| #include "output.h" |
| #include "target.h" |
| #include "common/common-target.h" |
| #include "langhooks.h" |
| #include "tree-inline.h" |
| #include "tree-iterator.h" |
| #include "predict.h" |
| #include "dominance.h" |
| #include "cfg.h" |
| #include "basic-block.h" |
| #include "bitmap.h" |
| #include "tree-ssa-alias.h" |
| #include "internal-fn.h" |
| #include "gimple-expr.h" |
| #include "is-a.h" |
| #include "gimple.h" |
| #include "gimple-iterator.h" |
| #include "gimplify.h" |
| #include "gimple-ssa.h" |
| #include "hash-map.h" |
| #include "plugin-api.h" |
| #include "ipa-ref.h" |
| #include "cgraph.h" |
| #include "tree-phinodes.h" |
| #include "stringpool.h" |
| #include "tree-ssanames.h" |
| #include "rtl.h" |
| #include "statistics.h" |
| #include "real.h" |
| #include "fixed-value.h" |
| #include "insn-config.h" |
| #include "expmed.h" |
| #include "dojump.h" |
| #include "explow.h" |
| #include "emit-rtl.h" |
| #include "stmt.h" |
| #include "expr.h" |
| #include "tree-dfa.h" |
| #include "params.h" |
| #include "tree-pass.h" |
| #include "langhooks-def.h" |
| #include "diagnostic.h" |
| #include "tree-diagnostic.h" |
| #include "tree-pretty-print.h" |
| #include "except.h" |
| #include "debug.h" |
| #include "intl.h" |
| #include "builtins.h" |
| |
| /* Tree code classes. */ |
| |
| #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE, |
| #define END_OF_BASE_TREE_CODES tcc_exceptional, |
| |
| const enum tree_code_class tree_code_type[] = { |
| #include "all-tree.def" |
| }; |
| |
| #undef DEFTREECODE |
| #undef END_OF_BASE_TREE_CODES |
| |
| /* Table indexed by tree code giving number of expression |
| operands beyond the fixed part of the node structure. |
| Not used for types or decls. */ |
| |
| #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH, |
| #define END_OF_BASE_TREE_CODES 0, |
| |
| const unsigned char tree_code_length[] = { |
| #include "all-tree.def" |
| }; |
| |
| #undef DEFTREECODE |
| #undef END_OF_BASE_TREE_CODES |
| |
| /* Names of tree components. |
| Used for printing out the tree and error messages. */ |
| #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME, |
| #define END_OF_BASE_TREE_CODES "@dummy", |
| |
| static const char *const tree_code_name[] = { |
| #include "all-tree.def" |
| }; |
| |
| #undef DEFTREECODE |
| #undef END_OF_BASE_TREE_CODES |
| |
| /* Each tree code class has an associated string representation. |
| These must correspond to the tree_code_class entries. */ |
| |
| const char *const tree_code_class_strings[] = |
| { |
| "exceptional", |
| "constant", |
| "type", |
| "declaration", |
| "reference", |
| "comparison", |
| "unary", |
| "binary", |
| "statement", |
| "vl_exp", |
| "expression" |
| }; |
| |
| /* obstack.[ch] explicitly declined to prototype this. */ |
| extern int _obstack_allocated_p (struct obstack *h, void *obj); |
| |
| /* Statistics-gathering stuff. */ |
| |
| static int tree_code_counts[MAX_TREE_CODES]; |
| int tree_node_counts[(int) all_kinds]; |
| int tree_node_sizes[(int) all_kinds]; |
| |
| /* Keep in sync with tree.h:enum tree_node_kind. */ |
| static const char * const tree_node_kind_names[] = { |
| "decls", |
| "types", |
| "blocks", |
| "stmts", |
| "refs", |
| "exprs", |
| "constants", |
| "identifiers", |
| "vecs", |
| "binfos", |
| "ssa names", |
| "constructors", |
| "random kinds", |
| "lang_decl kinds", |
| "lang_type kinds", |
| "omp clauses", |
| }; |
| |
| /* Unique id for next decl created. */ |
| static GTY(()) int next_decl_uid; |
| /* Unique id for next type created. */ |
| static GTY(()) int next_type_uid = 1; |
| /* Unique id for next debug decl created. Use negative numbers, |
| to catch erroneous uses. */ |
| static GTY(()) int next_debug_decl_uid; |
| |
| /* Since we cannot rehash a type after it is in the table, we have to |
| keep the hash code. */ |
| |
| struct GTY((for_user)) type_hash { |
| unsigned long hash; |
| tree type; |
| }; |
| |
| /* Initial size of the hash table (rounded to next prime). */ |
| #define TYPE_HASH_INITIAL_SIZE 1000 |
| |
| struct type_cache_hasher : ggc_cache_hasher<type_hash *> |
| { |
| static hashval_t hash (type_hash *t) { return t->hash; } |
| static bool equal (type_hash *a, type_hash *b); |
| |
| static void |
| handle_cache_entry (type_hash *&t) |
| { |
| extern void gt_ggc_mx (type_hash *&); |
| if (t == HTAB_DELETED_ENTRY || t == HTAB_EMPTY_ENTRY) |
| return; |
| else if (ggc_marked_p (t->type)) |
| gt_ggc_mx (t); |
| else |
| t = static_cast<type_hash *> (HTAB_DELETED_ENTRY); |
| } |
| }; |
| |
| /* Now here is the hash table. When recording a type, it is added to |
| the slot whose index is the hash code. Note that the hash table is |
| used for several kinds of types (function types, array types and |
| array index range types, for now). While all these live in the |
| same table, they are completely independent, and the hash code is |
| computed differently for each of these. */ |
| |
| static GTY ((cache)) hash_table<type_cache_hasher> *type_hash_table; |
| |
| /* Hash table and temporary node for larger integer const values. */ |
| static GTY (()) tree int_cst_node; |
| |
| struct int_cst_hasher : ggc_cache_hasher<tree> |
| { |
| static hashval_t hash (tree t); |
| static bool equal (tree x, tree y); |
| }; |
| |
| static GTY ((cache)) hash_table<int_cst_hasher> *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; |
| |
| struct cl_option_hasher : ggc_cache_hasher<tree> |
| { |
| static hashval_t hash (tree t); |
| static bool equal (tree x, tree y); |
| }; |
| |
| static GTY ((cache)) hash_table<cl_option_hasher> *cl_option_hash_table; |
| |
| /* General tree->tree mapping structure for use in hash tables. */ |
| |
| |
| static GTY ((cache)) |
| hash_table<tree_decl_map_cache_hasher> *debug_expr_for_decl; |
| |
| static GTY ((cache)) |
| hash_table<tree_decl_map_cache_hasher> *value_expr_for_decl; |
| |
| struct tree_vec_map_cache_hasher : ggc_cache_hasher<tree_vec_map *> |
| { |
| static hashval_t hash (tree_vec_map *m) { return DECL_UID (m->base.from); } |
| |
| static bool |
| equal (tree_vec_map *a, tree_vec_map *b) |
| { |
| return a->base.from == b->base.from; |
| } |
| |
| static void |
| handle_cache_entry (tree_vec_map *&m) |
| { |
| extern void gt_ggc_mx (tree_vec_map *&); |
| if (m == HTAB_EMPTY_ENTRY || m == HTAB_DELETED_ENTRY) |
| return; |
| else if (ggc_marked_p (m->base.from)) |
| gt_ggc_mx (m); |
| else |
| m = static_cast<tree_vec_map *> (HTAB_DELETED_ENTRY); |
| } |
| }; |
| |
| static GTY ((cache)) |
| hash_table<tree_vec_map_cache_hasher> *debug_args_for_decl; |
| |
| static void set_type_quals (tree, int); |
| static void print_type_hash_statistics (void); |
| static void print_debug_expr_statistics (void); |
| static void print_value_expr_statistics (void); |
| static void type_hash_list (const_tree, inchash::hash &); |
| static void attribute_hash_list (const_tree, inchash::hash &); |
| |
| tree global_trees[TI_MAX]; |
| tree integer_types[itk_none]; |
| |
| bool int_n_enabled_p[NUM_INT_N_ENTS]; |
| struct int_n_trees_t int_n_trees [NUM_INT_N_ENTS]; |
| |
| unsigned char tree_contains_struct[MAX_TREE_CODES][64]; |
| |
| /* Number of operands for each OpenMP clause. */ |
| unsigned const char omp_clause_num_ops[] = |
| { |
| 0, /* OMP_CLAUSE_ERROR */ |
| 1, /* OMP_CLAUSE_PRIVATE */ |
| 1, /* OMP_CLAUSE_SHARED */ |
| 1, /* OMP_CLAUSE_FIRSTPRIVATE */ |
| 2, /* OMP_CLAUSE_LASTPRIVATE */ |
| 4, /* OMP_CLAUSE_REDUCTION */ |
| 1, /* OMP_CLAUSE_COPYIN */ |
| 1, /* OMP_CLAUSE_COPYPRIVATE */ |
| 3, /* OMP_CLAUSE_LINEAR */ |
| 2, /* OMP_CLAUSE_ALIGNED */ |
| 1, /* OMP_CLAUSE_DEPEND */ |
| 1, /* OMP_CLAUSE_UNIFORM */ |
| 2, /* OMP_CLAUSE_FROM */ |
| 2, /* OMP_CLAUSE_TO */ |
| 2, /* OMP_CLAUSE_MAP */ |
| 2, /* OMP_CLAUSE__CACHE_ */ |
| 1, /* OMP_CLAUSE_DEVICE_RESIDENT */ |
| 1, /* OMP_CLAUSE_USE_DEVICE */ |
| 2, /* OMP_CLAUSE_GANG */ |
| 1, /* OMP_CLAUSE_ASYNC */ |
| 1, /* OMP_CLAUSE_WAIT */ |
| 0, /* OMP_CLAUSE_AUTO */ |
| 0, /* OMP_CLAUSE_SEQ */ |
| 1, /* OMP_CLAUSE__LOOPTEMP_ */ |
| 1, /* OMP_CLAUSE_IF */ |
| 1, /* OMP_CLAUSE_NUM_THREADS */ |
| 1, /* OMP_CLAUSE_SCHEDULE */ |
| 0, /* OMP_CLAUSE_NOWAIT */ |
| 0, /* OMP_CLAUSE_ORDERED */ |
| 0, /* OMP_CLAUSE_DEFAULT */ |
| 3, /* OMP_CLAUSE_COLLAPSE */ |
| 0, /* OMP_CLAUSE_UNTIED */ |
| 1, /* OMP_CLAUSE_FINAL */ |
| 0, /* OMP_CLAUSE_MERGEABLE */ |
| 1, /* OMP_CLAUSE_DEVICE */ |
| 1, /* OMP_CLAUSE_DIST_SCHEDULE */ |
| 0, /* OMP_CLAUSE_INBRANCH */ |
| 0, /* OMP_CLAUSE_NOTINBRANCH */ |
| 1, /* OMP_CLAUSE_NUM_TEAMS */ |
| 1, /* OMP_CLAUSE_THREAD_LIMIT */ |
| 0, /* OMP_CLAUSE_PROC_BIND */ |
| 1, /* OMP_CLAUSE_SAFELEN */ |
| 1, /* OMP_CLAUSE_SIMDLEN */ |
| 0, /* OMP_CLAUSE_FOR */ |
| 0, /* OMP_CLAUSE_PARALLEL */ |
| 0, /* OMP_CLAUSE_SECTIONS */ |
| 0, /* OMP_CLAUSE_TASKGROUP */ |
| 1, /* OMP_CLAUSE__SIMDUID_ */ |
| 1, /* OMP_CLAUSE__CILK_FOR_COUNT_ */ |
| 0, /* OMP_CLAUSE_INDEPENDENT */ |
| 1, /* OMP_CLAUSE_WORKER */ |
| 1, /* OMP_CLAUSE_VECTOR */ |
| 1, /* OMP_CLAUSE_NUM_GANGS */ |
| 1, /* OMP_CLAUSE_NUM_WORKERS */ |
| 1, /* OMP_CLAUSE_VECTOR_LENGTH */ |
| }; |
| |
| const char * const omp_clause_code_name[] = |
| { |
| "error_clause", |
| "private", |
| "shared", |
| "firstprivate", |
| "lastprivate", |
| "reduction", |
| "copyin", |
| "copyprivate", |
| "linear", |
| "aligned", |
| "depend", |
| "uniform", |
| "from", |
| "to", |
| "map", |
| "_cache_", |
| "device_resident", |
| "use_device", |
| "gang", |
| "async", |
| "wait", |
| "auto", |
| "seq", |
| "_looptemp_", |
| "if", |
| "num_threads", |
| "schedule", |
| "nowait", |
| "ordered", |
| "default", |
| "collapse", |
| "untied", |
| "final", |
| "mergeable", |
| "device", |
| "dist_schedule", |
| "inbranch", |
| "notinbranch", |
| "num_teams", |
| "thread_limit", |
| "proc_bind", |
| "safelen", |
| "simdlen", |
| "for", |
| "parallel", |
| "sections", |
| "taskgroup", |
| "_simduid_", |
| "_Cilk_for_count_", |
| "independent", |
| "worker", |
| "vector", |
| "num_gangs", |
| "num_workers", |
| "vector_length" |
| }; |
| |
| |
| /* Return the tree node structure used by tree code CODE. */ |
| |
| static inline enum tree_node_structure_enum |
| tree_node_structure_for_code (enum tree_code code) |
| { |
| switch (TREE_CODE_CLASS (code)) |
| { |
| case tcc_declaration: |
| { |
| switch (code) |
| { |
| case FIELD_DECL: |
| return TS_FIELD_DECL; |
| case PARM_DECL: |
| return TS_PARM_DECL; |
| case VAR_DECL: |
| return TS_VAR_DECL; |
| case LABEL_DECL: |
| return TS_LABEL_DECL; |
| case RESULT_DECL: |
| return TS_RESULT_DECL; |
| case DEBUG_EXPR_DECL: |
| return TS_DECL_WRTL; |
| case CONST_DECL: |
| return TS_CONST_DECL; |
| case TYPE_DECL: |
| return TS_TYPE_DECL; |
| case FUNCTION_DECL: |
| return TS_FUNCTION_DECL; |
| case TRANSLATION_UNIT_DECL: |
| return TS_TRANSLATION_UNIT_DECL; |
| default: |
| return TS_DECL_NON_COMMON; |
| } |
| } |
| case tcc_type: |
| return TS_TYPE_NON_COMMON; |
| case tcc_reference: |
| case tcc_comparison: |
| case tcc_unary: |
| case tcc_binary: |
| case tcc_expression: |
| case tcc_statement: |
| case tcc_vl_exp: |
| return TS_EXP; |
| default: /* tcc_constant and tcc_exceptional */ |
| break; |
| } |
| switch (code) |
| { |
| /* tcc_constant cases. */ |
| case VOID_CST: return TS_TYPED; |
| case INTEGER_CST: return TS_INT_CST; |
| case REAL_CST: return TS_REAL_CST; |
| case FIXED_CST: return TS_FIXED_CST; |
| case COMPLEX_CST: return TS_COMPLEX; |
| case VECTOR_CST: return TS_VECTOR; |
| case STRING_CST: return TS_STRING; |
| /* tcc_exceptional cases. */ |
| 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 SSA_NAME: return TS_SSA_NAME; |
| case PLACEHOLDER_EXPR: return TS_COMMON; |
| case STATEMENT_LIST: return TS_STATEMENT_LIST; |
| case BLOCK: return TS_BLOCK; |
| 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 (); |
| } |
| } |
| |
| |
| /* Initialize tree_contains_struct to describe the hierarchy of tree |
| nodes. */ |
| |
| static void |
| initialize_tree_contains_struct (void) |
| { |
| unsigned i; |
| |
| for (i = ERROR_MARK; i < LAST_AND_UNUSED_TREE_CODE; i++) |
| { |
| enum tree_code code; |
| enum tree_node_structure_enum ts_code; |
| |
| code = (enum tree_code) i; |
| ts_code = tree_node_structure_for_code (code); |
| |
| /* Mark the TS structure itself. */ |
| tree_contains_struct[code][ts_code] = 1; |
| |
| /* Mark all the structures that TS is derived from. */ |
| switch (ts_code) |
| { |
| case TS_TYPED: |
| case TS_BLOCK: |
| MARK_TS_BASE (code); |
| break; |
| |
| case TS_COMMON: |
| case TS_INT_CST: |
| case TS_REAL_CST: |
| case TS_FIXED_CST: |
| case TS_VECTOR: |
| case TS_STRING: |
| case TS_COMPLEX: |
| case TS_SSA_NAME: |
| case TS_CONSTRUCTOR: |
| case TS_EXP: |
| case TS_STATEMENT_LIST: |
| MARK_TS_TYPED (code); |
| break; |
| |
| case TS_IDENTIFIER: |
| case TS_DECL_MINIMAL: |
| case TS_TYPE_COMMON: |
| case TS_LIST: |
| case TS_VEC: |
| case TS_BINFO: |
| case TS_OMP_CLAUSE: |
| case TS_OPTIMIZATION: |
| case TS_TARGET_OPTION: |
| MARK_TS_COMMON (code); |
| break; |
| |
| case TS_TYPE_WITH_LANG_SPECIFIC: |
| MARK_TS_TYPE_COMMON (code); |
| break; |
| |
| case TS_TYPE_NON_COMMON: |
| MARK_TS_TYPE_WITH_LANG_SPECIFIC (code); |
| break; |
| |
| case TS_DECL_COMMON: |
| MARK_TS_DECL_MINIMAL (code); |
| break; |
| |
| case TS_DECL_WRTL: |
| case TS_CONST_DECL: |
| MARK_TS_DECL_COMMON (code); |
| break; |
| |
| case TS_DECL_NON_COMMON: |
| MARK_TS_DECL_WITH_VIS (code); |
| break; |
| |
| case TS_DECL_WITH_VIS: |
| case TS_PARM_DECL: |
| case TS_LABEL_DECL: |
| case TS_RESULT_DECL: |
| MARK_TS_DECL_WRTL (code); |
| break; |
| |
| case TS_FIELD_DECL: |
| MARK_TS_DECL_COMMON (code); |
| break; |
| |
| case TS_VAR_DECL: |
| MARK_TS_DECL_WITH_VIS (code); |
| break; |
| |
| case TS_TYPE_DECL: |
| case TS_FUNCTION_DECL: |
| MARK_TS_DECL_NON_COMMON (code); |
| break; |
| |
| case TS_TRANSLATION_UNIT_DECL: |
| MARK_TS_DECL_COMMON (code); |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Basic consistency checks for attributes used in fold. */ |
| gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON]); |
| gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON]); |
| gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_COMMON]); |
| gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_COMMON]); |
| gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_COMMON]); |
| gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_COMMON]); |
| gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_COMMON]); |
| gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_COMMON]); |
| gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_COMMON]); |
| gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_COMMON]); |
| gcc_assert (tree_contains_struct[FIELD_DECL][TS_DECL_COMMON]); |
| gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_WRTL]); |
| gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_WRTL]); |
| gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_WRTL]); |
| gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_WRTL]); |
| gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_WRTL]); |
| gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_MINIMAL]); |
| gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_MINIMAL]); |
| gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_MINIMAL]); |
| gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_MINIMAL]); |
| gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_MINIMAL]); |
| gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_MINIMAL]); |
| gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_MINIMAL]); |
| gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_MINIMAL]); |
| gcc_assert (tree_contains_struct[FIELD_DECL][TS_DECL_MINIMAL]); |
| gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS]); |
| gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS]); |
| gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_WITH_VIS]); |
| gcc_assert (tree_contains_struct[VAR_DECL][TS_VAR_DECL]); |
| gcc_assert (tree_contains_struct[FIELD_DECL][TS_FIELD_DECL]); |
| gcc_assert (tree_contains_struct[PARM_DECL][TS_PARM_DECL]); |
| gcc_assert (tree_contains_struct[LABEL_DECL][TS_LABEL_DECL]); |
| gcc_assert (tree_contains_struct[RESULT_DECL][TS_RESULT_DECL]); |
| gcc_assert (tree_contains_struct[CONST_DECL][TS_CONST_DECL]); |
| gcc_assert (tree_contains_struct[TYPE_DECL][TS_TYPE_DECL]); |
| gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL]); |
| gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL]); |
| gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON]); |
| gcc_assert (tree_contains_struct[NAMELIST_DECL][TS_DECL_MINIMAL]); |
| gcc_assert (tree_contains_struct[NAMELIST_DECL][TS_DECL_COMMON]); |
| } |
| |
| |
| /* Init tree.c. */ |
| |
| void |
| init_ttree (void) |
| { |
| /* Initialize the hash table of types. */ |
| type_hash_table |
| = hash_table<type_cache_hasher>::create_ggc (TYPE_HASH_INITIAL_SIZE); |
| |
| debug_expr_for_decl |
| = hash_table<tree_decl_map_cache_hasher>::create_ggc (512); |
| |
| value_expr_for_decl |
| = hash_table<tree_decl_map_cache_hasher>::create_ggc (512); |
| |
| int_cst_hash_table = hash_table<int_cst_hasher>::create_ggc (1024); |
| |
| int_cst_node = make_int_cst (1, 1); |
| |
| cl_option_hash_table = hash_table<cl_option_hasher>::create_ggc (64); |
| |
| cl_optimization_node = make_node (OPTIMIZATION_NODE); |
| cl_target_option_node = make_node (TARGET_OPTION_NODE); |
| |
| /* Initialize the tree_contains_struct array. */ |
| initialize_tree_contains_struct (); |
| lang_hooks.init_ts (); |
| } |
| |
| |
| /* The name of the object as the assembler will see it (but before any |
| translations made by ASM_OUTPUT_LABELREF). Often this is the same |
| as DECL_NAME. It is an IDENTIFIER_NODE. */ |
| tree |
| decl_assembler_name (tree decl) |
| { |
| if (!DECL_ASSEMBLER_NAME_SET_P (decl)) |
| lang_hooks.set_decl_assembler_name (decl); |
| return DECL_WITH_VIS_CHECK (decl)->decl_with_vis.assembler_name; |
| } |
| |
| /* When the target supports COMDAT groups, this indicates which group the |
| DECL is associated with. This can be either an IDENTIFIER_NODE or a |
| decl, in which case its DECL_ASSEMBLER_NAME identifies the group. */ |
| tree |
| decl_comdat_group (const_tree node) |
| { |
| struct symtab_node *snode = symtab_node::get (node); |
| if (!snode) |
| return NULL; |
| return snode->get_comdat_group (); |
| } |
| |
| /* Likewise, but make sure it's been reduced to an IDENTIFIER_NODE. */ |
| tree |
| decl_comdat_group_id (const_tree node) |
| { |
| struct symtab_node *snode = symtab_node::get (node); |
| if (!snode) |
| return NULL; |
| return snode->get_comdat_group_id (); |
| } |
| |
| /* When the target supports named section, return its name as IDENTIFIER_NODE |
| or NULL if it is in no section. */ |
| const char * |
| decl_section_name (const_tree node) |
| { |
| struct symtab_node *snode = symtab_node::get (node); |
| if (!snode) |
| return NULL; |
| return snode->get_section (); |
| } |
| |
| /* Set section section name of NODE to VALUE (that is expected to |
| be identifier node) */ |
| void |
| set_decl_section_name (tree node, const char *value) |
| { |
| struct symtab_node *snode; |
| |
| if (value == NULL) |
| { |
| snode = symtab_node::get (node); |
| if (!snode) |
| return; |
| } |
| else if (TREE_CODE (node) == VAR_DECL) |
| snode = varpool_node::get_create (node); |
| else |
| snode = cgraph_node::get_create (node); |
| snode->set_section (value); |
| } |
| |
| /* Return TLS model of a variable NODE. */ |
| enum tls_model |
| decl_tls_model (const_tree node) |
| { |
| struct varpool_node *snode = varpool_node::get (node); |
| if (!snode) |
| return TLS_MODEL_NONE; |
| return snode->tls_model; |
| } |
| |
| /* Set TLS model of variable NODE to MODEL. */ |
| void |
| set_decl_tls_model (tree node, enum tls_model model) |
| { |
| struct varpool_node *vnode; |
| |
| if (model == TLS_MODEL_NONE) |
| { |
| vnode = varpool_node::get (node); |
| if (!vnode) |
| return; |
| } |
| else |
| vnode = varpool_node::get_create (node); |
| vnode->tls_model = model; |
| } |
| |
| /* 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, INTEGER_CST, STRING_CST, and CALL_EXPR. */ |
| size_t |
| tree_code_size (enum tree_code code) |
| { |
| switch (TREE_CODE_CLASS (code)) |
| { |
| case tcc_declaration: /* A decl node */ |
| { |
| switch (code) |
| { |
| case FIELD_DECL: |
| return sizeof (struct tree_field_decl); |
| case PARM_DECL: |
| return sizeof (struct tree_parm_decl); |
| case VAR_DECL: |
| return sizeof (struct tree_var_decl); |
| case LABEL_DECL: |
| return sizeof (struct tree_label_decl); |
| case RESULT_DECL: |
| return sizeof (struct tree_result_decl); |
| case CONST_DECL: |
| return sizeof (struct tree_const_decl); |
| case TYPE_DECL: |
| return sizeof (struct tree_type_decl); |
| case FUNCTION_DECL: |
| return sizeof (struct tree_function_decl); |
| case DEBUG_EXPR_DECL: |
| return sizeof (struct tree_decl_with_rtl); |
| case TRANSLATION_UNIT_DECL: |
| return sizeof (struct tree_translation_unit_decl); |
| case NAMESPACE_DECL: |
| case IMPORTED_DECL: |
| case NAMELIST_DECL: |
| return sizeof (struct tree_decl_non_common); |
| default: |
| return lang_hooks.tree_size (code); |
| } |
| } |
| |
| case tcc_type: /* a type node */ |
| return sizeof (struct tree_type_non_common); |
| |
| case tcc_reference: /* a reference */ |
| case tcc_expression: /* an expression */ |
| case tcc_statement: /* an expression with side effects */ |
| case tcc_comparison: /* a comparison expression */ |
| case tcc_unary: /* a unary arithmetic expression */ |
| case tcc_binary: /* a binary arithmetic expression */ |
| return (sizeof (struct tree_exp) |
| + (TREE_CODE_LENGTH (code) - 1) * sizeof (tree)); |
| |
| case tcc_constant: /* a constant */ |
| switch (code) |
| { |
| case VOID_CST: return sizeof (struct tree_typed); |
| case INTEGER_CST: gcc_unreachable (); |
| case REAL_CST: return sizeof (struct tree_real_cst); |
| case FIXED_CST: return sizeof (struct tree_fixed_cst); |
| case COMPLEX_CST: return sizeof (struct tree_complex); |
| case VECTOR_CST: return sizeof (struct tree_vector); |
| case STRING_CST: gcc_unreachable (); |
| default: |
| return lang_hooks.tree_size (code); |
| } |
| |
| case tcc_exceptional: /* something random, like an identifier. */ |
| switch (code) |
| { |
| case IDENTIFIER_NODE: return lang_hooks.identifier_size; |
| case TREE_LIST: return sizeof (struct tree_list); |
| |
| case ERROR_MARK: |
| case PLACEHOLDER_EXPR: return sizeof (struct tree_common); |
| |
| case TREE_VEC: |
| 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); |
| } |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Compute the number of bytes occupied by NODE. This routine only |
| looks at TREE_CODE, except for those nodes that have variable sizes. */ |
| size_t |
| tree_size (const_tree node) |
| { |
| const enum tree_code code = TREE_CODE (node); |
| switch (code) |
| { |
| case INTEGER_CST: |
| return (sizeof (struct tree_int_cst) |
| + (TREE_INT_CST_EXT_NUNITS (node) - 1) * sizeof (HOST_WIDE_INT)); |
| |
| case TREE_BINFO: |
| return (offsetof (struct tree_binfo, base_binfos) |
| + vec<tree, va_gc> |
| ::embedded_size (BINFO_N_BASE_BINFOS (node))); |
| |
| case TREE_VEC: |
| return (sizeof (struct tree_vec) |
| + (TREE_VEC_LENGTH (node) - 1) * sizeof (tree)); |
| |
| case VECTOR_CST: |
| return (sizeof (struct tree_vector) |
| + (TYPE_VECTOR_SUBPARTS (TREE_TYPE (node)) - 1) * sizeof (tree)); |
| |
| case STRING_CST: |
| return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1; |
| |
| case OMP_CLAUSE: |
| return (sizeof (struct tree_omp_clause) |
| + (omp_clause_num_ops[OMP_CLAUSE_CODE (node)] - 1) |
| * sizeof (tree)); |
| |
| default: |
| if (TREE_CODE_CLASS (code) == tcc_vl_exp) |
| return (sizeof (struct tree_exp) |
| + (VL_EXP_OPERAND_LENGTH (node) - 1) * sizeof (tree)); |
| else |
| return tree_code_size (code); |
| } |
| } |
| |
| /* Record interesting allocation statistics for a tree node with CODE |
| and LENGTH. */ |
| |
| static void |
| record_node_allocation_statistics (enum tree_code code ATTRIBUTE_UNUSED, |
| size_t length ATTRIBUTE_UNUSED) |
| { |
| enum tree_code_class type = TREE_CODE_CLASS (code); |
| tree_node_kind kind; |
| |
| if (!GATHER_STATISTICS) |
| return; |
| |
| switch (type) |
| { |
| case tcc_declaration: /* A decl node */ |
| kind = d_kind; |
| break; |
| |
| case tcc_type: /* a type node */ |
| kind = t_kind; |
| break; |
| |
| case tcc_statement: /* an expression with side effects */ |
| kind = s_kind; |
| break; |
| |
| case tcc_reference: /* a reference */ |
| kind = r_kind; |
| break; |
| |
| case tcc_expression: /* an expression */ |
| case tcc_comparison: /* a comparison expression */ |
| case tcc_unary: /* a unary arithmetic expression */ |
| case tcc_binary: /* a binary arithmetic expression */ |
| kind = e_kind; |
| break; |
| |
| case tcc_constant: /* a constant */ |
| kind = c_kind; |
| break; |
| |
| case tcc_exceptional: /* something random, like an identifier. */ |
| switch (code) |
| { |
| case IDENTIFIER_NODE: |
| kind = id_kind; |
| break; |
| |
| case TREE_VEC: |
| kind = vec_kind; |
| break; |
| |
| case TREE_BINFO: |
| kind = binfo_kind; |
| break; |
| |
| case SSA_NAME: |
| kind = ssa_name_kind; |
| break; |
| |
| case BLOCK: |
| kind = b_kind; |
| break; |
| |
| case CONSTRUCTOR: |
| kind = constr_kind; |
| break; |
| |
| case OMP_CLAUSE: |
| kind = omp_clause_kind; |
| break; |
| |
| default: |
| kind = x_kind; |
| break; |
| } |
| break; |
| |
| case tcc_vl_exp: |
| kind = e_kind; |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| tree_code_counts[(int) code]++; |
| tree_node_counts[(int) kind]++; |
| tree_node_sizes[(int) kind] += length; |
| } |
| |
| /* Allocate and return a new UID from the DECL_UID namespace. */ |
| |
| int |
| allocate_decl_uid (void) |
| { |
| return next_decl_uid++; |
| } |
| |
| /* 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 TREE_VEC, |
| INTEGER_CST or OMP_CLAUSE nodes, which is enforced by asserts in |
| tree_code_size. |
| |
| Achoo! I got a code in the node. */ |
| |
| tree |
| make_node_stat (enum tree_code code MEM_STAT_DECL) |
| { |
| tree t; |
| enum tree_code_class type = TREE_CODE_CLASS (code); |
| size_t length = tree_code_size (code); |
| |
| record_node_allocation_statistics (code, length); |
| |
| t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT); |
| TREE_SET_CODE (t, code); |
| |
| switch (type) |
| { |
| case tcc_statement: |
| TREE_SIDE_EFFECTS (t) = 1; |
| break; |
| |
| case tcc_declaration: |
| if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) |
| { |
| if (code == FUNCTION_DECL) |
| { |
| DECL_ALIGN (t) = FUNCTION_BOUNDARY; |
| DECL_MODE (t) = FUNCTION_MODE; |
| } |
| else |
| DECL_ALIGN (t) = 1; |
| } |
| DECL_SOURCE_LOCATION (t) = input_location; |
| if (TREE_CODE (t) == DEBUG_EXPR_DECL) |
| DECL_UID (t) = --next_debug_decl_uid; |
| else |
| { |
| DECL_UID (t) = allocate_decl_uid (); |
| SET_DECL_PT_UID (t, -1); |
| } |
| if (TREE_CODE (t) == LABEL_DECL) |
| LABEL_DECL_UID (t) = -1; |
| |
| break; |
| |
| case tcc_type: |
| TYPE_UID (t) = next_type_uid++; |
| TYPE_ALIGN (t) = BITS_PER_UNIT; |
| TYPE_USER_ALIGN (t) = 0; |
| TYPE_MAIN_VARIANT (t) = t; |
| TYPE_CANONICAL (t) = t; |
| |
| /* Default to no attributes for type, but let target change that. */ |
| TYPE_ATTRIBUTES (t) = NULL_TREE; |
| targetm.set_default_type_attributes (t); |
| |
| /* We have not yet computed the alias set for this type. */ |
| TYPE_ALIAS_SET (t) = -1; |
| break; |
| |
| case tcc_constant: |
| TREE_CONSTANT (t) = 1; |
| break; |
| |
| case tcc_expression: |
| switch (code) |
| { |
| case INIT_EXPR: |
| case MODIFY_EXPR: |
| case VA_ARG_EXPR: |
| case PREDECREMENT_EXPR: |
| case PREINCREMENT_EXPR: |
| case POSTDECREMENT_EXPR: |
| case POSTINCREMENT_EXPR: |
| /* All of these have side-effects, no matter what their |
| operands are. */ |
| TREE_SIDE_EFFECTS (t) = 1; |
| break; |
| |
| default: |
| break; |
| } |
| break; |
| |
| default: |
| /* Other classes need no special treatment. */ |
| break; |
| } |
| |
| return t; |
| } |
| |
| /* Return a new node with the same contents as NODE except that its |
| TREE_CHAIN, if it has one, is zero and it has a fresh uid. */ |
| |
| tree |
| copy_node_stat (tree node MEM_STAT_DECL) |
| { |
| tree t; |
| enum tree_code code = TREE_CODE (node); |
| size_t length; |
| |
| gcc_assert (code != STATEMENT_LIST); |
| |
| length = tree_size (node); |
| record_node_allocation_statistics (code, length); |
| t = ggc_alloc_tree_node_stat (length PASS_MEM_STAT); |
| memcpy (t, node, length); |
| |
| if (CODE_CONTAINS_STRUCT (code, TS_COMMON)) |
| TREE_CHAIN (t) = 0; |
| TREE_ASM_WRITTEN (t) = 0; |
| TREE_VISITED (t) = 0; |
| |
| if (TREE_CODE_CLASS (code) == tcc_declaration) |
| { |
| if (code == DEBUG_EXPR_DECL) |
| DECL_UID (t) = --next_debug_decl_uid; |
| else |
| { |
| DECL_UID (t) = allocate_decl_uid (); |
| if (DECL_PT_UID_SET_P (node)) |
| SET_DECL_PT_UID (t, DECL_PT_UID (node)); |
| } |
| if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL) |
| && DECL_HAS_VALUE_EXPR_P (node)) |
| { |
| SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (node)); |
| DECL_HAS_VALUE_EXPR_P (t) = 1; |
| } |
| /* DECL_DEBUG_EXPR is copied explicitely by callers. */ |
| if (TREE_CODE (node) == VAR_DECL) |
| { |
| DECL_HAS_DEBUG_EXPR_P (t) = 0; |
| t->decl_with_vis.symtab_node = NULL; |
| } |
| if (TREE_CODE (node) == VAR_DECL && DECL_HAS_INIT_PRIORITY_P (node)) |
| { |
| SET_DECL_INIT_PRIORITY (t, DECL_INIT_PRIORITY (node)); |
| DECL_HAS_INIT_PRIORITY_P (t) = 1; |
| } |
| if (TREE_CODE (node) == FUNCTION_DECL) |
| { |
| DECL_STRUCT_FUNCTION (t) = NULL; |
| t->decl_with_vis.symtab_node = NULL; |
| } |
| } |
| else if (TREE_CODE_CLASS (code) == tcc_type) |
| { |
| TYPE_UID (t) = next_type_uid++; |
| /* The following is so that the debug code for |
| the copy is different from the original type. |
| The two statements usually duplicate each other |
| (because they clear fields of the same union), |
| but the optimizer should catch that. */ |
| TYPE_SYMTAB_POINTER (t) = 0; |
| TYPE_SYMTAB_ADDRESS (t) = 0; |
| |
| /* Do not copy the values cache. */ |
| if (TYPE_CACHED_VALUES_P (t)) |
| { |
| TYPE_CACHED_VALUES_P (t) = 0; |
| TYPE_CACHED_VALUES (t) = NULL_TREE; |
| } |
| } |
| |
| return t; |
| } |
| |
| /* Return a copy of a chain of nodes, chained through the TREE_CHAIN field. |
| For example, this can copy a list made of TREE_LIST nodes. */ |
| |
| tree |
| copy_list (tree list) |
| { |
| tree head; |
| tree prev, next; |
| |
| if (list == 0) |
| return 0; |
| |
| head = prev = copy_node (list); |
| next = TREE_CHAIN (list); |
| while (next) |
| { |
| TREE_CHAIN (prev) = copy_node (next); |
| prev = TREE_CHAIN (prev); |
| next = TREE_CHAIN (next); |
| } |
| return head; |
| } |
| |
| |
| /* Return the value that TREE_INT_CST_EXT_NUNITS should have for an |
| INTEGER_CST with value CST and type TYPE. */ |
| |
| static unsigned int |
| get_int_cst_ext_nunits (tree type, const wide_int &cst) |
| { |
| gcc_checking_assert (cst.get_precision () == TYPE_PRECISION (type)); |
| /* We need extra HWIs if CST is an unsigned integer with its |
| upper bit set. */ |
| if (TYPE_UNSIGNED (type) && wi::neg_p (cst)) |
| return cst.get_precision () / HOST_BITS_PER_WIDE_INT + 1; |
| return cst.get_len (); |
| } |
| |
| /* Return a new INTEGER_CST with value CST and type TYPE. */ |
| |
| static tree |
| build_new_int_cst (tree type, const wide_int &cst) |
| { |
| unsigned int len = cst.get_len (); |
| unsigned int ext_len = get_int_cst_ext_nunits (type, cst); |
| tree nt = make_int_cst (len, ext_len); |
| |
| if (len < ext_len) |
| { |
| --ext_len; |
| TREE_INT_CST_ELT (nt, ext_len) |
| = zext_hwi (-1, cst.get_precision () % HOST_BITS_PER_WIDE_INT); |
| for (unsigned int i = len; i < ext_len; ++i) |
| TREE_INT_CST_ELT (nt, i) = -1; |
| } |
| else if (TYPE_UNSIGNED (type) |
| && cst.get_precision () < len * HOST_BITS_PER_WIDE_INT) |
| { |
| len--; |
| TREE_INT_CST_ELT (nt, len) |
| = zext_hwi (cst.elt (len), |
| cst.get_precision () % HOST_BITS_PER_WIDE_INT); |
| } |
| |
| for (unsigned int i = 0; i < len; i++) |
| TREE_INT_CST_ELT (nt, i) = cst.elt (i); |
| TREE_TYPE (nt) = type; |
| return nt; |
| } |
| |
| /* Create an INT_CST node with a LOW value sign extended to TYPE. */ |
| |
| tree |
| build_int_cst (tree type, HOST_WIDE_INT low) |
| { |
| /* Support legacy code. */ |
| if (!type) |
| type = integer_type_node; |
| |
| return wide_int_to_tree (type, wi::shwi (low, TYPE_PRECISION (type))); |
| } |
| |
| tree |
| build_int_cstu (tree type, unsigned HOST_WIDE_INT cst) |
| { |
| return wide_int_to_tree (type, wi::uhwi (cst, TYPE_PRECISION (type))); |
| } |
| |
| /* Create an INT_CST node with a LOW value sign extended to TYPE. */ |
| |
| tree |
| build_int_cst_type (tree type, HOST_WIDE_INT low) |
| { |
| gcc_assert (type); |
| return wide_int_to_tree (type, wi::shwi (low, TYPE_PRECISION (type))); |
| } |
| |
| /* Constructs tree in type TYPE from with value given by CST. Signedness |
| of CST is assumed to be the same as the signedness of TYPE. */ |
| |
| tree |
| double_int_to_tree (tree type, double_int cst) |
| { |
| return wide_int_to_tree (type, widest_int::from (cst, TYPE_SIGN (type))); |
| } |
| |
| /* We force the wide_int CST to the range of the type TYPE by sign or |
| zero extending it. OVERFLOWABLE indicates if we are interested in |
| overflow of the value, when >0 we are only interested in signed |
| overflow, for <0 we are interested in any overflow. OVERFLOWED |
| indicates whether overflow has already occurred. CONST_OVERFLOWED |
| indicates whether constant overflow has already occurred. We force |
| T's value to be within range of T's type (by setting to 0 or 1 all |
| the bits outside the type's range). We set TREE_OVERFLOWED if, |
| OVERFLOWED is nonzero, |
| or OVERFLOWABLE is >0 and signed overflow occurs |
| or OVERFLOWABLE is <0 and any overflow occurs |
| We return a new tree node for the extended wide_int. The node |
| is shared if no overflow flags are set. */ |
| |
| |
| tree |
| force_fit_type (tree type, const wide_int_ref &cst, |
| int overflowable, bool overflowed) |
| { |
| signop sign = TYPE_SIGN (type); |
| |
| /* If we need to set overflow flags, return a new unshared node. */ |
| if (overflowed || !wi::fits_to_tree_p (cst, type)) |
| { |
| if (overflowed |
| || overflowable < 0 |
| || (overflowable > 0 && sign == SIGNED)) |
| { |
| wide_int tmp = wide_int::from (cst, TYPE_PRECISION (type), sign); |
| tree t = build_new_int_cst (type, tmp); |
| TREE_OVERFLOW (t) = 1; |
| return t; |
| } |
| } |
| |
| /* Else build a shared node. */ |
| return wide_int_to_tree (type, cst); |
| } |
| |
| /* These are the hash table functions for the hash table of INTEGER_CST |
| nodes of a sizetype. */ |
| |
| /* Return the hash code code X, an INTEGER_CST. */ |
| |
| hashval_t |
| int_cst_hasher::hash (tree x) |
| { |
| const_tree const t = x; |
| hashval_t code = TYPE_UID (TREE_TYPE (t)); |
| int i; |
| |
| for (i = 0; i < TREE_INT_CST_NUNITS (t); i++) |
| code = iterative_hash_host_wide_int (TREE_INT_CST_ELT(t, i), code); |
| |
| return code; |
| } |
| |
| /* Return nonzero if the value represented by *X (an INTEGER_CST tree node) |
| is the same as that given by *Y, which is the same. */ |
| |
| bool |
| int_cst_hasher::equal (tree x, tree y) |
| { |
| const_tree const xt = x; |
| const_tree const yt = y; |
| |
| if (TREE_TYPE (xt) != TREE_TYPE (yt) |
| || TREE_INT_CST_NUNITS (xt) != TREE_INT_CST_NUNITS (yt) |
| || TREE_INT_CST_EXT_NUNITS (xt) != TREE_INT_CST_EXT_NUNITS (yt)) |
| return false; |
| |
| for (int i = 0; i < TREE_INT_CST_NUNITS (xt); i++) |
| if (TREE_INT_CST_ELT (xt, i) != TREE_INT_CST_ELT (yt, i)) |
| return false; |
| |
| return true; |
| } |
| |
| /* Create an INT_CST node of TYPE and value CST. |
| The returned node is always shared. For small integers we use a |
| per-type vector cache, for larger ones we use a single hash table. |
| The value is extended from its precision according to the sign of |
| the type to be a multiple of HOST_BITS_PER_WIDE_INT. This defines |
| the upper bits and ensures that hashing and value equality based |
| upon the underlying HOST_WIDE_INTs works without masking. */ |
| |
| tree |
| wide_int_to_tree (tree type, const wide_int_ref &pcst) |
| { |
| tree t; |
| int ix = -1; |
| int limit = 0; |
| |
| gcc_assert (type); |
| unsigned int prec = TYPE_PRECISION (type); |
| signop sgn = TYPE_SIGN (type); |
| |
| /* Verify that everything is canonical. */ |
| int l = pcst.get_len (); |
| if (l > 1) |
| { |
| if (pcst.elt (l - 1) == 0) |
| gcc_checking_assert (pcst.elt (l - 2) < 0); |
| if (pcst.elt (l - 1) == (HOST_WIDE_INT) -1) |
| gcc_checking_assert (pcst.elt (l - 2) >= 0); |
| } |
| |
| wide_int cst = wide_int::from (pcst, prec, sgn); |
| unsigned int ext_len = get_int_cst_ext_nunits (type, cst); |
| |
| if (ext_len == 1) |
| { |
| /* We just need to store a single HOST_WIDE_INT. */ |
| HOST_WIDE_INT hwi; |
| if (TYPE_UNSIGNED (type)) |
| hwi = cst.to_uhwi (); |
| else |
| hwi = cst.to_shwi (); |
| |
| switch (TREE_CODE (type)) |
| { |
| case NULLPTR_TYPE: |
| gcc_assert (hwi == 0); |
| /* Fallthru. */ |
| |
| case POINTER_TYPE: |
| case REFERENCE_TYPE: |
| case POINTER_BOUNDS_TYPE: |
| /* Cache NULL pointer and zero bounds. */ |
| if (hwi == 0) |
| { |
| limit = 1; |
| ix = 0; |
| } |
| break; |
| |
| case BOOLEAN_TYPE: |
| /* Cache false or true. */ |
| limit = 2; |
| if (hwi < 2) |
| ix = hwi; |
| break; |
| |
| case INTEGER_TYPE: |
| case OFFSET_TYPE: |
| if (TYPE_SIGN (type) == UNSIGNED) |
| { |
| /* Cache [0, N). */ |
| limit = INTEGER_SHARE_LIMIT; |
| if (IN_RANGE (hwi, 0, INTEGER_SHARE_LIMIT - 1)) |
| ix = hwi; |
| } |
| else |
| { |
| /* Cache [-1, N). */ |
| limit = INTEGER_SHARE_LIMIT + 1; |
| if (IN_RANGE (hwi, -1, INTEGER_SHARE_LIMIT - 1)) |
| ix = hwi + 1; |
| } |
| break; |
| |
| case ENUMERAL_TYPE: |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| if (ix >= 0) |
| { |
| /* Look for it in the type's vector of small shared ints. */ |
| if (!TYPE_CACHED_VALUES_P (type)) |
| { |
| TYPE_CACHED_VALUES_P (type) = 1; |
| TYPE_CACHED_VALUES (type) = make_tree_vec (limit); |
| } |
| |
| t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix); |
| if (t) |
| /* Make sure no one is clobbering the shared constant. */ |
| gcc_checking_assert (TREE_TYPE (t) == type |
| && TREE_INT_CST_NUNITS (t) == 1 |
| && TREE_INT_CST_OFFSET_NUNITS (t) == 1 |
| && TREE_INT_CST_EXT_NUNITS (t) == 1 |
| && TREE_INT_CST_ELT (t, 0) == hwi); |
| else |
| { |
| /* Create a new shared int. */ |
| t = build_new_int_cst (type, cst); |
| TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t; |
| } |
| } |
| else |
| { |
| /* Use the cache of larger shared ints, using int_cst_node as |
| a temporary. */ |
| |
| TREE_INT_CST_ELT (int_cst_node, 0) = hwi; |
| TREE_TYPE (int_cst_node) = type; |
| |
| tree *slot = int_cst_hash_table->find_slot (int_cst_node, INSERT); |
| t = *slot; |
| if (!t) |
| { |
| /* Insert this one into the hash table. */ |
| t = int_cst_node; |
| *slot = t; |
| /* Make a new node for next time round. */ |
| int_cst_node = make_int_cst (1, 1); |
| } |
| } |
| } |
| else |
| { |
| /* The value either hashes properly or we drop it on the floor |
| for the gc to take care of. There will not be enough of them |
| to worry about. */ |
| |
| tree nt = build_new_int_cst (type, cst); |
| tree *slot = int_cst_hash_table->find_slot (nt, INSERT); |
| t = *slot; |
| if (!t) |
| { |
| /* Insert this one into the hash table. */ |
| t = nt; |
| *slot = t; |
| } |
| } |
| |
| return t; |
| } |
| |
| void |
| cache_integer_cst (tree t) |
| { |
| tree type = TREE_TYPE (t); |
| int ix = -1; |
| int limit = 0; |
| int prec = TYPE_PRECISION (type); |
| |
| gcc_assert (!TREE_OVERFLOW (t)); |
| |
| switch (TREE_CODE (type)) |
| { |
| case NULLPTR_TYPE: |
| gcc_assert (integer_zerop (t)); |
| /* Fallthru. */ |
| |
| case POINTER_TYPE: |
| case REFERENCE_TYPE: |
| /* Cache NULL pointer. */ |
| if (integer_zerop (t)) |
| { |
| limit = 1; |
| ix = 0; |
| } |
| break; |
| |
| case BOOLEAN_TYPE: |
| /* Cache false or true. */ |
| limit = 2; |
| if (wi::ltu_p (t, 2)) |
| ix = TREE_INT_CST_ELT (t, 0); |
| break; |
| |
| case INTEGER_TYPE: |
| case OFFSET_TYPE: |
| if (TYPE_UNSIGNED (type)) |
| { |
| /* Cache 0..N */ |
| limit = INTEGER_SHARE_LIMIT; |
| |
| /* This is a little hokie, but if the prec is smaller than |
| what is necessary to hold INTEGER_SHARE_LIMIT, then the |
| obvious test will not get the correct answer. */ |
| if (prec < HOST_BITS_PER_WIDE_INT) |
| { |
| if (tree_to_uhwi (t) < (unsigned HOST_WIDE_INT) INTEGER_SHARE_LIMIT) |
| ix = tree_to_uhwi (t); |
| } |
| else if (wi::ltu_p (t, INTEGER_SHARE_LIMIT)) |
| ix = tree_to_uhwi (t); |
| } |
| else |
| { |
| /* Cache -1..N */ |
| limit = INTEGER_SHARE_LIMIT + 1; |
| |
| if (integer_minus_onep (t)) |
| ix = 0; |
| else if (!wi::neg_p (t)) |
| { |
| if (prec < HOST_BITS_PER_WIDE_INT) |
| { |
| if (tree_to_shwi (t) < INTEGER_SHARE_LIMIT) |
| ix = tree_to_shwi (t) + 1; |
| } |
| else if (wi::ltu_p (t, INTEGER_SHARE_LIMIT)) |
| ix = tree_to_shwi (t) + 1; |
| } |
| } |
| break; |
| |
| case ENUMERAL_TYPE: |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| if (ix >= 0) |
| { |
| /* Look for it in the type's vector of small shared ints. */ |
| if (!TYPE_CACHED_VALUES_P (type)) |
| { |
| TYPE_CACHED_VALUES_P (type) = 1; |
| TYPE_CACHED_VALUES (type) = make_tree_vec (limit); |
| } |
| |
| gcc_assert (TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) == NULL_TREE); |
| TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t; |
| } |
| else |
| { |
| /* Use the cache of larger shared ints. */ |
| tree *slot = int_cst_hash_table->find_slot (t, INSERT); |
| /* If there is already an entry for the number verify it's the |
| same. */ |
| if (*slot) |
| gcc_assert (wi::eq_p (tree (*slot), t)); |
| else |
| /* Otherwise insert this one into the hash table. */ |
| *slot = t; |
| } |
| } |
| |
| |
| /* Builds an integer constant in TYPE such that lowest BITS bits are ones |
| and the rest are zeros. */ |
| |
| tree |
| build_low_bits_mask (tree type, unsigned bits) |
| { |
| gcc_assert (bits <= TYPE_PRECISION (type)); |
| |
| return wide_int_to_tree (type, wi::mask (bits, false, |
| TYPE_PRECISION (type))); |
| } |
| |
| /* Checks that X is integer constant that can be expressed in (unsigned) |
| HOST_WIDE_INT without loss of precision. */ |
| |
| bool |
| cst_and_fits_in_hwi (const_tree x) |
| { |
| if (TREE_CODE (x) != INTEGER_CST) |
| return false; |
| |
| if (TYPE_PRECISION (TREE_TYPE (x)) > HOST_BITS_PER_WIDE_INT) |
| return false; |
| |
| return TREE_INT_CST_NUNITS (x) == 1; |
| } |
| |
| /* Build a newly constructed TREE_VEC node of length LEN. */ |
| |
| tree |
| make_vector_stat (unsigned len MEM_STAT_DECL) |
| { |
| tree t; |
| unsigned length = (len - 1) * sizeof (tree) + sizeof (struct tree_vector); |
| |
| record_node_allocation_statistics (VECTOR_CST, length); |
| |
| t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT); |
| |
| TREE_SET_CODE (t, VECTOR_CST); |
| TREE_CONSTANT (t) = 1; |
| |
| return t; |
| } |
| |
| /* Return a new VECTOR_CST node whose type is TYPE and whose values |
| are in a list pointed to by VALS. */ |
| |
| tree |
| build_vector_stat (tree type, tree *vals MEM_STAT_DECL) |
| { |
| int over = 0; |
| unsigned cnt = 0; |
| tree v = make_vector (TYPE_VECTOR_SUBPARTS (type)); |
| TREE_TYPE (v) = type; |
| |
| /* Iterate through elements and check for overflow. */ |
| for (cnt = 0; cnt < TYPE_VECTOR_SUBPARTS (type); ++cnt) |
| { |
| tree value = vals[cnt]; |
| |
| VECTOR_CST_ELT (v, cnt) = value; |
| |
| /* Don't crash if we get an address constant. */ |
| if (!CONSTANT_CLASS_P (value)) |
| continue; |
| |
| over |= TREE_OVERFLOW (value); |
| } |
| |
| TREE_OVERFLOW (v) = over; |
| return v; |
| } |
| |
| /* Return a new VECTOR_CST node whose type is TYPE and whose values |
| are extracted from V, a vector of CONSTRUCTOR_ELT. */ |
| |
| tree |
| build_vector_from_ctor (tree type, vec<constructor_elt, va_gc> *v) |
| { |
| tree *vec = XALLOCAVEC (tree, TYPE_VECTOR_SUBPARTS (type)); |
| unsigned HOST_WIDE_INT idx; |
| tree value; |
| |
| FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value) |
| vec[idx] = value; |
| for (; idx < TYPE_VECTOR_SUBPARTS (type); ++idx) |
| vec[idx] = build_zero_cst (TREE_TYPE (type)); |
| |
| return build_vector (type, vec); |
| } |
| |
| /* Build a vector of type VECTYPE where all the elements are SCs. */ |
| tree |
| build_vector_from_val (tree vectype, tree sc) |
| { |
| int i, nunits = TYPE_VECTOR_SUBPARTS (vectype); |
| |
| if (sc == error_mark_node) |
| return sc; |
| |
| /* Verify that the vector type is suitable for SC. Note that there |
| is some inconsistency in the type-system with respect to restrict |
| qualifications of pointers. Vector types always have a main-variant |
| element type and the qualification is applied to the vector-type. |
| So TREE_TYPE (vector-type) does not return a properly qualified |
| vector element-type. */ |
| gcc_checking_assert (types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (sc)), |
| TREE_TYPE (vectype))); |
| |
| if (CONSTANT_CLASS_P (sc)) |
| { |
| tree *v = XALLOCAVEC (tree, nunits); |
| for (i = 0; i < nunits; ++i) |
| v[i] = sc; |
| return build_vector (vectype, v); |
| } |
| else |
| { |
| vec<constructor_elt, va_gc> *v; |
| vec_alloc (v, nunits); |
| for (i = 0; i < nunits; ++i) |
| CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, sc); |
| return build_constructor (vectype, v); |
| } |
| } |
| |
| /* Return a new CONSTRUCTOR node whose type is TYPE and whose values |
| are in the vec pointed to by VALS. */ |
| tree |
| build_constructor (tree type, vec<constructor_elt, va_gc> *vals) |
| { |
| tree c = make_node (CONSTRUCTOR); |
| unsigned int i; |
| constructor_elt *elt; |
| bool constant_p = true; |
| bool side_effects_p = false; |
| |
| TREE_TYPE (c) = type; |
| CONSTRUCTOR_ELTS (c) = vals; |
| |
| FOR_EACH_VEC_SAFE_ELT (vals, i, elt) |
| { |
| /* Mostly ctors will have elts that don't have side-effects, so |
| the usual case is to scan all the elements. Hence a single |
| loop for both const and side effects, rather than one loop |
| each (with early outs). */ |
| if (!TREE_CONSTANT (elt->value)) |
| constant_p = false; |
| if (TREE_SIDE_EFFECTS (elt->value)) |
| side_effects_p = true; |
| } |
| |
| TREE_SIDE_EFFECTS (c) = side_effects_p; |
| TREE_CONSTANT (c) = constant_p; |
| |
| return c; |
| } |
| |
| /* Build a CONSTRUCTOR node made of a single initializer, with the specified |
| INDEX and VALUE. */ |
| tree |
| build_constructor_single (tree type, tree index, tree value) |
| { |
| vec<constructor_elt, va_gc> *v; |
| constructor_elt elt = {index, value}; |
| |
| vec_alloc (v, 1); |
| v->quick_push (elt); |
| |
| return build_constructor (type, v); |
| } |
| |
| |
| /* Return a new CONSTRUCTOR node whose type is TYPE and whose values |
| are in a list pointed to by VALS. */ |
| tree |
| build_constructor_from_list (tree type, tree vals) |
| { |
| tree t; |
| vec<constructor_elt, va_gc> *v = NULL; |
| |
| if (vals) |
| { |
| vec_alloc (v, list_length (vals)); |
| for (t = vals; t; t = TREE_CHAIN (t)) |
| CONSTRUCTOR_APPEND_ELT (v, TREE_PURPOSE (t), TREE_VALUE (t)); |
| } |
| |
| return build_constructor (type, v); |
| } |
| |
| /* Return a new CONSTRUCTOR node whose type is TYPE. NELTS is the number |
| of elements, provided as index/value pairs. */ |
| |
| tree |
| build_constructor_va (tree type, int nelts, ...) |
| { |
| vec<constructor_elt, va_gc> *v = NULL; |
| va_list p; |
| |
| va_start (p, nelts); |
| vec_alloc (v, nelts); |
| while (nelts--) |
| { |
| tree index = va_arg (p, tree); |
| tree value = va_arg (p, tree); |
| CONSTRUCTOR_APPEND_ELT (v, index, value); |
| } |
| va_end (p); |
| return build_constructor (type, v); |
| } |
| |
| /* Return a new FIXED_CST node whose type is TYPE and value is F. */ |
| |
| tree |
| build_fixed (tree type, FIXED_VALUE_TYPE f) |
| { |
| tree v; |
| FIXED_VALUE_TYPE *fp; |
| |
| v = make_node (FIXED_CST); |
| fp = ggc_alloc<fixed_value> (); |
| memcpy (fp, &f, sizeof (FIXED_VALUE_TYPE)); |
| |
| TREE_TYPE (v) = type; |
| TREE_FIXED_CST_PTR (v) = fp; |
| return v; |
| } |
| |
| /* Return a new REAL_CST node whose type is TYPE and value is D. */ |
| |
| tree |
| build_real (tree type, REAL_VALUE_TYPE d) |
| { |
| tree v; |
| REAL_VALUE_TYPE *dp; |
| int overflow = 0; |
| |
| /* ??? Used to check for overflow here via CHECK_FLOAT_TYPE. |
| Consider doing it via real_convert now. */ |
| |
| v = make_node (REAL_CST); |
| dp = ggc_alloc<real_value> (); |
| memcpy (dp, &d, sizeof (REAL_VALUE_TYPE)); |
| |
| TREE_TYPE (v) = type; |
| TREE_REAL_CST_PTR (v) = dp; |
| TREE_OVERFLOW (v) = overflow; |
| return v; |
| } |
| |
| /* Return a new REAL_CST node whose type is TYPE |
| and whose value is the integer value of the INTEGER_CST node I. */ |
| |
| REAL_VALUE_TYPE |
| real_value_from_int_cst (const_tree type, const_tree i) |
| { |
| REAL_VALUE_TYPE d; |
| |
| /* Clear all bits of the real value type so that we can later do |
| bitwise comparisons to see if two values are the same. */ |
| memset (&d, 0, sizeof d); |
| |
| real_from_integer (&d, type ? TYPE_MODE (type) : VOIDmode, i, |
| TYPE_SIGN (TREE_TYPE (i))); |
| return d; |
| } |
| |
| /* Given a tree representing an integer constant I, return a tree |
| representing the same value as a floating-point constant of type TYPE. */ |
| |
| tree |
| build_real_from_int_cst (tree type, const_tree i) |
| { |
| tree v; |
| int overflow = TREE_OVERFLOW (i); |
| |
| v = build_real (type, real_value_from_int_cst (type, i)); |
| |
| TREE_OVERFLOW (v) |= overflow; |
| return v; |
| } |
| |
| /* Return a newly constructed STRING_CST node whose value is |
| the LEN characters at STR. |
| Note that for a C string literal, LEN should include the trailing NUL. |
| The TREE_TYPE is not initialized. */ |
| |
| tree |
| build_string (int len, const char *str) |
| { |
| tree s; |
| size_t length; |
| |
| /* Do not waste bytes provided by padding of struct tree_string. */ |
| length = len + offsetof (struct tree_string, str) + 1; |
| |
| record_node_allocation_statistics (STRING_CST, length); |
| |
| s = (tree) ggc_internal_alloc (length); |
| |
| memset (s, 0, sizeof (struct tree_typed)); |
| TREE_SET_CODE (s, STRING_CST); |
| TREE_CONSTANT (s) = 1; |
| TREE_STRING_LENGTH (s) = len; |
| memcpy (s->string.str, str, len); |
| s->string.str[len] = '\0'; |
| |
| return s; |
| } |
| |
| /* Return a newly constructed COMPLEX_CST node whose value is |
| specified by the real and imaginary parts REAL and IMAG. |
| Both REAL and IMAG should be constant nodes. TYPE, if specified, |
| will be the type of the COMPLEX_CST; otherwise a new type will be made. */ |
| |
| tree |
| build_complex (tree type, tree real, tree imag) |
| { |
| tree t = make_node (COMPLEX_CST); |
| |
| TREE_REALPART (t) = real; |
| TREE_IMAGPART (t) = imag; |
| TREE_TYPE (t) = type ? type : build_complex_type (TREE_TYPE (real)); |
| TREE_OVERFLOW (t) = TREE_OVERFLOW (real) | TREE_OVERFLOW (imag); |
| return t; |
| } |
| |
| /* Return a constant of arithmetic type TYPE which is the |
| multiplicative identity of the set TYPE. */ |
| |
| tree |
| build_one_cst (tree type) |
| { |
| switch (TREE_CODE (type)) |
| { |
| case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: |
| case POINTER_TYPE: case REFERENCE_TYPE: |
| case OFFSET_TYPE: |
| return build_int_cst (type, 1); |
| |
| case REAL_TYPE: |
| return build_real (type, dconst1); |
| |
| case FIXED_POINT_TYPE: |
| /* We can only generate 1 for accum types. */ |
| gcc_assert (ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type))); |
| return build_fixed (type, FCONST1 (TYPE_MODE (type))); |
| |
| case VECTOR_TYPE: |
| { |
| tree scalar = build_one_cst (TREE_TYPE (type)); |
| |
| return build_vector_from_val (type, scalar); |
| } |
| |
| case COMPLEX_TYPE: |
| return build_complex (type, |
| build_one_cst (TREE_TYPE (type)), |
| build_zero_cst (TREE_TYPE (type))); |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Return an integer of type TYPE containing all 1's in as much precision as |
| it contains, or a complex or vector whose subparts are such integers. */ |
| |
| tree |
| build_all_ones_cst (tree type) |
| { |
| if (TREE_CODE (type) == COMPLEX_TYPE) |
| { |
| tree scalar = build_all_ones_cst (TREE_TYPE (type)); |
| return build_complex (type, scalar, scalar); |
| } |
| else |
| return build_minus_one_cst (type); |
| } |
| |
| /* Return a constant of arithmetic type TYPE which is the |
| opposite of the multiplicative identity of the set TYPE. */ |
| |
| tree |
| build_minus_one_cst (tree type) |
| { |
| switch (TREE_CODE (type)) |
| { |
| case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: |
| case POINTER_TYPE: case REFERENCE_TYPE: |
| case OFFSET_TYPE: |
| return build_int_cst (type, -1); |
| |
| case REAL_TYPE: |
| return build_real (type, dconstm1); |
| |
| case FIXED_POINT_TYPE: |
| /* We can only generate 1 for accum types. */ |
| gcc_assert (ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type))); |
| return build_fixed (type, fixed_from_double_int (double_int_minus_one, |
| TYPE_MODE (type))); |
| |
| case VECTOR_TYPE: |
| { |
| tree scalar = build_minus_one_cst (TREE_TYPE (type)); |
| |
| return build_vector_from_val (type, scalar); |
| } |
| |
| case COMPLEX_TYPE: |
| return build_complex (type, |
| build_minus_one_cst (TREE_TYPE (type)), |
| build_zero_cst (TREE_TYPE (type))); |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Build 0 constant of type TYPE. This is used by constructor folding |
| and thus the constant should be represented in memory by |
| zero(es). */ |
| |
| tree |
| build_zero_cst (tree type) |
| { |
| switch (TREE_CODE (type)) |
| { |
| case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: |
| case POINTER_TYPE: case REFERENCE_TYPE: |
| case OFFSET_TYPE: case NULLPTR_TYPE: |
| return build_int_cst (type, 0); |
| |
| case REAL_TYPE: |
| return build_real (type, dconst0); |
| |
| case FIXED_POINT_TYPE: |
| return build_fixed (type, FCONST0 (TYPE_MODE (type))); |
| |
| case VECTOR_TYPE: |
| { |
| tree scalar = build_zero_cst (TREE_TYPE (type)); |
| |
| return build_vector_from_val (type, scalar); |
| } |
| |
| case COMPLEX_TYPE: |
| { |
| tree zero = build_zero_cst (TREE_TYPE (type)); |
| |
| return build_complex (type, zero, zero); |
| } |
| |
| default: |
| if (!AGGREGATE_TYPE_P (type)) |
| return fold_convert (type, integer_zero_node); |
| return build_constructor (type, NULL); |
| } |
| } |
| |
| |
| /* Build a BINFO with LEN language slots. */ |
| |
| tree |
| make_tree_binfo_stat (unsigned base_binfos MEM_STAT_DECL) |
| { |
| tree t; |
| size_t length = (offsetof (struct tree_binfo, base_binfos) |
| + vec<tree, va_gc>::embedded_size (base_binfos)); |
| |
| record_node_allocation_statistics (TREE_BINFO, length); |
| |
| t = ggc_alloc_tree_node_stat (length PASS_MEM_STAT); |
| |
| memset (t, 0, offsetof (struct tree_binfo, base_binfos)); |
| |
| TREE_SET_CODE (t, TREE_BINFO); |
| |
| BINFO_BASE_BINFOS (t)->embedded_init (base_binfos); |
| |
| return t; |
| } |
| |
| /* Create a CASE_LABEL_EXPR tree node and return it. */ |
| |
| tree |
| build_case_label (tree low_value, tree high_value, tree label_decl) |
| { |
| tree t = make_node (CASE_LABEL_EXPR); |
| |
| TREE_TYPE (t) = void_type_node; |
| SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (label_decl)); |
| |
| CASE_LOW (t) = low_value; |
| CASE_HIGH (t) = high_value; |
| CASE_LABEL (t) = label_decl; |
| CASE_CHAIN (t) = NULL_TREE; |
| |
| return t; |
| } |
| |
| /* Build a newly constructed INTEGER_CST node. LEN and EXT_LEN are the |
| values of TREE_INT_CST_NUNITS and TREE_INT_CST_EXT_NUNITS respectively. |
| The latter determines the length of the HOST_WIDE_INT vector. */ |
| |
| tree |
| make_int_cst_stat (int len, int ext_len MEM_STAT_DECL) |
| { |
| tree t; |
| int length = ((ext_len - 1) * sizeof (HOST_WIDE_INT) |
| + sizeof (struct tree_int_cst)); |
| |
| gcc_assert (len); |
| record_node_allocation_statistics (INTEGER_CST, length); |
| |
| t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT); |
| |
| TREE_SET_CODE (t, INTEGER_CST); |
| TREE_INT_CST_NUNITS (t) = len; |
| TREE_INT_CST_EXT_NUNITS (t) = ext_len; |
| /* to_offset can only be applied to trees that are offset_int-sized |
| or smaller. EXT_LEN is correct if it fits, otherwise the constant |
| must be exactly the precision of offset_int and so LEN is correct. */ |
| if (ext_len <= OFFSET_INT_ELTS) |
| TREE_INT_CST_OFFSET_NUNITS (t) = ext_len; |
| else |
| TREE_INT_CST_OFFSET_NUNITS (t) = len; |
| |
| TREE_CONSTANT (t) = 1; |
| |
| return t; |
| } |
| |
| /* Build a newly constructed TREE_VEC node of length LEN. */ |
| |
| tree |
| make_tree_vec_stat (int len MEM_STAT_DECL) |
| { |
| tree t; |
| int length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec); |
| |
| record_node_allocation_statistics (TREE_VEC, length); |
| |
| t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT); |
| |
| TREE_SET_CODE (t, TREE_VEC); |
| TREE_VEC_LENGTH (t) = len; |
| |
| return t; |
| } |
| |
| /* Grow a TREE_VEC node to new length LEN. */ |
| |
| tree |
| grow_tree_vec_stat (tree v, int len MEM_STAT_DECL) |
| { |
| gcc_assert (TREE_CODE (v) == TREE_VEC); |
| |
| int oldlen = TREE_VEC_LENGTH (v); |
| gcc_assert (len > oldlen); |
| |
| int oldlength = (oldlen - 1) * sizeof (tree) + sizeof (struct tree_vec); |
| int length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec); |
| |
| record_node_allocation_statistics (TREE_VEC, length - oldlength); |
| |
| v = (tree) ggc_realloc (v, length PASS_MEM_STAT); |
| |
| TREE_VEC_LENGTH (v) = len; |
| |
| return v; |
| } |
| |
| /* Return 1 if EXPR is the integer constant zero or a complex constant |
| of zero. */ |
| |
| int |
| integer_zerop (const_tree expr) |
| { |
| STRIP_NOPS (expr); |
| |
| switch (TREE_CODE (expr)) |
| { |
| case INTEGER_CST: |
| return wi::eq_p (expr, 0); |
| case COMPLEX_CST: |
| return (integer_zerop (TREE_REALPART (expr)) |
| && integer_zerop (TREE_IMAGPART (expr))); |
| case VECTOR_CST: |
| { |
| unsigned i; |
| for (i = 0; i < VECTOR_CST_NELTS (expr); ++i) |
| if (!integer_zerop (VECTOR_CST_ELT (expr, i))) |
| return false; |
| return true; |
| } |
| default: |
| return false; |
| } |
| } |
| |
| /* Return 1 if EXPR is the integer constant one or the corresponding |
| complex constant. */ |
| |
| int |
| integer_onep (const_tree expr) |
| { |
| STRIP_NOPS (expr); |
| |
| switch (TREE_CODE (expr)) |
| { |
| case INTEGER_CST: |
| return wi::eq_p (wi::to_widest (expr), 1); |
| case COMPLEX_CST: |
| return (integer_onep (TREE_REALPART (expr)) |
| && integer_zerop (TREE_IMAGPART (expr))); |
| case VECTOR_CST: |
| { |
| unsigned i; |
| for (i = 0; i < VECTOR_CST_NELTS (expr); ++i) |
| if (!integer_onep (VECTOR_CST_ELT (expr, i))) |
| return false; |
| return true; |
| } |
| default: |
| return false; |
| } |
| } |
| |
| /* Return 1 if EXPR is the integer constant one. For complex and vector, |
| return 1 if every piece is the integer constant one. */ |
| |
| int |
| integer_each_onep (const_tree expr) |
| { |
| STRIP_NOPS (expr); |
| |
| if (TREE_CODE (expr) == COMPLEX_CST) |
| return (integer_onep (TREE_REALPART (expr)) |
| && integer_onep (TREE_IMAGPART (expr))); |
| else |
| return integer_onep (expr); |
| } |
| |
| /* Return 1 if EXPR is an integer containing all 1's in as much precision as |
| it contains, or a complex or vector whose subparts are such integers. */ |
| |
| int |
| integer_all_onesp (const_tree expr) |
| { |
| STRIP_NOPS (expr); |
| |
| if (TREE_CODE (expr) == COMPLEX_CST |
| && integer_all_onesp (TREE_REALPART (expr)) |
| && integer_all_onesp (TREE_IMAGPART (expr))) |
| return 1; |
| |
| else if (TREE_CODE (expr) == VECTOR_CST) |
| { |
| unsigned i; |
| for (i = 0; i < VECTOR_CST_NELTS (expr); ++i) |
| if (!integer_all_onesp (VECTOR_CST_ELT (expr, i))) |
| return 0; |
| return 1; |
| } |
| |
| else if (TREE_CODE (expr) != INTEGER_CST) |
| return 0; |
| |
| return wi::max_value (TYPE_PRECISION (TREE_TYPE (expr)), UNSIGNED) == expr; |
| } |
| |
| /* Return 1 if EXPR is the integer constant minus one. */ |
| |
| int |
| integer_minus_onep (const_tree expr) |
| { |
| STRIP_NOPS (expr); |
| |
| if (TREE_CODE (expr) == COMPLEX_CST) |
| return (integer_all_onesp (TREE_REALPART (expr)) |
| && integer_zerop (TREE_IMAGPART (expr))); |
| else |
| return integer_all_onesp (expr); |
| } |
| |
| /* Return 1 if EXPR is an integer constant that is a power of 2 (i.e., has only |
| one bit on). */ |
| |
| int |
| integer_pow2p (const_tree expr) |
| { |
| STRIP_NOPS (expr); |
| |
| if (TREE_CODE (expr) == COMPLEX_CST |
| && integer_pow2p (TREE_REALPART (expr)) |
| && integer_zerop (TREE_IMAGPART (expr))) |
| return 1; |
| |
| if (TREE_CODE (expr) != INTEGER_CST) |
| return 0; |
| |
| return wi::popcount (expr) == 1; |
| } |
| |
| /* Return 1 if EXPR is an integer constant other than zero or a |
| complex constant other than zero. */ |
| |
| int |
| integer_nonzerop (const_tree expr) |
| { |
| STRIP_NOPS (expr); |
| |
| return ((TREE_CODE (expr) == INTEGER_CST |
| && !wi::eq_p (expr, 0)) |
| || (TREE_CODE (expr) == COMPLEX_CST |
| && (integer_nonzerop (TREE_REALPART (expr)) |
| || integer_nonzerop (TREE_IMAGPART (expr))))); |
| } |
| |
| /* Return 1 if EXPR is the integer constant one. For vector, |
| return 1 if every piece is the integer constant minus one |
| (representing the value TRUE). */ |
| |
| int |
| integer_truep (const_tree expr) |
| { |
| STRIP_NOPS (expr); |
| |
| if (TREE_CODE (expr) == VECTOR_CST) |
| return integer_all_onesp (expr); |
| return integer_onep (expr); |
| } |
| |
| /* Return 1 if EXPR is the fixed-point constant zero. */ |
| |
| int |
| fixed_zerop (const_tree expr) |
| { |
| return (TREE_CODE (expr) == FIXED_CST |
| && TREE_FIXED_CST (expr).data.is_zero ()); |
| } |
| |
| /* Return the power of two represented by a tree node known to be a |
| power of two. */ |
| |
| int |
| tree_log2 (const_tree expr) |
| { |
| STRIP_NOPS (expr); |
| |
| if (TREE_CODE (expr) == COMPLEX_CST) |
| return tree_log2 (TREE_REALPART (expr)); |
| |
| return wi::exact_log2 (expr); |
| } |
| |
| /* Similar, but return the largest integer Y such that 2 ** Y is less |
| than or equal to EXPR. */ |
| |
| int |
| tree_floor_log2 (const_tree expr) |
| { |
| STRIP_NOPS (expr); |
| |
| if (TREE_CODE (expr) == COMPLEX_CST) |
| return tree_log2 (TREE_REALPART (expr)); |
| |
| return wi::floor_log2 (expr); |
| } |
| |
| /* Return number of known trailing zero bits in EXPR, or, if the value of |
| EXPR is known to be zero, the precision of it's type. */ |
| |
| unsigned int |
| tree_ctz (const_tree expr) |
| { |
| if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)) |
| && !POINTER_TYPE_P (TREE_TYPE (expr))) |
| return 0; |
| |
| unsigned int ret1, ret2, prec = TYPE_PRECISION (TREE_TYPE (expr)); |
| switch (TREE_CODE (expr)) |
| { |
| case INTEGER_CST: |
| ret1 = wi::ctz (expr); |
| return MIN (ret1, prec); |
| case SSA_NAME: |
| ret1 = wi::ctz (get_nonzero_bits (expr)); |
| return MIN (ret1, prec); |
| case PLUS_EXPR: |
| case MINUS_EXPR: |
| case BIT_IOR_EXPR: |
| case BIT_XOR_EXPR: |
| case MIN_EXPR: |
| case MAX_EXPR: |
| ret1 = tree_ctz (TREE_OPERAND (expr, 0)); |
| if (ret1 == 0) |
| return ret1; |
| ret2 = tree_ctz (TREE_OPERAND (expr, 1)); |
| return MIN (ret1, ret2); |
| case POINTER_PLUS_EXPR: |
| ret1 = tree_ctz (TREE_OPERAND (expr, 0)); |
| ret2 = tree_ctz (TREE_OPERAND (expr, 1)); |
| /* Second operand is sizetype, which could be in theory |
| wider than pointer's precision. Make sure we never |
| return more than prec. */ |
| ret2 = MIN (ret2, prec); |
| return MIN (ret1, ret2); |
| case BIT_AND_EXPR: |
| ret1 = tree_ctz (TREE_OPERAND (expr, 0)); |
| ret2 = tree_ctz (TREE_OPERAND (expr, 1)); |
| return MAX (ret1, ret2); |
| case MULT_EXPR: |
| ret1 = tree_ctz (TREE_OPERAND (expr, 0)); |
| ret2 = tree_ctz (TREE_OPERAND (expr, 1)); |
| return MIN (ret1 + ret2, prec); |
| case LSHIFT_EXPR: |
| ret1 = tree_ctz (TREE_OPERAND (expr, 0)); |
| if (tree_fits_uhwi_p (TREE_OPERAND (expr, 1)) |
| && (tree_to_uhwi (TREE_OPERAND (expr, 1)) < prec)) |
| { |
| ret2 = tree_to_uhwi (TREE_OPERAND (expr, 1)); |
| return MIN (ret1 + ret2, prec); |
| } |
| return ret1; |
| case RSHIFT_EXPR: |
| if (tree_fits_uhwi_p (TREE_OPERAND (expr, 1)) |
| && (tree_to_uhwi (TREE_OPERAND (expr, 1)) < prec)) |
| { |
| ret1 = tree_ctz (TREE_OPERAND (expr, 0)); |
| ret2 = tree_to_uhwi (TREE_OPERAND (expr, 1)); |
| if (ret1 > ret2) |
| return ret1 - ret2; |
| } |
| return 0; |
| case TRUNC_DIV_EXPR: |
| case CEIL_DIV_EXPR: |
| case FLOOR_DIV_EXPR: |
| case ROUND_DIV_EXPR: |
| case EXACT_DIV_EXPR: |
| if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST |
| && tree_int_cst_sgn (TREE_OPERAND (expr, 1)) == 1) |
| { |
| int l = tree_log2 (TREE_OPERAND (expr, 1)); |
| if (l >= 0) |
| { |
| ret1 = tree_ctz (TREE_OPERAND (expr, 0)); |
| ret2 = l; |
| if (ret1 > ret2) |
| return ret1 - ret2; |
| } |
| } |
| return 0; |
| CASE_CONVERT: |
| ret1 = tree_ctz (TREE_OPERAND (expr, 0)); |
| if (ret1 && ret1 == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0)))) |
| ret1 = prec; |
| return MIN (ret1, prec); |
| case SAVE_EXPR: |
| return tree_ctz (TREE_OPERAND (expr, 0)); |
| case COND_EXPR: |
| ret1 = tree_ctz (TREE_OPERAND (expr, 1)); |
| if (ret1 == 0) |
| return 0; |
| ret2 = tree_ctz (TREE_OPERAND (expr, 2)); |
| return MIN (ret1, ret2); |
| case COMPOUND_EXPR: |
| return tree_ctz (TREE_OPERAND (expr, 1)); |
| case ADDR_EXPR: |
| ret1 = get_pointer_alignment (CONST_CAST_TREE (expr)); |
| if (ret1 > BITS_PER_UNIT) |
| { |
| ret1 = ctz_hwi (ret1 / BITS_PER_UNIT); |
| return MIN (ret1, prec); |
| } |
| return 0; |
| default: |
| return 0; |
| } |
| } |
| |
| /* Return 1 if EXPR is the real constant zero. Trailing zeroes matter for |
| decimal float constants, so don't return 1 for them. */ |
| |
| int |
| real_zerop (const_tree expr) |
| { |
| STRIP_NOPS (expr); |
| |
| switch (TREE_CODE (expr)) |
| { |
| case REAL_CST: |
| return REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0) |
| && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))); |
| case COMPLEX_CST: |
| return real_zerop (TREE_REALPART (expr)) |
| && real_zerop (TREE_IMAGPART (expr)); |
| case VECTOR_CST: |
| { |
| unsigned i; |
| for (i = 0; i < VECTOR_CST_NELTS (expr); ++i) |
| if (!real_zerop (VECTOR_CST_ELT (expr, i))) |
| return false; |
| return true; |
| } |
| default: |
| return false; |
| } |
| } |
| |
| /* Return 1 if EXPR is the real constant one in real or complex form. |
| Trailing zeroes matter for decimal float constants, so don't return |
| 1 for them. */ |
| |
| int |
| real_onep (const_tree expr) |
| { |
| STRIP_NOPS (expr); |
| |
| switch (TREE_CODE (expr)) |
| { |
| case REAL_CST: |
| return REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1) |
| && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))); |
| case COMPLEX_CST: |
| return real_onep (TREE_REALPART (expr)) |
| && real_zerop (TREE_IMAGPART (expr)); |
| case VECTOR_CST: |
| { |
| unsigned i; |
| for (i = 0; i < VECTOR_CST_NELTS (expr); ++i) |
| if (!real_onep (VECTOR_CST_ELT (expr, i))) |
| return false; |
| return true; |
| } |
| default: |
| return false; |
| } |
| } |
| |
| /* Return 1 if EXPR is the real constant minus one. Trailing zeroes |
| matter for decimal float constants, so don't return 1 for them. */ |
| |
| int |
| real_minus_onep (const_tree expr) |
| { |
| STRIP_NOPS (expr); |
| |
| switch (TREE_CODE (expr)) |
| { |
| case REAL_CST: |
| return REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1) |
| && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))); |
| case COMPLEX_CST: |
| return real_minus_onep (TREE_REALPART (expr)) |
| && real_zerop (TREE_IMAGPART (expr)); |
| case VECTOR_CST: |
| { |
| unsigned i; |
| for (i = 0; i < VECTOR_CST_NELTS (expr); ++i) |
| if (!real_minus_onep (VECTOR_CST_ELT (expr, i))) |
| return false; |
| return true; |
| } |
| default: |
| return false; |
| } |
| } |
| |
| /* Nonzero if EXP is a constant or a cast of a constant. */ |
| |
| int |
| really_constant_p (const_tree exp) |
| { |
| /* This is not quite the same as STRIP_NOPS. It does more. */ |
| while (CONVERT_EXPR_P (exp) |
| || TREE_CODE (exp) == NON_LVALUE_EXPR) |
| exp = TREE_OPERAND (exp, 0); |
| return TREE_CONSTANT (exp); |
| } |
| |
| /* Return first list element whose TREE_VALUE is ELEM. |
| Return 0 if ELEM is not in LIST. */ |
| |
| tree |
| value_member (tree elem, tree list) |
| { |
| while (list) |
| { |
| if (elem == TREE_VALUE (list)) |
| return list; |
| list = TREE_CHAIN (list); |
| } |
| return NULL_TREE; |
| } |
| |
| /* Return first list element whose TREE_PURPOSE is ELEM. |
| Return 0 if ELEM is not in LIST. */ |
| |
| tree |
| purpose_member (const_tree elem, tree list) |
| { |
| while (list) |
| { |
| if (elem == TREE_PURPOSE (list)) |
| return list; |
| list = TREE_CHAIN (list); |
| } |
| return NULL_TREE; |
| } |
| |
| /* Return true if ELEM is in V. */ |
| |
| bool |
| vec_member (const_tree elem, vec<tree, va_gc> *v) |
| { |
| unsigned ix; |
| tree t; |
| FOR_EACH_VEC_SAFE_ELT (v, ix, t) |
| if (elem == t) |
| return true; |
| return false; |
| } |
| |
| /* Returns element number IDX (zero-origin) of chain CHAIN, or |
| NULL_TREE. */ |
| |
| tree |
| chain_index (int idx, tree chain) |
| { |
| for (; chain && idx > 0; --idx) |
| chain = TREE_CHAIN (chain); |
| return chain; |
| } |
| |
| /* Return nonzero if ELEM is part of the chain CHAIN. */ |
| |
| int |
| chain_member (const_tree elem, const_tree chain) |
| { |
| while (chain) |
| { |
| if (elem == chain) |
| return 1; |
| chain = DECL_CHAIN (chain); |
| } |
| |
| return 0; |
| } |
| |
| /* Return the length of a chain of nodes chained through TREE_CHAIN. |
| We expect a null pointer to mark the end of the chain. |
| This is the Lisp primitive `length'. */ |
| |
| int |
| list_length (const_tree t) |
| { |
| const_tree p = t; |
| #ifdef ENABLE_TREE_CHECKING |
| const_tree q = t; |
| #endif |
| int len = 0; |
| |
| while (p) |
| { |
| p = TREE_CHAIN (p); |
| #ifdef ENABLE_TREE_CHECKING |
| if (len % 2) |
| q = TREE_CHAIN (q); |
| gcc_assert (p != q); |
| #endif |
| len++; |
| } |
| |
| return len; |
| } |
| |
| /* Returns the first FIELD_DECL in the TYPE_FIELDS of the RECORD_TYPE or |
| UNION_TYPE TYPE, or NULL_TREE if none. */ |
| |
| tree |
| first_field (const_tree type) |
| { |
| tree t = TYPE_FIELDS (type); |
| while (t && TREE_CODE (t) != FIELD_DECL) |
| t = TREE_CHAIN (t); |
| return t; |
| } |
| |
| /* Concatenate two chains of nodes (chained through TREE_CHAIN) |
| by modifying the last node in chain 1 to point to chain 2. |
| This is the Lisp primitive `nconc'. */ |
| |
| tree |
| chainon (tree op1, tree op2) |
| { |
| tree t1; |
| |
| if (!op1) |
| return op2; |
| if (!op2) |
| return op1; |
| |
| for (t1 = op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1)) |
| continue; |
| TREE_CHAIN (t1) = op2; |
| |
| #ifdef ENABLE_TREE_CHECKING |
| { |
| tree t2; |
| for (t2 = op2; t2; t2 = TREE_CHAIN (t2)) |
| gcc_assert (t2 != t1); |
| } |
| #endif |
| |
| return op1; |
| } |
| |
| /* Return the last node in a chain of nodes (chained through TREE_CHAIN). */ |
| |
| tree |
| tree_last (tree chain) |
| { |
| tree next; |
| if (chain) |
| while ((next = TREE_CHAIN (chain))) |
| chain = next; |
| return chain; |
| } |
| |
| /* Reverse the order of elements in the chain T, |
| and return the new head of the chain (old last element). */ |
| |
| tree |
| nreverse (tree t) |
| { |
| tree prev = 0, decl, next; |
| for (decl = t; decl; decl = next) |
| { |
| /* We shouldn't be using this function to reverse BLOCK chains; we |
| have blocks_nreverse for that. */ |
| gcc_checking_assert (TREE_CODE (decl) != BLOCK); |
| next = TREE_CHAIN (decl); |
| TREE_CHAIN (decl) = prev; |
| prev = decl; |
| } |
| return prev; |
| } |
| |
| /* Return a newly created TREE_LIST node whose |
| purpose and value fields are PARM and VALUE. */ |
| |
| tree |
| build_tree_list_stat (tree parm, tree value MEM_STAT_DECL) |
| { |
| tree t = make_node_stat (TREE_LIST PASS_MEM_STAT); |
| TREE_PURPOSE (t) = parm; |
| TREE_VALUE (t) = value; |
| return t; |
| } |
| |
| /* Build a chain of TREE_LIST nodes from a vector. */ |
| |
| tree |
| build_tree_list_vec_stat (const vec<tree, va_gc> *vec MEM_STAT_DECL) |
| { |
| tree ret = NULL_TREE; |
| tree *pp = &ret; |
| unsigned int i; |
| tree t; |
| FOR_EACH_VEC_SAFE_ELT (vec, i, t) |
| { |
| *pp = build_tree_list_stat (NULL, t PASS_MEM_STAT); |
| pp = &TREE_CHAIN (*pp); |
| } |
| return ret; |
| } |
| |
| /* Return a newly created TREE_LIST node whose |
| purpose and value fields are PURPOSE and VALUE |
| and whose TREE_CHAIN is CHAIN. */ |
| |
| tree |
| tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL) |
| { |
| tree node; |
| |
| node = ggc_alloc_tree_node_stat (sizeof (struct tree_list) PASS_MEM_STAT); |
| memset (node, 0, sizeof (struct tree_common)); |
| |
| record_node_allocation_statistics (TREE_LIST, sizeof (struct tree_list)); |
| |
| TREE_SET_CODE (node, TREE_LIST); |
| TREE_CHAIN (node) = chain; |
| TREE_PURPOSE (node) = purpose; |
| TREE_VALUE (node) = value; |
| return node; |
| } |
| |
| /* Return the values of the elements of a CONSTRUCTOR as a vector of |
| trees. */ |
| |
| vec<tree, va_gc> * |
| ctor_to_vec (tree ctor) |
| { |
| vec<tree, va_gc> *vec; |
| vec_alloc (vec, CONSTRUCTOR_NELTS (ctor)); |
| unsigned int ix; |
| tree val; |
| |
| FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), ix, val) |
| vec->quick_push (val); |
| |
| return vec; |
| } |
| |
| /* Return the size nominally occupied by an object of type TYPE |
| when it resides in memory. The value is measured in units of bytes, |
| and its data type is that normally used for type sizes |
| (which is the first type created by make_signed_type or |
| make_unsigned_type). */ |
| |
| tree |
| size_in_bytes (const_tree type) |
| { |
| tree t; |
| |
| if (type == error_mark_node) |
| return integer_zero_node; |
| |
| type = TYPE_MAIN_VARIANT (type); |
| t = TYPE_SIZE_UNIT (type); |
| |
| if (t == 0) |
| { |
| lang_hooks.types.incomplete_type_error (NULL_TREE, type); |
| return size_zero_node; |
| } |
| |
| return t; |
| } |
| |
| /* Return the size of TYPE (in bytes) as a wide integer |
| or return -1 if the size can vary or is larger than an integer. */ |
| |
| HOST_WIDE_INT |
| int_size_in_bytes (const_tree type) |
| { |
| tree t; |
| |
| if (type == error_mark_node) |
| return 0; |
| |
| type = TYPE_MAIN_VARIANT (type); |
| t = TYPE_SIZE_UNIT (type); |
| |
| if (t && tree_fits_uhwi_p (t)) |
| return TREE_INT_CST_LOW (t); |
| else |
| return -1; |
| } |
| |
| /* Return the maximum size of TYPE (in bytes) as a wide integer |
| or return -1 if the size can vary or is larger than an integer. */ |
| |
| HOST_WIDE_INT |
| max_int_size_in_bytes (const_tree type) |
| { |
| HOST_WIDE_INT size = -1; |
| tree size_tree; |
| |
| /* If this is an array type, check for a possible MAX_SIZE attached. */ |
| |
| if (TREE_CODE (type) == ARRAY_TYPE) |
| { |
| size_tree = TYPE_ARRAY_MAX_SIZE (type); |
| |
| if (size_tree && tree_fits_uhwi_p (size_tree)) |
| size = tree_to_uhwi (size_tree); |
| } |
| |
| /* If we still haven't been able to get a size, see if the language |
| can compute a maximum size. */ |
| |
| if (size == -1) |
| { |
| size_tree = lang_hooks.types.max_size (type); |
| |
| if (size_tree && tree_fits_uhwi_p (size_tree)) |
| size = tree_to_uhwi (size_tree); |
| } |
| |
| return size; |
| } |
| |
| /* Return the bit position of FIELD, in bits from the start of the record. |
| This is a tree of type bitsizetype. */ |
| |
| tree |
| bit_position (const_tree field) |
| { |
| return bit_from_pos (DECL_FIELD_OFFSET (field), |
| DECL_FIELD_BIT_OFFSET (field)); |
| } |
| |
| /* Return the byte position of FIELD, in bytes from the start of the record. |
| This is a tree of type sizetype. */ |
| |
| tree |
| byte_position (const_tree field) |
| { |
| return byte_from_pos (DECL_FIELD_OFFSET (field), |
| DECL_FIELD_BIT_OFFSET (field)); |
| } |
| |
| /* Likewise, but return as an integer. It must be representable in |
| that way (since it could be a signed value, we don't have the |
| option of returning -1 like int_size_in_byte can. */ |
| |
| HOST_WIDE_INT |
| int_byte_position (const_tree field) |
| { |
| return tree_to_shwi (byte_position (field)); |
| } |
| |
| /* Return the strictest alignment, in bits, that T is known to have. */ |
| |
| unsigned int |
| expr_align (const_tree t) |
| { |
| unsigned int align0, align1; |
| |
| switch (TREE_CODE (t)) |
| { |
| CASE_CONVERT: case NON_LVALUE_EXPR: |
| /* If we have conversions, we know that the alignment of the |
| object must meet each of the alignments of the types. */ |
| align0 = expr_align (TREE_OPERAND (t, 0)); |
| align1 = TYPE_ALIGN (TREE_TYPE (t)); |
| return MAX (align0, align1); |
| |
| case SAVE_EXPR: case COMPOUND_EXPR: case MODIFY_EXPR: |
| case INIT_EXPR: case TARGET_EXPR: case WITH_CLEANUP_EXPR: |
| case CLEANUP_POINT_EXPR: |
| /* These don't change the alignment of an object. */ |
| return expr_align (TREE_OPERAND (t, 0)); |
| |
| case COND_EXPR: |
| /* The best we can do is say that the alignment is the least aligned |
| of the two arms. */ |
| align0 = expr_align (TREE_OPERAND (t, 1)); |
| align1 = expr_align (TREE_OPERAND (t, 2)); |
| return MIN (align0, align1); |
| |
| /* FIXME: LABEL_DECL and CONST_DECL never have DECL_ALIGN set |
| meaningfully, it's always 1. */ |
| case LABEL_DECL: case CONST_DECL: |
| case VAR_DECL: case PARM_DECL: case RESULT_DECL: |
| case FUNCTION_DECL: |
| gcc_assert (DECL_ALIGN (t) != 0); |
| return DECL_ALIGN (t); |
| |
| default: |
| break; |
| } |
| |
| /* Otherwise take the alignment from that of the type. */ |
| return TYPE_ALIGN (TREE_TYPE (t)); |
| } |
| |
| /* Return, as a tree node, the number of elements for TYPE (which is an |
| ARRAY_TYPE) minus one. This counts only elements of the top array. */ |
| |
| tree |
| array_type_nelts (const_tree type) |
| { |
| tree index_type, min, max; |
| |
| /* If they did it with unspecified bounds, then we should have already |
| given an error about it before we got here. */ |
| if (! TYPE_DOMAIN (type)) |
| return error_mark_node; |
| |
| index_type = TYPE_DOMAIN (type); |
| min = TYPE_MIN_VALUE (index_type); |
| max = TYPE_MAX_VALUE (index_type); |
| |
| /* TYPE_MAX_VALUE may not be set if the array has unknown length. */ |
| if (!max) |
| return error_mark_node; |
| |
| return (integer_zerop (min) |
| ? max |
| : fold_build2 (MINUS_EXPR, TREE_TYPE (max), max, min)); |
| } |
| |
| /* If arg is static -- a reference to an object in static storage -- then |
| return the object. This is not the same as the C meaning of `static'. |
| If arg isn't static, return NULL. */ |
| |
| tree |
| staticp (tree arg) |
| { |
| switch (TREE_CODE (arg)) |
| { |
| case FUNCTION_DECL: |
| /* Nested functions are static, even though taking their address will |
| involve a trampoline as we unnest the nested function and create |
| the trampoline on the tree level. */ |
| return arg; |
| |
| case VAR_DECL: |
| return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg)) |
| && ! DECL_THREAD_LOCAL_P (arg) |
| && ! DECL_DLLIMPORT_P (arg) |
| ? arg : NULL); |
| |
| case CONST_DECL: |
| return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg)) |
| ? arg : NULL); |
| |
| case CONSTRUCTOR: |
| return TREE_STATIC (arg) ? arg : NULL; |
| |
| case LABEL_DECL: |
| case STRING_CST: |
| return arg; |
| |
| case COMPONENT_REF: |
| /* If the thing being referenced is not a field, then it is |
| something language specific. */ |
| gcc_assert (TREE_CODE (TREE_OPERAND (arg, 1)) == FIELD_DECL); |
| |
| /* If we are referencing a bitfield, we can't evaluate an |
| ADDR_EXPR at compile time and so it isn't a constant. */ |
| if (DECL_BIT_FIELD (TREE_OPERAND (arg, 1))) |
| return NULL; |
| |
| return staticp (TREE_OPERAND (arg, 0)); |
| |
| case BIT_FIELD_REF: |
| return NULL; |
| |
| case INDIRECT_REF: |
| return TREE_CONSTANT (TREE_OPERAND (arg, 0)) ? arg : NULL; |
| |
| case ARRAY_REF: |
| case ARRAY_RANGE_REF: |
| if (TREE_CODE (TYPE_SIZE (TREE_TYPE (arg))) == INTEGER_CST |
| && TREE_CODE (TREE_OPERAND (arg, 1)) == INTEGER_CST) |
| return staticp (TREE_OPERAND (arg, 0)); |
| else |
| return NULL; |
| |
| case COMPOUND_LITERAL_EXPR: |
| return TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (arg)) ? arg : NULL; |
| |
| default: |
| return NULL; |
| } |
| } |
| |
| |
| |
| |
| /* Return whether OP is a DECL whose address is function-invariant. */ |
| |
| bool |
| decl_address_invariant_p (const_tree op) |
| { |
| /* The conditions below are slightly less strict than the one in |
| staticp. */ |
| |
| switch (TREE_CODE (op)) |
| { |
| case PARM_DECL: |
| case RESULT_DECL: |
| case LABEL_DECL: |
| case FUNCTION_DECL: |
| return true; |
| |
| case VAR_DECL: |
| if ((TREE_STATIC (op) || DECL_EXTERNAL (op)) |
| || DECL_THREAD_LOCAL_P (op) |
| || DECL_CONTEXT (op) == current_function_decl |
| || decl_function_context (op) == current_function_decl) |
| return true; |
| break; |
| |
| case CONST_DECL: |
| if ((TREE_STATIC (op) || DECL_EXTERNAL (op)) |
| || decl_function_context (op) == current_function_decl) |
| return true; |
| break; |
| |
| default: |
| break; |
| } |
| |
| return false; |
| } |
| |
| /* Return whether OP is a DECL whose address is interprocedural-invariant. */ |
| |
| bool |
| decl_address_ip_invariant_p (const_tree op) |
| { |
| /* The conditions below are slightly less strict than the one in |
| staticp. */ |
| |
| switch (TREE_CODE (op)) |
| { |
| case LABEL_DECL: |
| case FUNCTION_DECL: |
| case STRING_CST: |
| return true; |
| |
| case VAR_DECL: |
| if (((TREE_STATIC (op) || DECL_EXTERNAL (op)) |
| && !DECL_DLLIMPORT_P (op)) |
| || DECL_THREAD_LOCAL_P (op)) |
| return true; |
| break; |
| |
| case CONST_DECL: |
| if ((TREE_STATIC (op) || DECL_EXTERNAL (op))) |
| return true; |
| break; |
| |
| default: |
| break; |
| } |
| |
| return false; |
| } |
| |
| |
| /* Return true if T is function-invariant (internal function, does |
| not handle arithmetic; that's handled in skip_simple_arithmetic and |
| tree_invariant_p). */ |
| |
| static bool tree_invariant_p (tree t); |
| |
| static bool |
| tree_invariant_p_1 (tree t) |
| { |
| tree op; |
| |
| if (TREE_CONSTANT (t) |
| || (TREE_READONLY (t) && !TREE_SIDE_EFFECTS (t))) |
| return true; |
| |
| switch (TREE_CODE (t)) |
| { |
| case SAVE_EXPR: |
| return true; |
| |
| case ADDR_EXPR: |
| op = TREE_OPERAND (t, 0); |
| while (handled_component_p (op)) |
| { |
| switch (TREE_CODE (op)) |
| { |
| case ARRAY_REF: |
| case ARRAY_RANGE_REF: |
| if (!tree_invariant_p (TREE_OPERAND (op, 1)) |
| || TREE_OPERAND (op, 2) != NULL_TREE |
| || TREE_OPERAND (op, 3) != NULL_TREE) |
| return false; |
| break; |
| |
| case COMPONENT_REF: |
| if (TREE_OPERAND (op, 2) != NULL_TREE) |
| return false; |
| break; |
| |
| default:; |
| } |
| op = TREE_OPERAND (op, 0); |
| } |
| |
| return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op); |
| |
| default: |
| break; |
| } |
| |
| return false; |
| } |
| |
| /* Return true if T is function-invariant. */ |
| |
| static bool |
| tree_invariant_p (tree t) |
| { |
| tree inner = skip_simple_arithmetic (t); |
| return tree_invariant_p_1 (inner); |
| } |
| |
| /* Wrap a SAVE_EXPR around EXPR, if appropriate. |
| Do this to any expression which may be used in more than one place, |
| but must be evaluated only once. |
| |
| Normally, expand_expr would reevaluate the expression each time. |
| Calling save_expr produces something that is evaluated and recorded |
| the first time expand_expr is called on it. Subsequent calls to |
| expand_expr just reuse the recorded value. |
| |
| The call to expand_expr that generates code that actually computes |
| the value is the first call *at compile time*. Subsequent calls |
| *at compile time* generate code to use the saved value. |
| This produces correct result provided that *at run time* control |
| always flows through the insns made by the first expand_expr |
| before reaching the other places where the save_expr was evaluated. |
| You, the caller of save_expr, must make sure this is so. |
| |
| Constants, and certain read-only nodes, are returned with no |
| SAVE_EXPR because that is safe. Expressions containing placeholders |
| are not touched; see tree.def for an explanation of what these |
| are used for. */ |
| |
| tree |
| save_expr (tree expr) |
| { |
| tree t = fold (expr); |
| tree inner; |
| |
| /* If the tree evaluates to a constant, then we don't want to hide that |
| fact (i.e. this allows further folding, and direct checks for constants). |
| However, a read-only object that has side effects cannot be bypassed. |
| Since it is no problem to reevaluate literals, we just return the |
| literal node. */ |
| inner = skip_simple_arithmetic (t); |
| if (TREE_CODE (inner) == ERROR_MARK) |
| return inner; |
| |
| if (tree_invariant_p_1 (inner)) |
| return t; |
| |
| /* If INNER contains a PLACEHOLDER_EXPR, we must evaluate it each time, since |
| it means that the size or offset of some field of an object depends on |
| the value within another field. |
| |
| Note that it must not be the case that T contains both a PLACEHOLDER_EXPR |
| and some variable since it would then need to be both evaluated once and |
| evaluated more than once. Front-ends must assure this case cannot |
| happen by surrounding any such subexpressions in their own SAVE_EXPR |
| and forcing evaluation at the proper time. */ |
| if (contains_placeholder_p (inner)) |
| return t; |
| |
| t = build1 (SAVE_EXPR, TREE_TYPE (expr), t); |
| SET_EXPR_LOCATION (t, EXPR_LOCATION (expr)); |
| |
| /* This expression might be placed ahead of a jump to ensure that the |
| value was computed on both sides of the jump. So make sure it isn't |
| eliminated as dead. */ |
| TREE_SIDE_EFFECTS (t) = 1; |
| return t; |
| } |
| |
| /* Look inside EXPR into any simple arithmetic operations. Return the |
| outermost non-arithmetic or non-invariant node. */ |
| |
| tree |
| skip_simple_arithmetic (tree expr) |
| { |
| /* We don't care about whether this can be used as an lvalue in this |
| context. */ |
| while (TREE_CODE (expr) == NON_LVALUE_EXPR) |
| expr = TREE_OPERAND (expr, 0); |
| |
| /* If we have simple operations applied to a SAVE_EXPR or to a SAVE_EXPR and |
| a constant, it will be more efficient to not make another SAVE_EXPR since |
| it will allow better simplification and GCSE will be able to merge the |
| computations if they actually occur. */ |
| while (true) |
| { |
| if (UNARY_CLASS_P (expr)) |
| expr = TREE_OPERAND (expr, 0); |
| else if (BINARY_CLASS_P (expr)) |
| { |
| if (tree_invariant_p (TREE_OPERAND (expr, 1))) |
| expr = TREE_OPERAND (expr, 0); |
| else if (tree_invariant_p (TREE_OPERAND |