138fd1498Szrj /* Language-independent node constructors for parse phase of GNU compiler.
238fd1498Szrj Copyright (C) 1987-2018 Free Software Foundation, Inc.
338fd1498Szrj
438fd1498Szrj This file is part of GCC.
538fd1498Szrj
638fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
738fd1498Szrj the terms of the GNU General Public License as published by the Free
838fd1498Szrj Software Foundation; either version 3, or (at your option) any later
938fd1498Szrj version.
1038fd1498Szrj
1138fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1238fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1338fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1438fd1498Szrj for more details.
1538fd1498Szrj
1638fd1498Szrj You should have received a copy of the GNU General Public License
1738fd1498Szrj along with GCC; see the file COPYING3. If not see
1838fd1498Szrj <http://www.gnu.org/licenses/>. */
1938fd1498Szrj
2038fd1498Szrj /* This file contains the low level primitives for operating on tree nodes,
2138fd1498Szrj including allocation, list operations, interning of identifiers,
2238fd1498Szrj construction of data type nodes and statement nodes,
2338fd1498Szrj and construction of type conversion nodes. It also contains
2438fd1498Szrj tables index by tree code that describe how to take apart
2538fd1498Szrj nodes of that code.
2638fd1498Szrj
2738fd1498Szrj It is intended to be language-independent but can occasionally
2838fd1498Szrj calls language-dependent routines. */
2938fd1498Szrj
3038fd1498Szrj #include "config.h"
3138fd1498Szrj #include "system.h"
3238fd1498Szrj #include "coretypes.h"
3338fd1498Szrj #include "backend.h"
3438fd1498Szrj #include "target.h"
3538fd1498Szrj #include "tree.h"
3638fd1498Szrj #include "gimple.h"
3738fd1498Szrj #include "tree-pass.h"
3838fd1498Szrj #include "ssa.h"
3938fd1498Szrj #include "cgraph.h"
4038fd1498Szrj #include "diagnostic.h"
4138fd1498Szrj #include "flags.h"
4238fd1498Szrj #include "alias.h"
4338fd1498Szrj #include "fold-const.h"
4438fd1498Szrj #include "stor-layout.h"
4538fd1498Szrj #include "calls.h"
4638fd1498Szrj #include "attribs.h"
4738fd1498Szrj #include "toplev.h" /* get_random_seed */
4838fd1498Szrj #include "output.h"
4938fd1498Szrj #include "common/common-target.h"
5038fd1498Szrj #include "langhooks.h"
5138fd1498Szrj #include "tree-inline.h"
5238fd1498Szrj #include "tree-iterator.h"
5338fd1498Szrj #include "internal-fn.h"
5438fd1498Szrj #include "gimple-iterator.h"
5538fd1498Szrj #include "gimplify.h"
5638fd1498Szrj #include "tree-dfa.h"
5738fd1498Szrj #include "params.h"
5838fd1498Szrj #include "langhooks-def.h"
5938fd1498Szrj #include "tree-diagnostic.h"
6038fd1498Szrj #include "except.h"
6138fd1498Szrj #include "builtins.h"
6238fd1498Szrj #include "print-tree.h"
6338fd1498Szrj #include "ipa-utils.h"
6438fd1498Szrj #include "selftest.h"
6538fd1498Szrj #include "stringpool.h"
6638fd1498Szrj #include "attribs.h"
6738fd1498Szrj #include "rtl.h"
6838fd1498Szrj #include "regs.h"
6938fd1498Szrj #include "tree-vector-builder.h"
7038fd1498Szrj
7138fd1498Szrj /* Tree code classes. */
7238fd1498Szrj
7338fd1498Szrj #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
7438fd1498Szrj #define END_OF_BASE_TREE_CODES tcc_exceptional,
7538fd1498Szrj
7638fd1498Szrj const enum tree_code_class tree_code_type[] = {
7738fd1498Szrj #include "all-tree.def"
7838fd1498Szrj };
7938fd1498Szrj
8038fd1498Szrj #undef DEFTREECODE
8138fd1498Szrj #undef END_OF_BASE_TREE_CODES
8238fd1498Szrj
8338fd1498Szrj /* Table indexed by tree code giving number of expression
8438fd1498Szrj operands beyond the fixed part of the node structure.
8538fd1498Szrj Not used for types or decls. */
8638fd1498Szrj
8738fd1498Szrj #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
8838fd1498Szrj #define END_OF_BASE_TREE_CODES 0,
8938fd1498Szrj
9038fd1498Szrj const unsigned char tree_code_length[] = {
9138fd1498Szrj #include "all-tree.def"
9238fd1498Szrj };
9338fd1498Szrj
9438fd1498Szrj #undef DEFTREECODE
9538fd1498Szrj #undef END_OF_BASE_TREE_CODES
9638fd1498Szrj
9738fd1498Szrj /* Names of tree components.
9838fd1498Szrj Used for printing out the tree and error messages. */
9938fd1498Szrj #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
10038fd1498Szrj #define END_OF_BASE_TREE_CODES "@dummy",
10138fd1498Szrj
10238fd1498Szrj static const char *const tree_code_name[] = {
10338fd1498Szrj #include "all-tree.def"
10438fd1498Szrj };
10538fd1498Szrj
10638fd1498Szrj #undef DEFTREECODE
10738fd1498Szrj #undef END_OF_BASE_TREE_CODES
10838fd1498Szrj
10938fd1498Szrj /* Each tree code class has an associated string representation.
11038fd1498Szrj These must correspond to the tree_code_class entries. */
11138fd1498Szrj
11238fd1498Szrj const char *const tree_code_class_strings[] =
11338fd1498Szrj {
11438fd1498Szrj "exceptional",
11538fd1498Szrj "constant",
11638fd1498Szrj "type",
11738fd1498Szrj "declaration",
11838fd1498Szrj "reference",
11938fd1498Szrj "comparison",
12038fd1498Szrj "unary",
12138fd1498Szrj "binary",
12238fd1498Szrj "statement",
12338fd1498Szrj "vl_exp",
12438fd1498Szrj "expression"
12538fd1498Szrj };
12638fd1498Szrj
12738fd1498Szrj /* obstack.[ch] explicitly declined to prototype this. */
12838fd1498Szrj extern int _obstack_allocated_p (struct obstack *h, void *obj);
12938fd1498Szrj
13038fd1498Szrj /* Statistics-gathering stuff. */
13138fd1498Szrj
13238fd1498Szrj static uint64_t tree_code_counts[MAX_TREE_CODES];
13338fd1498Szrj uint64_t tree_node_counts[(int) all_kinds];
13438fd1498Szrj uint64_t tree_node_sizes[(int) all_kinds];
13538fd1498Szrj
13638fd1498Szrj /* Keep in sync with tree.h:enum tree_node_kind. */
13738fd1498Szrj static const char * const tree_node_kind_names[] = {
13838fd1498Szrj "decls",
13938fd1498Szrj "types",
14038fd1498Szrj "blocks",
14138fd1498Szrj "stmts",
14238fd1498Szrj "refs",
14338fd1498Szrj "exprs",
14438fd1498Szrj "constants",
14538fd1498Szrj "identifiers",
14638fd1498Szrj "vecs",
14738fd1498Szrj "binfos",
14838fd1498Szrj "ssa names",
14938fd1498Szrj "constructors",
15038fd1498Szrj "random kinds",
15138fd1498Szrj "lang_decl kinds",
15238fd1498Szrj "lang_type kinds",
15338fd1498Szrj "omp clauses",
15438fd1498Szrj };
15538fd1498Szrj
15638fd1498Szrj /* Unique id for next decl created. */
15738fd1498Szrj static GTY(()) int next_decl_uid;
15838fd1498Szrj /* Unique id for next type created. */
15938fd1498Szrj static GTY(()) unsigned next_type_uid = 1;
16038fd1498Szrj /* Unique id for next debug decl created. Use negative numbers,
16138fd1498Szrj to catch erroneous uses. */
16238fd1498Szrj static GTY(()) int next_debug_decl_uid;
16338fd1498Szrj
16438fd1498Szrj /* Since we cannot rehash a type after it is in the table, we have to
16538fd1498Szrj keep the hash code. */
16638fd1498Szrj
16738fd1498Szrj struct GTY((for_user)) type_hash {
16838fd1498Szrj unsigned long hash;
16938fd1498Szrj tree type;
17038fd1498Szrj };
17138fd1498Szrj
17238fd1498Szrj /* Initial size of the hash table (rounded to next prime). */
17338fd1498Szrj #define TYPE_HASH_INITIAL_SIZE 1000
17438fd1498Szrj
17538fd1498Szrj struct type_cache_hasher : ggc_cache_ptr_hash<type_hash>
17638fd1498Szrj {
hashtype_cache_hasher17738fd1498Szrj static hashval_t hash (type_hash *t) { return t->hash; }
17838fd1498Szrj static bool equal (type_hash *a, type_hash *b);
17938fd1498Szrj
18038fd1498Szrj static int
keep_cache_entrytype_cache_hasher18138fd1498Szrj keep_cache_entry (type_hash *&t)
18238fd1498Szrj {
18338fd1498Szrj return ggc_marked_p (t->type);
18438fd1498Szrj }
18538fd1498Szrj };
18638fd1498Szrj
18738fd1498Szrj /* Now here is the hash table. When recording a type, it is added to
18838fd1498Szrj the slot whose index is the hash code. Note that the hash table is
18938fd1498Szrj used for several kinds of types (function types, array types and
19038fd1498Szrj array index range types, for now). While all these live in the
19138fd1498Szrj same table, they are completely independent, and the hash code is
19238fd1498Szrj computed differently for each of these. */
19338fd1498Szrj
19438fd1498Szrj static GTY ((cache)) hash_table<type_cache_hasher> *type_hash_table;
19538fd1498Szrj
19638fd1498Szrj /* Hash table and temporary node for larger integer const values. */
19738fd1498Szrj static GTY (()) tree int_cst_node;
19838fd1498Szrj
19938fd1498Szrj struct int_cst_hasher : ggc_cache_ptr_hash<tree_node>
20038fd1498Szrj {
20138fd1498Szrj static hashval_t hash (tree t);
20238fd1498Szrj static bool equal (tree x, tree y);
20338fd1498Szrj };
20438fd1498Szrj
20538fd1498Szrj static GTY ((cache)) hash_table<int_cst_hasher> *int_cst_hash_table;
20638fd1498Szrj
20738fd1498Szrj /* Class and variable for making sure that there is a single POLY_INT_CST
20838fd1498Szrj for a given value. */
20938fd1498Szrj struct poly_int_cst_hasher : ggc_cache_ptr_hash<tree_node>
21038fd1498Szrj {
21138fd1498Szrj typedef std::pair<tree, const poly_wide_int *> compare_type;
21238fd1498Szrj static hashval_t hash (tree t);
21338fd1498Szrj static bool equal (tree x, const compare_type &y);
21438fd1498Szrj };
21538fd1498Szrj
21638fd1498Szrj static GTY ((cache)) hash_table<poly_int_cst_hasher> *poly_int_cst_hash_table;
21738fd1498Szrj
21838fd1498Szrj /* Hash table for optimization flags and target option flags. Use the same
21938fd1498Szrj hash table for both sets of options. Nodes for building the current
22038fd1498Szrj optimization and target option nodes. The assumption is most of the time
22138fd1498Szrj the options created will already be in the hash table, so we avoid
22238fd1498Szrj allocating and freeing up a node repeatably. */
22338fd1498Szrj static GTY (()) tree cl_optimization_node;
22438fd1498Szrj static GTY (()) tree cl_target_option_node;
22538fd1498Szrj
22638fd1498Szrj struct cl_option_hasher : ggc_cache_ptr_hash<tree_node>
22738fd1498Szrj {
22838fd1498Szrj static hashval_t hash (tree t);
22938fd1498Szrj static bool equal (tree x, tree y);
23038fd1498Szrj };
23138fd1498Szrj
23238fd1498Szrj static GTY ((cache)) hash_table<cl_option_hasher> *cl_option_hash_table;
23338fd1498Szrj
23438fd1498Szrj /* General tree->tree mapping structure for use in hash tables. */
23538fd1498Szrj
23638fd1498Szrj
23738fd1498Szrj static GTY ((cache))
23838fd1498Szrj hash_table<tree_decl_map_cache_hasher> *debug_expr_for_decl;
23938fd1498Szrj
24038fd1498Szrj static GTY ((cache))
24138fd1498Szrj hash_table<tree_decl_map_cache_hasher> *value_expr_for_decl;
24238fd1498Szrj
24338fd1498Szrj struct tree_vec_map_cache_hasher : ggc_cache_ptr_hash<tree_vec_map>
24438fd1498Szrj {
hashtree_vec_map_cache_hasher24538fd1498Szrj static hashval_t hash (tree_vec_map *m) { return DECL_UID (m->base.from); }
24638fd1498Szrj
24738fd1498Szrj static bool
equaltree_vec_map_cache_hasher24838fd1498Szrj equal (tree_vec_map *a, tree_vec_map *b)
24938fd1498Szrj {
25038fd1498Szrj return a->base.from == b->base.from;
25138fd1498Szrj }
25238fd1498Szrj
25338fd1498Szrj static int
keep_cache_entrytree_vec_map_cache_hasher25438fd1498Szrj keep_cache_entry (tree_vec_map *&m)
25538fd1498Szrj {
25638fd1498Szrj return ggc_marked_p (m->base.from);
25738fd1498Szrj }
25838fd1498Szrj };
25938fd1498Szrj
26038fd1498Szrj static GTY ((cache))
26138fd1498Szrj hash_table<tree_vec_map_cache_hasher> *debug_args_for_decl;
26238fd1498Szrj
26338fd1498Szrj static void set_type_quals (tree, int);
26438fd1498Szrj static void print_type_hash_statistics (void);
26538fd1498Szrj static void print_debug_expr_statistics (void);
26638fd1498Szrj static void print_value_expr_statistics (void);
26738fd1498Szrj
26838fd1498Szrj tree global_trees[TI_MAX];
26938fd1498Szrj tree integer_types[itk_none];
27038fd1498Szrj
27138fd1498Szrj bool int_n_enabled_p[NUM_INT_N_ENTS];
27238fd1498Szrj struct int_n_trees_t int_n_trees [NUM_INT_N_ENTS];
27338fd1498Szrj
27438fd1498Szrj bool tree_contains_struct[MAX_TREE_CODES][64];
27538fd1498Szrj
27638fd1498Szrj /* Number of operands for each OpenMP clause. */
27738fd1498Szrj unsigned const char omp_clause_num_ops[] =
27838fd1498Szrj {
27938fd1498Szrj 0, /* OMP_CLAUSE_ERROR */
28038fd1498Szrj 1, /* OMP_CLAUSE_PRIVATE */
28138fd1498Szrj 1, /* OMP_CLAUSE_SHARED */
28238fd1498Szrj 1, /* OMP_CLAUSE_FIRSTPRIVATE */
28338fd1498Szrj 2, /* OMP_CLAUSE_LASTPRIVATE */
28438fd1498Szrj 5, /* OMP_CLAUSE_REDUCTION */
28538fd1498Szrj 1, /* OMP_CLAUSE_COPYIN */
28638fd1498Szrj 1, /* OMP_CLAUSE_COPYPRIVATE */
28738fd1498Szrj 3, /* OMP_CLAUSE_LINEAR */
28838fd1498Szrj 2, /* OMP_CLAUSE_ALIGNED */
28938fd1498Szrj 1, /* OMP_CLAUSE_DEPEND */
29038fd1498Szrj 1, /* OMP_CLAUSE_UNIFORM */
29138fd1498Szrj 1, /* OMP_CLAUSE_TO_DECLARE */
29238fd1498Szrj 1, /* OMP_CLAUSE_LINK */
29338fd1498Szrj 2, /* OMP_CLAUSE_FROM */
29438fd1498Szrj 2, /* OMP_CLAUSE_TO */
29538fd1498Szrj 2, /* OMP_CLAUSE_MAP */
29638fd1498Szrj 1, /* OMP_CLAUSE_USE_DEVICE_PTR */
29738fd1498Szrj 1, /* OMP_CLAUSE_IS_DEVICE_PTR */
29838fd1498Szrj 2, /* OMP_CLAUSE__CACHE_ */
29938fd1498Szrj 2, /* OMP_CLAUSE_GANG */
30038fd1498Szrj 1, /* OMP_CLAUSE_ASYNC */
30138fd1498Szrj 1, /* OMP_CLAUSE_WAIT */
30238fd1498Szrj 0, /* OMP_CLAUSE_AUTO */
30338fd1498Szrj 0, /* OMP_CLAUSE_SEQ */
30438fd1498Szrj 1, /* OMP_CLAUSE__LOOPTEMP_ */
30538fd1498Szrj 1, /* OMP_CLAUSE_IF */
30638fd1498Szrj 1, /* OMP_CLAUSE_NUM_THREADS */
30738fd1498Szrj 1, /* OMP_CLAUSE_SCHEDULE */
30838fd1498Szrj 0, /* OMP_CLAUSE_NOWAIT */
30938fd1498Szrj 1, /* OMP_CLAUSE_ORDERED */
31038fd1498Szrj 0, /* OMP_CLAUSE_DEFAULT */
31138fd1498Szrj 3, /* OMP_CLAUSE_COLLAPSE */
31238fd1498Szrj 0, /* OMP_CLAUSE_UNTIED */
31338fd1498Szrj 1, /* OMP_CLAUSE_FINAL */
31438fd1498Szrj 0, /* OMP_CLAUSE_MERGEABLE */
31538fd1498Szrj 1, /* OMP_CLAUSE_DEVICE */
31638fd1498Szrj 1, /* OMP_CLAUSE_DIST_SCHEDULE */
31738fd1498Szrj 0, /* OMP_CLAUSE_INBRANCH */
31838fd1498Szrj 0, /* OMP_CLAUSE_NOTINBRANCH */
31938fd1498Szrj 1, /* OMP_CLAUSE_NUM_TEAMS */
32038fd1498Szrj 1, /* OMP_CLAUSE_THREAD_LIMIT */
32138fd1498Szrj 0, /* OMP_CLAUSE_PROC_BIND */
32238fd1498Szrj 1, /* OMP_CLAUSE_SAFELEN */
32338fd1498Szrj 1, /* OMP_CLAUSE_SIMDLEN */
32438fd1498Szrj 0, /* OMP_CLAUSE_FOR */
32538fd1498Szrj 0, /* OMP_CLAUSE_PARALLEL */
32638fd1498Szrj 0, /* OMP_CLAUSE_SECTIONS */
32738fd1498Szrj 0, /* OMP_CLAUSE_TASKGROUP */
32838fd1498Szrj 1, /* OMP_CLAUSE_PRIORITY */
32938fd1498Szrj 1, /* OMP_CLAUSE_GRAINSIZE */
33038fd1498Szrj 1, /* OMP_CLAUSE_NUM_TASKS */
33138fd1498Szrj 0, /* OMP_CLAUSE_NOGROUP */
33238fd1498Szrj 0, /* OMP_CLAUSE_THREADS */
33338fd1498Szrj 0, /* OMP_CLAUSE_SIMD */
33438fd1498Szrj 1, /* OMP_CLAUSE_HINT */
33538fd1498Szrj 0, /* OMP_CLAUSE_DEFALTMAP */
33638fd1498Szrj 1, /* OMP_CLAUSE__SIMDUID_ */
33738fd1498Szrj 0, /* OMP_CLAUSE__SIMT_ */
33838fd1498Szrj 0, /* OMP_CLAUSE_INDEPENDENT */
33938fd1498Szrj 1, /* OMP_CLAUSE_WORKER */
34038fd1498Szrj 1, /* OMP_CLAUSE_VECTOR */
34138fd1498Szrj 1, /* OMP_CLAUSE_NUM_GANGS */
34238fd1498Szrj 1, /* OMP_CLAUSE_NUM_WORKERS */
34338fd1498Szrj 1, /* OMP_CLAUSE_VECTOR_LENGTH */
34438fd1498Szrj 3, /* OMP_CLAUSE_TILE */
34538fd1498Szrj 2, /* OMP_CLAUSE__GRIDDIM_ */
34638fd1498Szrj };
34738fd1498Szrj
34838fd1498Szrj const char * const omp_clause_code_name[] =
34938fd1498Szrj {
35038fd1498Szrj "error_clause",
35138fd1498Szrj "private",
35238fd1498Szrj "shared",
35338fd1498Szrj "firstprivate",
35438fd1498Szrj "lastprivate",
35538fd1498Szrj "reduction",
35638fd1498Szrj "copyin",
35738fd1498Szrj "copyprivate",
35838fd1498Szrj "linear",
35938fd1498Szrj "aligned",
36038fd1498Szrj "depend",
36138fd1498Szrj "uniform",
36238fd1498Szrj "to",
36338fd1498Szrj "link",
36438fd1498Szrj "from",
36538fd1498Szrj "to",
36638fd1498Szrj "map",
36738fd1498Szrj "use_device_ptr",
36838fd1498Szrj "is_device_ptr",
36938fd1498Szrj "_cache_",
37038fd1498Szrj "gang",
37138fd1498Szrj "async",
37238fd1498Szrj "wait",
37338fd1498Szrj "auto",
37438fd1498Szrj "seq",
37538fd1498Szrj "_looptemp_",
37638fd1498Szrj "if",
37738fd1498Szrj "num_threads",
37838fd1498Szrj "schedule",
37938fd1498Szrj "nowait",
38038fd1498Szrj "ordered",
38138fd1498Szrj "default",
38238fd1498Szrj "collapse",
38338fd1498Szrj "untied",
38438fd1498Szrj "final",
38538fd1498Szrj "mergeable",
38638fd1498Szrj "device",
38738fd1498Szrj "dist_schedule",
38838fd1498Szrj "inbranch",
38938fd1498Szrj "notinbranch",
39038fd1498Szrj "num_teams",
39138fd1498Szrj "thread_limit",
39238fd1498Szrj "proc_bind",
39338fd1498Szrj "safelen",
39438fd1498Szrj "simdlen",
39538fd1498Szrj "for",
39638fd1498Szrj "parallel",
39738fd1498Szrj "sections",
39838fd1498Szrj "taskgroup",
39938fd1498Szrj "priority",
40038fd1498Szrj "grainsize",
40138fd1498Szrj "num_tasks",
40238fd1498Szrj "nogroup",
40338fd1498Szrj "threads",
40438fd1498Szrj "simd",
40538fd1498Szrj "hint",
40638fd1498Szrj "defaultmap",
40738fd1498Szrj "_simduid_",
40838fd1498Szrj "_simt_",
40938fd1498Szrj "independent",
41038fd1498Szrj "worker",
41138fd1498Szrj "vector",
41238fd1498Szrj "num_gangs",
41338fd1498Szrj "num_workers",
41438fd1498Szrj "vector_length",
41538fd1498Szrj "tile",
41638fd1498Szrj "_griddim_"
41738fd1498Szrj };
41838fd1498Szrj
41938fd1498Szrj
42038fd1498Szrj /* Return the tree node structure used by tree code CODE. */
42138fd1498Szrj
42238fd1498Szrj static inline enum tree_node_structure_enum
tree_node_structure_for_code(enum tree_code code)42338fd1498Szrj tree_node_structure_for_code (enum tree_code code)
42438fd1498Szrj {
42538fd1498Szrj switch (TREE_CODE_CLASS (code))
42638fd1498Szrj {
42738fd1498Szrj case tcc_declaration:
42838fd1498Szrj {
42938fd1498Szrj switch (code)
43038fd1498Szrj {
43138fd1498Szrj case FIELD_DECL:
43238fd1498Szrj return TS_FIELD_DECL;
43338fd1498Szrj case PARM_DECL:
43438fd1498Szrj return TS_PARM_DECL;
43538fd1498Szrj case VAR_DECL:
43638fd1498Szrj return TS_VAR_DECL;
43738fd1498Szrj case LABEL_DECL:
43838fd1498Szrj return TS_LABEL_DECL;
43938fd1498Szrj case RESULT_DECL:
44038fd1498Szrj return TS_RESULT_DECL;
44138fd1498Szrj case DEBUG_EXPR_DECL:
44238fd1498Szrj return TS_DECL_WRTL;
44338fd1498Szrj case CONST_DECL:
44438fd1498Szrj return TS_CONST_DECL;
44538fd1498Szrj case TYPE_DECL:
44638fd1498Szrj return TS_TYPE_DECL;
44738fd1498Szrj case FUNCTION_DECL:
44838fd1498Szrj return TS_FUNCTION_DECL;
44938fd1498Szrj case TRANSLATION_UNIT_DECL:
45038fd1498Szrj return TS_TRANSLATION_UNIT_DECL;
45138fd1498Szrj default:
45238fd1498Szrj return TS_DECL_NON_COMMON;
45338fd1498Szrj }
45438fd1498Szrj }
45538fd1498Szrj case tcc_type:
45638fd1498Szrj return TS_TYPE_NON_COMMON;
45738fd1498Szrj case tcc_reference:
45838fd1498Szrj case tcc_comparison:
45938fd1498Szrj case tcc_unary:
46038fd1498Szrj case tcc_binary:
46138fd1498Szrj case tcc_expression:
46238fd1498Szrj case tcc_statement:
46338fd1498Szrj case tcc_vl_exp:
46438fd1498Szrj return TS_EXP;
46538fd1498Szrj default: /* tcc_constant and tcc_exceptional */
46638fd1498Szrj break;
46738fd1498Szrj }
46838fd1498Szrj switch (code)
46938fd1498Szrj {
47038fd1498Szrj /* tcc_constant cases. */
47138fd1498Szrj case VOID_CST: return TS_TYPED;
47238fd1498Szrj case INTEGER_CST: return TS_INT_CST;
47338fd1498Szrj case POLY_INT_CST: return TS_POLY_INT_CST;
47438fd1498Szrj case REAL_CST: return TS_REAL_CST;
47538fd1498Szrj case FIXED_CST: return TS_FIXED_CST;
47638fd1498Szrj case COMPLEX_CST: return TS_COMPLEX;
47738fd1498Szrj case VECTOR_CST: return TS_VECTOR;
47838fd1498Szrj case STRING_CST: return TS_STRING;
47938fd1498Szrj /* tcc_exceptional cases. */
48038fd1498Szrj case ERROR_MARK: return TS_COMMON;
48138fd1498Szrj case IDENTIFIER_NODE: return TS_IDENTIFIER;
48238fd1498Szrj case TREE_LIST: return TS_LIST;
48338fd1498Szrj case TREE_VEC: return TS_VEC;
48438fd1498Szrj case SSA_NAME: return TS_SSA_NAME;
48538fd1498Szrj case PLACEHOLDER_EXPR: return TS_COMMON;
48638fd1498Szrj case STATEMENT_LIST: return TS_STATEMENT_LIST;
48738fd1498Szrj case BLOCK: return TS_BLOCK;
48838fd1498Szrj case CONSTRUCTOR: return TS_CONSTRUCTOR;
48938fd1498Szrj case TREE_BINFO: return TS_BINFO;
49038fd1498Szrj case OMP_CLAUSE: return TS_OMP_CLAUSE;
49138fd1498Szrj case OPTIMIZATION_NODE: return TS_OPTIMIZATION;
49238fd1498Szrj case TARGET_OPTION_NODE: return TS_TARGET_OPTION;
49338fd1498Szrj
49438fd1498Szrj default:
49538fd1498Szrj gcc_unreachable ();
49638fd1498Szrj }
49738fd1498Szrj }
49838fd1498Szrj
49938fd1498Szrj
50038fd1498Szrj /* Initialize tree_contains_struct to describe the hierarchy of tree
50138fd1498Szrj nodes. */
50238fd1498Szrj
50338fd1498Szrj static void
initialize_tree_contains_struct(void)50438fd1498Szrj initialize_tree_contains_struct (void)
50538fd1498Szrj {
50638fd1498Szrj unsigned i;
50738fd1498Szrj
50838fd1498Szrj for (i = ERROR_MARK; i < LAST_AND_UNUSED_TREE_CODE; i++)
50938fd1498Szrj {
51038fd1498Szrj enum tree_code code;
51138fd1498Szrj enum tree_node_structure_enum ts_code;
51238fd1498Szrj
51338fd1498Szrj code = (enum tree_code) i;
51438fd1498Szrj ts_code = tree_node_structure_for_code (code);
51538fd1498Szrj
51638fd1498Szrj /* Mark the TS structure itself. */
51738fd1498Szrj tree_contains_struct[code][ts_code] = 1;
51838fd1498Szrj
51938fd1498Szrj /* Mark all the structures that TS is derived from. */
52038fd1498Szrj switch (ts_code)
52138fd1498Szrj {
52238fd1498Szrj case TS_TYPED:
52338fd1498Szrj case TS_BLOCK:
52438fd1498Szrj case TS_OPTIMIZATION:
52538fd1498Szrj case TS_TARGET_OPTION:
52638fd1498Szrj MARK_TS_BASE (code);
52738fd1498Szrj break;
52838fd1498Szrj
52938fd1498Szrj case TS_COMMON:
53038fd1498Szrj case TS_INT_CST:
53138fd1498Szrj case TS_POLY_INT_CST:
53238fd1498Szrj case TS_REAL_CST:
53338fd1498Szrj case TS_FIXED_CST:
53438fd1498Szrj case TS_VECTOR:
53538fd1498Szrj case TS_STRING:
53638fd1498Szrj case TS_COMPLEX:
53738fd1498Szrj case TS_SSA_NAME:
53838fd1498Szrj case TS_CONSTRUCTOR:
53938fd1498Szrj case TS_EXP:
54038fd1498Szrj case TS_STATEMENT_LIST:
54138fd1498Szrj MARK_TS_TYPED (code);
54238fd1498Szrj break;
54338fd1498Szrj
54438fd1498Szrj case TS_IDENTIFIER:
54538fd1498Szrj case TS_DECL_MINIMAL:
54638fd1498Szrj case TS_TYPE_COMMON:
54738fd1498Szrj case TS_LIST:
54838fd1498Szrj case TS_VEC:
54938fd1498Szrj case TS_BINFO:
55038fd1498Szrj case TS_OMP_CLAUSE:
55138fd1498Szrj MARK_TS_COMMON (code);
55238fd1498Szrj break;
55338fd1498Szrj
55438fd1498Szrj case TS_TYPE_WITH_LANG_SPECIFIC:
55538fd1498Szrj MARK_TS_TYPE_COMMON (code);
55638fd1498Szrj break;
55738fd1498Szrj
55838fd1498Szrj case TS_TYPE_NON_COMMON:
55938fd1498Szrj MARK_TS_TYPE_WITH_LANG_SPECIFIC (code);
56038fd1498Szrj break;
56138fd1498Szrj
56238fd1498Szrj case TS_DECL_COMMON:
56338fd1498Szrj MARK_TS_DECL_MINIMAL (code);
56438fd1498Szrj break;
56538fd1498Szrj
56638fd1498Szrj case TS_DECL_WRTL:
56738fd1498Szrj case TS_CONST_DECL:
56838fd1498Szrj MARK_TS_DECL_COMMON (code);
56938fd1498Szrj break;
57038fd1498Szrj
57138fd1498Szrj case TS_DECL_NON_COMMON:
57238fd1498Szrj MARK_TS_DECL_WITH_VIS (code);
57338fd1498Szrj break;
57438fd1498Szrj
57538fd1498Szrj case TS_DECL_WITH_VIS:
57638fd1498Szrj case TS_PARM_DECL:
57738fd1498Szrj case TS_LABEL_DECL:
57838fd1498Szrj case TS_RESULT_DECL:
57938fd1498Szrj MARK_TS_DECL_WRTL (code);
58038fd1498Szrj break;
58138fd1498Szrj
58238fd1498Szrj case TS_FIELD_DECL:
58338fd1498Szrj MARK_TS_DECL_COMMON (code);
58438fd1498Szrj break;
58538fd1498Szrj
58638fd1498Szrj case TS_VAR_DECL:
58738fd1498Szrj MARK_TS_DECL_WITH_VIS (code);
58838fd1498Szrj break;
58938fd1498Szrj
59038fd1498Szrj case TS_TYPE_DECL:
59138fd1498Szrj case TS_FUNCTION_DECL:
59238fd1498Szrj MARK_TS_DECL_NON_COMMON (code);
59338fd1498Szrj break;
59438fd1498Szrj
59538fd1498Szrj case TS_TRANSLATION_UNIT_DECL:
59638fd1498Szrj MARK_TS_DECL_COMMON (code);
59738fd1498Szrj break;
59838fd1498Szrj
59938fd1498Szrj default:
60038fd1498Szrj gcc_unreachable ();
60138fd1498Szrj }
60238fd1498Szrj }
60338fd1498Szrj
60438fd1498Szrj /* Basic consistency checks for attributes used in fold. */
60538fd1498Szrj gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON]);
60638fd1498Szrj gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON]);
60738fd1498Szrj gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_COMMON]);
60838fd1498Szrj gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_COMMON]);
60938fd1498Szrj gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_COMMON]);
61038fd1498Szrj gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_COMMON]);
61138fd1498Szrj gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_COMMON]);
61238fd1498Szrj gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_COMMON]);
61338fd1498Szrj gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_COMMON]);
61438fd1498Szrj gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_COMMON]);
61538fd1498Szrj gcc_assert (tree_contains_struct[FIELD_DECL][TS_DECL_COMMON]);
61638fd1498Szrj gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_WRTL]);
61738fd1498Szrj gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_WRTL]);
61838fd1498Szrj gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_WRTL]);
61938fd1498Szrj gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_WRTL]);
62038fd1498Szrj gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_WRTL]);
62138fd1498Szrj gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_MINIMAL]);
62238fd1498Szrj gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_MINIMAL]);
62338fd1498Szrj gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_MINIMAL]);
62438fd1498Szrj gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_MINIMAL]);
62538fd1498Szrj gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_MINIMAL]);
62638fd1498Szrj gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_MINIMAL]);
62738fd1498Szrj gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_MINIMAL]);
62838fd1498Szrj gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_MINIMAL]);
62938fd1498Szrj gcc_assert (tree_contains_struct[FIELD_DECL][TS_DECL_MINIMAL]);
63038fd1498Szrj gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS]);
63138fd1498Szrj gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS]);
63238fd1498Szrj gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_WITH_VIS]);
63338fd1498Szrj gcc_assert (tree_contains_struct[VAR_DECL][TS_VAR_DECL]);
63438fd1498Szrj gcc_assert (tree_contains_struct[FIELD_DECL][TS_FIELD_DECL]);
63538fd1498Szrj gcc_assert (tree_contains_struct[PARM_DECL][TS_PARM_DECL]);
63638fd1498Szrj gcc_assert (tree_contains_struct[LABEL_DECL][TS_LABEL_DECL]);
63738fd1498Szrj gcc_assert (tree_contains_struct[RESULT_DECL][TS_RESULT_DECL]);
63838fd1498Szrj gcc_assert (tree_contains_struct[CONST_DECL][TS_CONST_DECL]);
63938fd1498Szrj gcc_assert (tree_contains_struct[TYPE_DECL][TS_TYPE_DECL]);
64038fd1498Szrj gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL]);
64138fd1498Szrj gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL]);
64238fd1498Szrj gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON]);
64338fd1498Szrj gcc_assert (tree_contains_struct[NAMELIST_DECL][TS_DECL_MINIMAL]);
64438fd1498Szrj gcc_assert (tree_contains_struct[NAMELIST_DECL][TS_DECL_COMMON]);
64538fd1498Szrj }
64638fd1498Szrj
64738fd1498Szrj
64838fd1498Szrj /* Init tree.c. */
64938fd1498Szrj
65038fd1498Szrj void
init_ttree(void)65138fd1498Szrj init_ttree (void)
65238fd1498Szrj {
65338fd1498Szrj /* Initialize the hash table of types. */
65438fd1498Szrj type_hash_table
65538fd1498Szrj = hash_table<type_cache_hasher>::create_ggc (TYPE_HASH_INITIAL_SIZE);
65638fd1498Szrj
65738fd1498Szrj debug_expr_for_decl
65838fd1498Szrj = hash_table<tree_decl_map_cache_hasher>::create_ggc (512);
65938fd1498Szrj
66038fd1498Szrj value_expr_for_decl
66138fd1498Szrj = hash_table<tree_decl_map_cache_hasher>::create_ggc (512);
66238fd1498Szrj
66338fd1498Szrj int_cst_hash_table = hash_table<int_cst_hasher>::create_ggc (1024);
66438fd1498Szrj
66538fd1498Szrj poly_int_cst_hash_table = hash_table<poly_int_cst_hasher>::create_ggc (64);
66638fd1498Szrj
66738fd1498Szrj int_cst_node = make_int_cst (1, 1);
66838fd1498Szrj
66938fd1498Szrj cl_option_hash_table = hash_table<cl_option_hasher>::create_ggc (64);
67038fd1498Szrj
67138fd1498Szrj cl_optimization_node = make_node (OPTIMIZATION_NODE);
67238fd1498Szrj cl_target_option_node = make_node (TARGET_OPTION_NODE);
67338fd1498Szrj
67438fd1498Szrj /* Initialize the tree_contains_struct array. */
67538fd1498Szrj initialize_tree_contains_struct ();
67638fd1498Szrj lang_hooks.init_ts ();
67738fd1498Szrj }
67838fd1498Szrj
67938fd1498Szrj
68038fd1498Szrj /* The name of the object as the assembler will see it (but before any
68138fd1498Szrj translations made by ASM_OUTPUT_LABELREF). Often this is the same
68238fd1498Szrj as DECL_NAME. It is an IDENTIFIER_NODE. */
68338fd1498Szrj tree
decl_assembler_name(tree decl)68438fd1498Szrj decl_assembler_name (tree decl)
68538fd1498Szrj {
68638fd1498Szrj if (!DECL_ASSEMBLER_NAME_SET_P (decl))
68738fd1498Szrj lang_hooks.set_decl_assembler_name (decl);
68838fd1498Szrj return DECL_ASSEMBLER_NAME_RAW (decl);
68938fd1498Szrj }
69038fd1498Szrj
69138fd1498Szrj /* The DECL_ASSEMBLER_NAME_RAW of DECL is being explicitly set to NAME
69238fd1498Szrj (either of which may be NULL). Inform the FE, if this changes the
69338fd1498Szrj name. */
69438fd1498Szrj
69538fd1498Szrj void
overwrite_decl_assembler_name(tree decl,tree name)69638fd1498Szrj overwrite_decl_assembler_name (tree decl, tree name)
69738fd1498Szrj {
69838fd1498Szrj if (DECL_ASSEMBLER_NAME_RAW (decl) != name)
69938fd1498Szrj lang_hooks.overwrite_decl_assembler_name (decl, name);
70038fd1498Szrj }
70138fd1498Szrj
70238fd1498Szrj /* When the target supports COMDAT groups, this indicates which group the
70338fd1498Szrj DECL is associated with. This can be either an IDENTIFIER_NODE or a
70438fd1498Szrj decl, in which case its DECL_ASSEMBLER_NAME identifies the group. */
70538fd1498Szrj tree
decl_comdat_group(const_tree node)70638fd1498Szrj decl_comdat_group (const_tree node)
70738fd1498Szrj {
70838fd1498Szrj struct symtab_node *snode = symtab_node::get (node);
70938fd1498Szrj if (!snode)
71038fd1498Szrj return NULL;
71138fd1498Szrj return snode->get_comdat_group ();
71238fd1498Szrj }
71338fd1498Szrj
71438fd1498Szrj /* Likewise, but make sure it's been reduced to an IDENTIFIER_NODE. */
71538fd1498Szrj tree
decl_comdat_group_id(const_tree node)71638fd1498Szrj decl_comdat_group_id (const_tree node)
71738fd1498Szrj {
71838fd1498Szrj struct symtab_node *snode = symtab_node::get (node);
71938fd1498Szrj if (!snode)
72038fd1498Szrj return NULL;
72138fd1498Szrj return snode->get_comdat_group_id ();
72238fd1498Szrj }
72338fd1498Szrj
72438fd1498Szrj /* When the target supports named section, return its name as IDENTIFIER_NODE
72538fd1498Szrj or NULL if it is in no section. */
72638fd1498Szrj const char *
decl_section_name(const_tree node)72738fd1498Szrj decl_section_name (const_tree node)
72838fd1498Szrj {
72938fd1498Szrj struct symtab_node *snode = symtab_node::get (node);
73038fd1498Szrj if (!snode)
73138fd1498Szrj return NULL;
73238fd1498Szrj return snode->get_section ();
73338fd1498Szrj }
73438fd1498Szrj
73538fd1498Szrj /* Set section name of NODE to VALUE (that is expected to be
73638fd1498Szrj identifier node) */
73738fd1498Szrj void
set_decl_section_name(tree node,const char * value)73838fd1498Szrj set_decl_section_name (tree node, const char *value)
73938fd1498Szrj {
74038fd1498Szrj struct symtab_node *snode;
74138fd1498Szrj
74238fd1498Szrj if (value == NULL)
74338fd1498Szrj {
74438fd1498Szrj snode = symtab_node::get (node);
74538fd1498Szrj if (!snode)
74638fd1498Szrj return;
74738fd1498Szrj }
74838fd1498Szrj else if (VAR_P (node))
74938fd1498Szrj snode = varpool_node::get_create (node);
75038fd1498Szrj else
75138fd1498Szrj snode = cgraph_node::get_create (node);
75238fd1498Szrj snode->set_section (value);
75338fd1498Szrj }
75438fd1498Szrj
75538fd1498Szrj /* Return TLS model of a variable NODE. */
75638fd1498Szrj enum tls_model
decl_tls_model(const_tree node)75738fd1498Szrj decl_tls_model (const_tree node)
75838fd1498Szrj {
75938fd1498Szrj struct varpool_node *snode = varpool_node::get (node);
76038fd1498Szrj if (!snode)
76138fd1498Szrj return TLS_MODEL_NONE;
76238fd1498Szrj return snode->tls_model;
76338fd1498Szrj }
76438fd1498Szrj
76538fd1498Szrj /* Set TLS model of variable NODE to MODEL. */
76638fd1498Szrj void
set_decl_tls_model(tree node,enum tls_model model)76738fd1498Szrj set_decl_tls_model (tree node, enum tls_model model)
76838fd1498Szrj {
76938fd1498Szrj struct varpool_node *vnode;
77038fd1498Szrj
77138fd1498Szrj if (model == TLS_MODEL_NONE)
77238fd1498Szrj {
77338fd1498Szrj vnode = varpool_node::get (node);
77438fd1498Szrj if (!vnode)
77538fd1498Szrj return;
77638fd1498Szrj }
77738fd1498Szrj else
77838fd1498Szrj vnode = varpool_node::get_create (node);
77938fd1498Szrj vnode->tls_model = model;
78038fd1498Szrj }
78138fd1498Szrj
78238fd1498Szrj /* Compute the number of bytes occupied by a tree with code CODE.
78338fd1498Szrj This function cannot be used for nodes that have variable sizes,
78438fd1498Szrj including TREE_VEC, INTEGER_CST, STRING_CST, and CALL_EXPR. */
78538fd1498Szrj size_t
tree_code_size(enum tree_code code)78638fd1498Szrj tree_code_size (enum tree_code code)
78738fd1498Szrj {
78838fd1498Szrj switch (TREE_CODE_CLASS (code))
78938fd1498Szrj {
79038fd1498Szrj case tcc_declaration: /* A decl node */
79138fd1498Szrj switch (code)
79238fd1498Szrj {
79338fd1498Szrj case FIELD_DECL: return sizeof (tree_field_decl);
79438fd1498Szrj case PARM_DECL: return sizeof (tree_parm_decl);
79538fd1498Szrj case VAR_DECL: return sizeof (tree_var_decl);
79638fd1498Szrj case LABEL_DECL: return sizeof (tree_label_decl);
79738fd1498Szrj case RESULT_DECL: return sizeof (tree_result_decl);
79838fd1498Szrj case CONST_DECL: return sizeof (tree_const_decl);
79938fd1498Szrj case TYPE_DECL: return sizeof (tree_type_decl);
80038fd1498Szrj case FUNCTION_DECL: return sizeof (tree_function_decl);
80138fd1498Szrj case DEBUG_EXPR_DECL: return sizeof (tree_decl_with_rtl);
80238fd1498Szrj case TRANSLATION_UNIT_DECL: return sizeof (tree_translation_unit_decl);
80338fd1498Szrj case NAMESPACE_DECL:
80438fd1498Szrj case IMPORTED_DECL:
80538fd1498Szrj case NAMELIST_DECL: return sizeof (tree_decl_non_common);
80638fd1498Szrj default:
80738fd1498Szrj gcc_checking_assert (code >= NUM_TREE_CODES);
80838fd1498Szrj return lang_hooks.tree_size (code);
80938fd1498Szrj }
81038fd1498Szrj
81138fd1498Szrj case tcc_type: /* a type node */
81238fd1498Szrj switch (code)
81338fd1498Szrj {
81438fd1498Szrj case OFFSET_TYPE:
81538fd1498Szrj case ENUMERAL_TYPE:
81638fd1498Szrj case BOOLEAN_TYPE:
81738fd1498Szrj case INTEGER_TYPE:
81838fd1498Szrj case REAL_TYPE:
81938fd1498Szrj case POINTER_TYPE:
82038fd1498Szrj case REFERENCE_TYPE:
82138fd1498Szrj case NULLPTR_TYPE:
82238fd1498Szrj case FIXED_POINT_TYPE:
82338fd1498Szrj case COMPLEX_TYPE:
82438fd1498Szrj case VECTOR_TYPE:
82538fd1498Szrj case ARRAY_TYPE:
82638fd1498Szrj case RECORD_TYPE:
82738fd1498Szrj case UNION_TYPE:
82838fd1498Szrj case QUAL_UNION_TYPE:
82938fd1498Szrj case VOID_TYPE:
83038fd1498Szrj case POINTER_BOUNDS_TYPE:
83138fd1498Szrj case FUNCTION_TYPE:
83238fd1498Szrj case METHOD_TYPE:
83338fd1498Szrj case LANG_TYPE: return sizeof (tree_type_non_common);
83438fd1498Szrj default:
83538fd1498Szrj gcc_checking_assert (code >= NUM_TREE_CODES);
83638fd1498Szrj return lang_hooks.tree_size (code);
83738fd1498Szrj }
83838fd1498Szrj
83938fd1498Szrj case tcc_reference: /* a reference */
84038fd1498Szrj case tcc_expression: /* an expression */
84138fd1498Szrj case tcc_statement: /* an expression with side effects */
84238fd1498Szrj case tcc_comparison: /* a comparison expression */
84338fd1498Szrj case tcc_unary: /* a unary arithmetic expression */
84438fd1498Szrj case tcc_binary: /* a binary arithmetic expression */
84538fd1498Szrj return (sizeof (struct tree_exp)
84638fd1498Szrj + (TREE_CODE_LENGTH (code) - 1) * sizeof (tree));
84738fd1498Szrj
84838fd1498Szrj case tcc_constant: /* a constant */
84938fd1498Szrj switch (code)
85038fd1498Szrj {
85138fd1498Szrj case VOID_CST: return sizeof (tree_typed);
85238fd1498Szrj case INTEGER_CST: gcc_unreachable ();
85338fd1498Szrj case POLY_INT_CST: return sizeof (tree_poly_int_cst);
85438fd1498Szrj case REAL_CST: return sizeof (tree_real_cst);
85538fd1498Szrj case FIXED_CST: return sizeof (tree_fixed_cst);
85638fd1498Szrj case COMPLEX_CST: return sizeof (tree_complex);
85738fd1498Szrj case VECTOR_CST: gcc_unreachable ();
85838fd1498Szrj case STRING_CST: gcc_unreachable ();
85938fd1498Szrj default:
86038fd1498Szrj gcc_checking_assert (code >= NUM_TREE_CODES);
86138fd1498Szrj return lang_hooks.tree_size (code);
86238fd1498Szrj }
86338fd1498Szrj
86438fd1498Szrj case tcc_exceptional: /* something random, like an identifier. */
86538fd1498Szrj switch (code)
86638fd1498Szrj {
86738fd1498Szrj case IDENTIFIER_NODE: return lang_hooks.identifier_size;
86838fd1498Szrj case TREE_LIST: return sizeof (tree_list);
86938fd1498Szrj
87038fd1498Szrj case ERROR_MARK:
87138fd1498Szrj case PLACEHOLDER_EXPR: return sizeof (tree_common);
87238fd1498Szrj
87338fd1498Szrj case TREE_VEC: gcc_unreachable ();
87438fd1498Szrj case OMP_CLAUSE: gcc_unreachable ();
87538fd1498Szrj
87638fd1498Szrj case SSA_NAME: return sizeof (tree_ssa_name);
87738fd1498Szrj
87838fd1498Szrj case STATEMENT_LIST: return sizeof (tree_statement_list);
87938fd1498Szrj case BLOCK: return sizeof (struct tree_block);
88038fd1498Szrj case CONSTRUCTOR: return sizeof (tree_constructor);
88138fd1498Szrj case OPTIMIZATION_NODE: return sizeof (tree_optimization_option);
88238fd1498Szrj case TARGET_OPTION_NODE: return sizeof (tree_target_option);
88338fd1498Szrj
88438fd1498Szrj default:
88538fd1498Szrj gcc_checking_assert (code >= NUM_TREE_CODES);
88638fd1498Szrj return lang_hooks.tree_size (code);
88738fd1498Szrj }
88838fd1498Szrj
88938fd1498Szrj default:
89038fd1498Szrj gcc_unreachable ();
89138fd1498Szrj }
89238fd1498Szrj }
89338fd1498Szrj
89438fd1498Szrj /* Compute the number of bytes occupied by NODE. This routine only
89538fd1498Szrj looks at TREE_CODE, except for those nodes that have variable sizes. */
89638fd1498Szrj size_t
tree_size(const_tree node)89738fd1498Szrj tree_size (const_tree node)
89838fd1498Szrj {
89938fd1498Szrj const enum tree_code code = TREE_CODE (node);
90038fd1498Szrj switch (code)
90138fd1498Szrj {
90238fd1498Szrj case INTEGER_CST:
90338fd1498Szrj return (sizeof (struct tree_int_cst)
90438fd1498Szrj + (TREE_INT_CST_EXT_NUNITS (node) - 1) * sizeof (HOST_WIDE_INT));
90538fd1498Szrj
90638fd1498Szrj case TREE_BINFO:
90738fd1498Szrj return (offsetof (struct tree_binfo, base_binfos)
90838fd1498Szrj + vec<tree, va_gc>
90938fd1498Szrj ::embedded_size (BINFO_N_BASE_BINFOS (node)));
91038fd1498Szrj
91138fd1498Szrj case TREE_VEC:
91238fd1498Szrj return (sizeof (struct tree_vec)
91338fd1498Szrj + (TREE_VEC_LENGTH (node) - 1) * sizeof (tree));
91438fd1498Szrj
91538fd1498Szrj case VECTOR_CST:
91638fd1498Szrj return (sizeof (struct tree_vector)
91738fd1498Szrj + (vector_cst_encoded_nelts (node) - 1) * sizeof (tree));
91838fd1498Szrj
91938fd1498Szrj case STRING_CST:
92038fd1498Szrj return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1;
92138fd1498Szrj
92238fd1498Szrj case OMP_CLAUSE:
92338fd1498Szrj return (sizeof (struct tree_omp_clause)
92438fd1498Szrj + (omp_clause_num_ops[OMP_CLAUSE_CODE (node)] - 1)
92538fd1498Szrj * sizeof (tree));
92638fd1498Szrj
92738fd1498Szrj default:
92838fd1498Szrj if (TREE_CODE_CLASS (code) == tcc_vl_exp)
92938fd1498Szrj return (sizeof (struct tree_exp)
93038fd1498Szrj + (VL_EXP_OPERAND_LENGTH (node) - 1) * sizeof (tree));
93138fd1498Szrj else
93238fd1498Szrj return tree_code_size (code);
93338fd1498Szrj }
93438fd1498Szrj }
93538fd1498Szrj
93638fd1498Szrj /* Return tree node kind based on tree CODE. */
93738fd1498Szrj
93838fd1498Szrj static tree_node_kind
get_stats_node_kind(enum tree_code code)93938fd1498Szrj get_stats_node_kind (enum tree_code code)
94038fd1498Szrj {
94138fd1498Szrj enum tree_code_class type = TREE_CODE_CLASS (code);
94238fd1498Szrj
94338fd1498Szrj switch (type)
94438fd1498Szrj {
94538fd1498Szrj case tcc_declaration: /* A decl node */
94638fd1498Szrj return d_kind;
94738fd1498Szrj case tcc_type: /* a type node */
94838fd1498Szrj return t_kind;
94938fd1498Szrj case tcc_statement: /* an expression with side effects */
95038fd1498Szrj return s_kind;
95138fd1498Szrj case tcc_reference: /* a reference */
95238fd1498Szrj return r_kind;
95338fd1498Szrj case tcc_expression: /* an expression */
95438fd1498Szrj case tcc_comparison: /* a comparison expression */
95538fd1498Szrj case tcc_unary: /* a unary arithmetic expression */
95638fd1498Szrj case tcc_binary: /* a binary arithmetic expression */
95738fd1498Szrj return e_kind;
95838fd1498Szrj case tcc_constant: /* a constant */
95938fd1498Szrj return c_kind;
96038fd1498Szrj case tcc_exceptional: /* something random, like an identifier. */
96138fd1498Szrj switch (code)
96238fd1498Szrj {
96338fd1498Szrj case IDENTIFIER_NODE:
96438fd1498Szrj return id_kind;
96538fd1498Szrj case TREE_VEC:
96638fd1498Szrj return vec_kind;
96738fd1498Szrj case TREE_BINFO:
96838fd1498Szrj return binfo_kind;
96938fd1498Szrj case SSA_NAME:
97038fd1498Szrj return ssa_name_kind;
97138fd1498Szrj case BLOCK:
97238fd1498Szrj return b_kind;
97338fd1498Szrj case CONSTRUCTOR:
97438fd1498Szrj return constr_kind;
97538fd1498Szrj case OMP_CLAUSE:
97638fd1498Szrj return omp_clause_kind;
97738fd1498Szrj default:
97838fd1498Szrj return x_kind;
97938fd1498Szrj }
98038fd1498Szrj break;
98138fd1498Szrj case tcc_vl_exp:
98238fd1498Szrj return e_kind;
98338fd1498Szrj default:
98438fd1498Szrj gcc_unreachable ();
98538fd1498Szrj }
98638fd1498Szrj }
98738fd1498Szrj
98838fd1498Szrj /* Record interesting allocation statistics for a tree node with CODE
98938fd1498Szrj and LENGTH. */
99038fd1498Szrj
99138fd1498Szrj static void
record_node_allocation_statistics(enum tree_code code,size_t length)99238fd1498Szrj record_node_allocation_statistics (enum tree_code code, size_t length)
99338fd1498Szrj {
99438fd1498Szrj if (!GATHER_STATISTICS)
99538fd1498Szrj return;
99638fd1498Szrj
99738fd1498Szrj tree_node_kind kind = get_stats_node_kind (code);
99838fd1498Szrj
99938fd1498Szrj tree_code_counts[(int) code]++;
100038fd1498Szrj tree_node_counts[(int) kind]++;
100138fd1498Szrj tree_node_sizes[(int) kind] += length;
100238fd1498Szrj }
100338fd1498Szrj
100438fd1498Szrj /* Allocate and return a new UID from the DECL_UID namespace. */
100538fd1498Szrj
100638fd1498Szrj int
allocate_decl_uid(void)100738fd1498Szrj allocate_decl_uid (void)
100838fd1498Szrj {
100938fd1498Szrj return next_decl_uid++;
101038fd1498Szrj }
101138fd1498Szrj
101238fd1498Szrj /* Return a newly allocated node of code CODE. For decl and type
101338fd1498Szrj nodes, some other fields are initialized. The rest of the node is
101438fd1498Szrj initialized to zero. This function cannot be used for TREE_VEC,
101538fd1498Szrj INTEGER_CST or OMP_CLAUSE nodes, which is enforced by asserts in
101638fd1498Szrj tree_code_size.
101738fd1498Szrj
101838fd1498Szrj Achoo! I got a code in the node. */
101938fd1498Szrj
102038fd1498Szrj tree
make_node(enum tree_code code MEM_STAT_DECL)102138fd1498Szrj make_node (enum tree_code code MEM_STAT_DECL)
102238fd1498Szrj {
102338fd1498Szrj tree t;
102438fd1498Szrj enum tree_code_class type = TREE_CODE_CLASS (code);
102538fd1498Szrj size_t length = tree_code_size (code);
102638fd1498Szrj
102738fd1498Szrj record_node_allocation_statistics (code, length);
102838fd1498Szrj
102938fd1498Szrj t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT);
103038fd1498Szrj TREE_SET_CODE (t, code);
103138fd1498Szrj
103238fd1498Szrj switch (type)
103338fd1498Szrj {
103438fd1498Szrj case tcc_statement:
103538fd1498Szrj if (code != DEBUG_BEGIN_STMT)
103638fd1498Szrj TREE_SIDE_EFFECTS (t) = 1;
103738fd1498Szrj break;
103838fd1498Szrj
103938fd1498Szrj case tcc_declaration:
104038fd1498Szrj if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
104138fd1498Szrj {
104238fd1498Szrj if (code == FUNCTION_DECL)
104338fd1498Szrj {
104438fd1498Szrj SET_DECL_ALIGN (t, FUNCTION_ALIGNMENT (FUNCTION_BOUNDARY));
104538fd1498Szrj SET_DECL_MODE (t, FUNCTION_MODE);
104638fd1498Szrj }
104738fd1498Szrj else
104838fd1498Szrj SET_DECL_ALIGN (t, 1);
104938fd1498Szrj }
105038fd1498Szrj DECL_SOURCE_LOCATION (t) = input_location;
105138fd1498Szrj if (TREE_CODE (t) == DEBUG_EXPR_DECL)
105238fd1498Szrj DECL_UID (t) = --next_debug_decl_uid;
105338fd1498Szrj else
105438fd1498Szrj {
105538fd1498Szrj DECL_UID (t) = allocate_decl_uid ();
105638fd1498Szrj SET_DECL_PT_UID (t, -1);
105738fd1498Szrj }
105838fd1498Szrj if (TREE_CODE (t) == LABEL_DECL)
105938fd1498Szrj LABEL_DECL_UID (t) = -1;
106038fd1498Szrj
106138fd1498Szrj break;
106238fd1498Szrj
106338fd1498Szrj case tcc_type:
106438fd1498Szrj TYPE_UID (t) = next_type_uid++;
106538fd1498Szrj SET_TYPE_ALIGN (t, BITS_PER_UNIT);
106638fd1498Szrj TYPE_USER_ALIGN (t) = 0;
106738fd1498Szrj TYPE_MAIN_VARIANT (t) = t;
106838fd1498Szrj TYPE_CANONICAL (t) = t;
106938fd1498Szrj
107038fd1498Szrj /* Default to no attributes for type, but let target change that. */
107138fd1498Szrj TYPE_ATTRIBUTES (t) = NULL_TREE;
107238fd1498Szrj targetm.set_default_type_attributes (t);
107338fd1498Szrj
107438fd1498Szrj /* We have not yet computed the alias set for this type. */
107538fd1498Szrj TYPE_ALIAS_SET (t) = -1;
107638fd1498Szrj break;
107738fd1498Szrj
107838fd1498Szrj case tcc_constant:
107938fd1498Szrj TREE_CONSTANT (t) = 1;
108038fd1498Szrj break;
108138fd1498Szrj
108238fd1498Szrj case tcc_expression:
108338fd1498Szrj switch (code)
108438fd1498Szrj {
108538fd1498Szrj case INIT_EXPR:
108638fd1498Szrj case MODIFY_EXPR:
108738fd1498Szrj case VA_ARG_EXPR:
108838fd1498Szrj case PREDECREMENT_EXPR:
108938fd1498Szrj case PREINCREMENT_EXPR:
109038fd1498Szrj case POSTDECREMENT_EXPR:
109138fd1498Szrj case POSTINCREMENT_EXPR:
109238fd1498Szrj /* All of these have side-effects, no matter what their
109338fd1498Szrj operands are. */
109438fd1498Szrj TREE_SIDE_EFFECTS (t) = 1;
109538fd1498Szrj break;
109638fd1498Szrj
109738fd1498Szrj default:
109838fd1498Szrj break;
109938fd1498Szrj }
110038fd1498Szrj break;
110138fd1498Szrj
110238fd1498Szrj case tcc_exceptional:
110338fd1498Szrj switch (code)
110438fd1498Szrj {
110538fd1498Szrj case TARGET_OPTION_NODE:
110638fd1498Szrj TREE_TARGET_OPTION(t)
110738fd1498Szrj = ggc_cleared_alloc<struct cl_target_option> ();
110838fd1498Szrj break;
110938fd1498Szrj
111038fd1498Szrj case OPTIMIZATION_NODE:
111138fd1498Szrj TREE_OPTIMIZATION (t)
111238fd1498Szrj = ggc_cleared_alloc<struct cl_optimization> ();
111338fd1498Szrj break;
111438fd1498Szrj
111538fd1498Szrj default:
111638fd1498Szrj break;
111738fd1498Szrj }
111838fd1498Szrj break;
111938fd1498Szrj
112038fd1498Szrj default:
112138fd1498Szrj /* Other classes need no special treatment. */
112238fd1498Szrj break;
112338fd1498Szrj }
112438fd1498Szrj
112538fd1498Szrj return t;
112638fd1498Szrj }
112738fd1498Szrj
112838fd1498Szrj /* Free tree node. */
112938fd1498Szrj
113038fd1498Szrj void
free_node(tree node)113138fd1498Szrj free_node (tree node)
113238fd1498Szrj {
113338fd1498Szrj enum tree_code code = TREE_CODE (node);
113438fd1498Szrj if (GATHER_STATISTICS)
113538fd1498Szrj {
113638fd1498Szrj enum tree_node_kind kind = get_stats_node_kind (code);
113738fd1498Szrj
113838fd1498Szrj gcc_checking_assert (tree_code_counts[(int) TREE_CODE (node)] != 0);
113938fd1498Szrj gcc_checking_assert (tree_node_counts[(int) kind] != 0);
114038fd1498Szrj gcc_checking_assert (tree_node_sizes[(int) kind] >= tree_size (node));
114138fd1498Szrj
114238fd1498Szrj tree_code_counts[(int) TREE_CODE (node)]--;
114338fd1498Szrj tree_node_counts[(int) kind]--;
114438fd1498Szrj tree_node_sizes[(int) kind] -= tree_size (node);
114538fd1498Szrj }
114638fd1498Szrj if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
114738fd1498Szrj vec_free (CONSTRUCTOR_ELTS (node));
114838fd1498Szrj else if (code == BLOCK)
114938fd1498Szrj vec_free (BLOCK_NONLOCALIZED_VARS (node));
115038fd1498Szrj else if (code == TREE_BINFO)
115138fd1498Szrj vec_free (BINFO_BASE_ACCESSES (node));
115238fd1498Szrj ggc_free (node);
115338fd1498Szrj }
115438fd1498Szrj
115538fd1498Szrj /* Return a new node with the same contents as NODE except that its
115638fd1498Szrj TREE_CHAIN, if it has one, is zero and it has a fresh uid. */
115738fd1498Szrj
115838fd1498Szrj tree
copy_node(tree node MEM_STAT_DECL)115938fd1498Szrj copy_node (tree node MEM_STAT_DECL)
116038fd1498Szrj {
116138fd1498Szrj tree t;
116238fd1498Szrj enum tree_code code = TREE_CODE (node);
116338fd1498Szrj size_t length;
116438fd1498Szrj
116538fd1498Szrj gcc_assert (code != STATEMENT_LIST);
116638fd1498Szrj
116738fd1498Szrj length = tree_size (node);
116838fd1498Szrj record_node_allocation_statistics (code, length);
116938fd1498Szrj t = ggc_alloc_tree_node_stat (length PASS_MEM_STAT);
117038fd1498Szrj memcpy (t, node, length);
117138fd1498Szrj
117238fd1498Szrj if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
117338fd1498Szrj TREE_CHAIN (t) = 0;
117438fd1498Szrj TREE_ASM_WRITTEN (t) = 0;
117538fd1498Szrj TREE_VISITED (t) = 0;
117638fd1498Szrj
117738fd1498Szrj if (TREE_CODE_CLASS (code) == tcc_declaration)
117838fd1498Szrj {
117938fd1498Szrj if (code == DEBUG_EXPR_DECL)
118038fd1498Szrj DECL_UID (t) = --next_debug_decl_uid;
118138fd1498Szrj else
118238fd1498Szrj {
118338fd1498Szrj DECL_UID (t) = allocate_decl_uid ();
118438fd1498Szrj if (DECL_PT_UID_SET_P (node))
118538fd1498Szrj SET_DECL_PT_UID (t, DECL_PT_UID (node));
118638fd1498Szrj }
118738fd1498Szrj if ((TREE_CODE (node) == PARM_DECL || VAR_P (node))
118838fd1498Szrj && DECL_HAS_VALUE_EXPR_P (node))
118938fd1498Szrj {
119038fd1498Szrj SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (node));
119138fd1498Szrj DECL_HAS_VALUE_EXPR_P (t) = 1;
119238fd1498Szrj }
119338fd1498Szrj /* DECL_DEBUG_EXPR is copied explicitely by callers. */
119438fd1498Szrj if (VAR_P (node))
119538fd1498Szrj {
119638fd1498Szrj DECL_HAS_DEBUG_EXPR_P (t) = 0;
119738fd1498Szrj t->decl_with_vis.symtab_node = NULL;
119838fd1498Szrj }
119938fd1498Szrj if (VAR_P (node) && DECL_HAS_INIT_PRIORITY_P (node))
120038fd1498Szrj {
120138fd1498Szrj SET_DECL_INIT_PRIORITY (t, DECL_INIT_PRIORITY (node));
120238fd1498Szrj DECL_HAS_INIT_PRIORITY_P (t) = 1;
120338fd1498Szrj }
120438fd1498Szrj if (TREE_CODE (node) == FUNCTION_DECL)
120538fd1498Szrj {
120638fd1498Szrj DECL_STRUCT_FUNCTION (t) = NULL;
120738fd1498Szrj t->decl_with_vis.symtab_node = NULL;
120838fd1498Szrj }
120938fd1498Szrj }
121038fd1498Szrj else if (TREE_CODE_CLASS (code) == tcc_type)
121138fd1498Szrj {
121238fd1498Szrj TYPE_UID (t) = next_type_uid++;
121338fd1498Szrj /* The following is so that the debug code for
121438fd1498Szrj the copy is different from the original type.
121538fd1498Szrj The two statements usually duplicate each other
121638fd1498Szrj (because they clear fields of the same union),
121738fd1498Szrj but the optimizer should catch that. */
121838fd1498Szrj TYPE_SYMTAB_ADDRESS (t) = 0;
121938fd1498Szrj TYPE_SYMTAB_DIE (t) = 0;
122038fd1498Szrj
122138fd1498Szrj /* Do not copy the values cache. */
122238fd1498Szrj if (TYPE_CACHED_VALUES_P (t))
122338fd1498Szrj {
122438fd1498Szrj TYPE_CACHED_VALUES_P (t) = 0;
122538fd1498Szrj TYPE_CACHED_VALUES (t) = NULL_TREE;
122638fd1498Szrj }
122738fd1498Szrj }
122838fd1498Szrj else if (code == TARGET_OPTION_NODE)
122938fd1498Szrj {
123038fd1498Szrj TREE_TARGET_OPTION (t) = ggc_alloc<struct cl_target_option>();
123138fd1498Szrj memcpy (TREE_TARGET_OPTION (t), TREE_TARGET_OPTION (node),
123238fd1498Szrj sizeof (struct cl_target_option));
123338fd1498Szrj }
123438fd1498Szrj else if (code == OPTIMIZATION_NODE)
123538fd1498Szrj {
123638fd1498Szrj TREE_OPTIMIZATION (t) = ggc_alloc<struct cl_optimization>();
123738fd1498Szrj memcpy (TREE_OPTIMIZATION (t), TREE_OPTIMIZATION (node),
123838fd1498Szrj sizeof (struct cl_optimization));
123938fd1498Szrj }
124038fd1498Szrj
124138fd1498Szrj return t;
124238fd1498Szrj }
124338fd1498Szrj
124438fd1498Szrj /* Return a copy of a chain of nodes, chained through the TREE_CHAIN field.
124538fd1498Szrj For example, this can copy a list made of TREE_LIST nodes. */
124638fd1498Szrj
124738fd1498Szrj tree
copy_list(tree list)124838fd1498Szrj copy_list (tree list)
124938fd1498Szrj {
125038fd1498Szrj tree head;
125138fd1498Szrj tree prev, next;
125238fd1498Szrj
125338fd1498Szrj if (list == 0)
125438fd1498Szrj return 0;
125538fd1498Szrj
125638fd1498Szrj head = prev = copy_node (list);
125738fd1498Szrj next = TREE_CHAIN (list);
125838fd1498Szrj while (next)
125938fd1498Szrj {
126038fd1498Szrj TREE_CHAIN (prev) = copy_node (next);
126138fd1498Szrj prev = TREE_CHAIN (prev);
126238fd1498Szrj next = TREE_CHAIN (next);
126338fd1498Szrj }
126438fd1498Szrj return head;
126538fd1498Szrj }
126638fd1498Szrj
126738fd1498Szrj
126838fd1498Szrj /* Return the value that TREE_INT_CST_EXT_NUNITS should have for an
126938fd1498Szrj INTEGER_CST with value CST and type TYPE. */
127038fd1498Szrj
127138fd1498Szrj static unsigned int
get_int_cst_ext_nunits(tree type,const wide_int & cst)127238fd1498Szrj get_int_cst_ext_nunits (tree type, const wide_int &cst)
127338fd1498Szrj {
127438fd1498Szrj gcc_checking_assert (cst.get_precision () == TYPE_PRECISION (type));
127538fd1498Szrj /* We need extra HWIs if CST is an unsigned integer with its
127638fd1498Szrj upper bit set. */
127738fd1498Szrj if (TYPE_UNSIGNED (type) && wi::neg_p (cst))
127838fd1498Szrj return cst.get_precision () / HOST_BITS_PER_WIDE_INT + 1;
127938fd1498Szrj return cst.get_len ();
128038fd1498Szrj }
128138fd1498Szrj
128238fd1498Szrj /* Return a new INTEGER_CST with value CST and type TYPE. */
128338fd1498Szrj
128438fd1498Szrj static tree
build_new_int_cst(tree type,const wide_int & cst)128538fd1498Szrj build_new_int_cst (tree type, const wide_int &cst)
128638fd1498Szrj {
128738fd1498Szrj unsigned int len = cst.get_len ();
128838fd1498Szrj unsigned int ext_len = get_int_cst_ext_nunits (type, cst);
128938fd1498Szrj tree nt = make_int_cst (len, ext_len);
129038fd1498Szrj
129138fd1498Szrj if (len < ext_len)
129238fd1498Szrj {
129338fd1498Szrj --ext_len;
129438fd1498Szrj TREE_INT_CST_ELT (nt, ext_len)
129538fd1498Szrj = zext_hwi (-1, cst.get_precision () % HOST_BITS_PER_WIDE_INT);
129638fd1498Szrj for (unsigned int i = len; i < ext_len; ++i)
129738fd1498Szrj TREE_INT_CST_ELT (nt, i) = -1;
129838fd1498Szrj }
129938fd1498Szrj else if (TYPE_UNSIGNED (type)
130038fd1498Szrj && cst.get_precision () < len * HOST_BITS_PER_WIDE_INT)
130138fd1498Szrj {
130238fd1498Szrj len--;
130338fd1498Szrj TREE_INT_CST_ELT (nt, len)
130438fd1498Szrj = zext_hwi (cst.elt (len),
130538fd1498Szrj cst.get_precision () % HOST_BITS_PER_WIDE_INT);
130638fd1498Szrj }
130738fd1498Szrj
130838fd1498Szrj for (unsigned int i = 0; i < len; i++)
130938fd1498Szrj TREE_INT_CST_ELT (nt, i) = cst.elt (i);
131038fd1498Szrj TREE_TYPE (nt) = type;
131138fd1498Szrj return nt;
131238fd1498Szrj }
131338fd1498Szrj
131438fd1498Szrj /* Return a new POLY_INT_CST with coefficients COEFFS and type TYPE. */
131538fd1498Szrj
131638fd1498Szrj static tree
build_new_poly_int_cst(tree type,tree (& coeffs)[NUM_POLY_INT_COEFFS]CXX_MEM_STAT_INFO)131738fd1498Szrj build_new_poly_int_cst (tree type, tree (&coeffs)[NUM_POLY_INT_COEFFS]
131838fd1498Szrj CXX_MEM_STAT_INFO)
131938fd1498Szrj {
132038fd1498Szrj size_t length = sizeof (struct tree_poly_int_cst);
132138fd1498Szrj record_node_allocation_statistics (POLY_INT_CST, length);
132238fd1498Szrj
132338fd1498Szrj tree t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT);
132438fd1498Szrj
132538fd1498Szrj TREE_SET_CODE (t, POLY_INT_CST);
132638fd1498Szrj TREE_CONSTANT (t) = 1;
132738fd1498Szrj TREE_TYPE (t) = type;
132838fd1498Szrj for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
132938fd1498Szrj POLY_INT_CST_COEFF (t, i) = coeffs[i];
133038fd1498Szrj return t;
133138fd1498Szrj }
133238fd1498Szrj
133338fd1498Szrj /* Create a constant tree that contains CST sign-extended to TYPE. */
133438fd1498Szrj
133538fd1498Szrj tree
build_int_cst(tree type,poly_int64 cst)133638fd1498Szrj build_int_cst (tree type, poly_int64 cst)
133738fd1498Szrj {
133838fd1498Szrj /* Support legacy code. */
133938fd1498Szrj if (!type)
134038fd1498Szrj type = integer_type_node;
134138fd1498Szrj
134238fd1498Szrj return wide_int_to_tree (type, wi::shwi (cst, TYPE_PRECISION (type)));
134338fd1498Szrj }
134438fd1498Szrj
134538fd1498Szrj /* Create a constant tree that contains CST zero-extended to TYPE. */
134638fd1498Szrj
134738fd1498Szrj tree
build_int_cstu(tree type,poly_uint64 cst)134838fd1498Szrj build_int_cstu (tree type, poly_uint64 cst)
134938fd1498Szrj {
135038fd1498Szrj return wide_int_to_tree (type, wi::uhwi (cst, TYPE_PRECISION (type)));
135138fd1498Szrj }
135238fd1498Szrj
135338fd1498Szrj /* Create a constant tree that contains CST sign-extended to TYPE. */
135438fd1498Szrj
135538fd1498Szrj tree
build_int_cst_type(tree type,poly_int64 cst)135638fd1498Szrj build_int_cst_type (tree type, poly_int64 cst)
135738fd1498Szrj {
135838fd1498Szrj gcc_assert (type);
135938fd1498Szrj return wide_int_to_tree (type, wi::shwi (cst, TYPE_PRECISION (type)));
136038fd1498Szrj }
136138fd1498Szrj
136238fd1498Szrj /* Constructs tree in type TYPE from with value given by CST. Signedness
136338fd1498Szrj of CST is assumed to be the same as the signedness of TYPE. */
136438fd1498Szrj
136538fd1498Szrj tree
double_int_to_tree(tree type,double_int cst)136638fd1498Szrj double_int_to_tree (tree type, double_int cst)
136738fd1498Szrj {
136838fd1498Szrj return wide_int_to_tree (type, widest_int::from (cst, TYPE_SIGN (type)));
136938fd1498Szrj }
137038fd1498Szrj
137138fd1498Szrj /* We force the wide_int CST to the range of the type TYPE by sign or
137238fd1498Szrj zero extending it. OVERFLOWABLE indicates if we are interested in
137338fd1498Szrj overflow of the value, when >0 we are only interested in signed
137438fd1498Szrj overflow, for <0 we are interested in any overflow. OVERFLOWED
137538fd1498Szrj indicates whether overflow has already occurred. CONST_OVERFLOWED
137638fd1498Szrj indicates whether constant overflow has already occurred. We force
137738fd1498Szrj T's value to be within range of T's type (by setting to 0 or 1 all
137838fd1498Szrj the bits outside the type's range). We set TREE_OVERFLOWED if,
137938fd1498Szrj OVERFLOWED is nonzero,
138038fd1498Szrj or OVERFLOWABLE is >0 and signed overflow occurs
138138fd1498Szrj or OVERFLOWABLE is <0 and any overflow occurs
138238fd1498Szrj We return a new tree node for the extended wide_int. The node
138338fd1498Szrj is shared if no overflow flags are set. */
138438fd1498Szrj
138538fd1498Szrj
138638fd1498Szrj tree
force_fit_type(tree type,const poly_wide_int_ref & cst,int overflowable,bool overflowed)138738fd1498Szrj force_fit_type (tree type, const poly_wide_int_ref &cst,
138838fd1498Szrj int overflowable, bool overflowed)
138938fd1498Szrj {
139038fd1498Szrj signop sign = TYPE_SIGN (type);
139138fd1498Szrj
139238fd1498Szrj /* If we need to set overflow flags, return a new unshared node. */
139338fd1498Szrj if (overflowed || !wi::fits_to_tree_p (cst, type))
139438fd1498Szrj {
139538fd1498Szrj if (overflowed
139638fd1498Szrj || overflowable < 0
139738fd1498Szrj || (overflowable > 0 && sign == SIGNED))
139838fd1498Szrj {
139938fd1498Szrj poly_wide_int tmp = poly_wide_int::from (cst, TYPE_PRECISION (type),
140038fd1498Szrj sign);
140138fd1498Szrj tree t;
140238fd1498Szrj if (tmp.is_constant ())
140338fd1498Szrj t = build_new_int_cst (type, tmp.coeffs[0]);
140438fd1498Szrj else
140538fd1498Szrj {
140638fd1498Szrj tree coeffs[NUM_POLY_INT_COEFFS];
140738fd1498Szrj for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
140838fd1498Szrj {
140938fd1498Szrj coeffs[i] = build_new_int_cst (type, tmp.coeffs[i]);
141038fd1498Szrj TREE_OVERFLOW (coeffs[i]) = 1;
141138fd1498Szrj }
141238fd1498Szrj t = build_new_poly_int_cst (type, coeffs);
141338fd1498Szrj }
141438fd1498Szrj TREE_OVERFLOW (t) = 1;
141538fd1498Szrj return t;
141638fd1498Szrj }
141738fd1498Szrj }
141838fd1498Szrj
141938fd1498Szrj /* Else build a shared node. */
142038fd1498Szrj return wide_int_to_tree (type, cst);
142138fd1498Szrj }
142238fd1498Szrj
142338fd1498Szrj /* These are the hash table functions for the hash table of INTEGER_CST
142438fd1498Szrj nodes of a sizetype. */
142538fd1498Szrj
142638fd1498Szrj /* Return the hash code X, an INTEGER_CST. */
142738fd1498Szrj
142838fd1498Szrj hashval_t
hash(tree x)142938fd1498Szrj int_cst_hasher::hash (tree x)
143038fd1498Szrj {
143138fd1498Szrj const_tree const t = x;
143238fd1498Szrj hashval_t code = TYPE_UID (TREE_TYPE (t));
143338fd1498Szrj int i;
143438fd1498Szrj
143538fd1498Szrj for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
143638fd1498Szrj code = iterative_hash_host_wide_int (TREE_INT_CST_ELT(t, i), code);
143738fd1498Szrj
143838fd1498Szrj return code;
143938fd1498Szrj }
144038fd1498Szrj
144138fd1498Szrj /* Return nonzero if the value represented by *X (an INTEGER_CST tree node)
144238fd1498Szrj is the same as that given by *Y, which is the same. */
144338fd1498Szrj
144438fd1498Szrj bool
equal(tree x,tree y)144538fd1498Szrj int_cst_hasher::equal (tree x, tree y)
144638fd1498Szrj {
144738fd1498Szrj const_tree const xt = x;
144838fd1498Szrj const_tree const yt = y;
144938fd1498Szrj
145038fd1498Szrj if (TREE_TYPE (xt) != TREE_TYPE (yt)
145138fd1498Szrj || TREE_INT_CST_NUNITS (xt) != TREE_INT_CST_NUNITS (yt)
145238fd1498Szrj || TREE_INT_CST_EXT_NUNITS (xt) != TREE_INT_CST_EXT_NUNITS (yt))
145338fd1498Szrj return false;
145438fd1498Szrj
145538fd1498Szrj for (int i = 0; i < TREE_INT_CST_NUNITS (xt); i++)
145638fd1498Szrj if (TREE_INT_CST_ELT (xt, i) != TREE_INT_CST_ELT (yt, i))
145738fd1498Szrj return false;
145838fd1498Szrj
145938fd1498Szrj return true;
146038fd1498Szrj }
146138fd1498Szrj
146238fd1498Szrj /* Create an INT_CST node of TYPE and value CST.
146338fd1498Szrj The returned node is always shared. For small integers we use a
146438fd1498Szrj per-type vector cache, for larger ones we use a single hash table.
146538fd1498Szrj The value is extended from its precision according to the sign of
146638fd1498Szrj the type to be a multiple of HOST_BITS_PER_WIDE_INT. This defines
146738fd1498Szrj the upper bits and ensures that hashing and value equality based
146838fd1498Szrj upon the underlying HOST_WIDE_INTs works without masking. */
146938fd1498Szrj
147038fd1498Szrj static tree
wide_int_to_tree_1(tree type,const wide_int_ref & pcst)147138fd1498Szrj wide_int_to_tree_1 (tree type, const wide_int_ref &pcst)
147238fd1498Szrj {
147338fd1498Szrj tree t;
147438fd1498Szrj int ix = -1;
147538fd1498Szrj int limit = 0;
147638fd1498Szrj
147738fd1498Szrj gcc_assert (type);
147838fd1498Szrj unsigned int prec = TYPE_PRECISION (type);
147938fd1498Szrj signop sgn = TYPE_SIGN (type);
148038fd1498Szrj
148138fd1498Szrj /* Verify that everything is canonical. */
148238fd1498Szrj int l = pcst.get_len ();
148338fd1498Szrj if (l > 1)
148438fd1498Szrj {
148538fd1498Szrj if (pcst.elt (l - 1) == 0)
148638fd1498Szrj gcc_checking_assert (pcst.elt (l - 2) < 0);
148738fd1498Szrj if (pcst.elt (l - 1) == HOST_WIDE_INT_M1)
148838fd1498Szrj gcc_checking_assert (pcst.elt (l - 2) >= 0);
148938fd1498Szrj }
149038fd1498Szrj
149138fd1498Szrj wide_int cst = wide_int::from (pcst, prec, sgn);
149238fd1498Szrj unsigned int ext_len = get_int_cst_ext_nunits (type, cst);
149338fd1498Szrj
149438fd1498Szrj if (ext_len == 1)
149538fd1498Szrj {
149638fd1498Szrj /* We just need to store a single HOST_WIDE_INT. */
149738fd1498Szrj HOST_WIDE_INT hwi;
149838fd1498Szrj if (TYPE_UNSIGNED (type))
149938fd1498Szrj hwi = cst.to_uhwi ();
150038fd1498Szrj else
150138fd1498Szrj hwi = cst.to_shwi ();
150238fd1498Szrj
150338fd1498Szrj switch (TREE_CODE (type))
150438fd1498Szrj {
150538fd1498Szrj case NULLPTR_TYPE:
150638fd1498Szrj gcc_assert (hwi == 0);
150738fd1498Szrj /* Fallthru. */
150838fd1498Szrj
150938fd1498Szrj case POINTER_TYPE:
151038fd1498Szrj case REFERENCE_TYPE:
151138fd1498Szrj case POINTER_BOUNDS_TYPE:
151238fd1498Szrj /* Cache NULL pointer and zero bounds. */
151338fd1498Szrj if (hwi == 0)
151438fd1498Szrj {
151538fd1498Szrj limit = 1;
151638fd1498Szrj ix = 0;
151738fd1498Szrj }
151838fd1498Szrj break;
151938fd1498Szrj
152038fd1498Szrj case BOOLEAN_TYPE:
152138fd1498Szrj /* Cache false or true. */
152238fd1498Szrj limit = 2;
152338fd1498Szrj if (IN_RANGE (hwi, 0, 1))
152438fd1498Szrj ix = hwi;
152538fd1498Szrj break;
152638fd1498Szrj
152738fd1498Szrj case INTEGER_TYPE:
152838fd1498Szrj case OFFSET_TYPE:
152938fd1498Szrj if (TYPE_SIGN (type) == UNSIGNED)
153038fd1498Szrj {
153138fd1498Szrj /* Cache [0, N). */
153238fd1498Szrj limit = INTEGER_SHARE_LIMIT;
153338fd1498Szrj if (IN_RANGE (hwi, 0, INTEGER_SHARE_LIMIT - 1))
153438fd1498Szrj ix = hwi;
153538fd1498Szrj }
153638fd1498Szrj else
153738fd1498Szrj {
153838fd1498Szrj /* Cache [-1, N). */
153938fd1498Szrj limit = INTEGER_SHARE_LIMIT + 1;
154038fd1498Szrj if (IN_RANGE (hwi, -1, INTEGER_SHARE_LIMIT - 1))
154138fd1498Szrj ix = hwi + 1;
154238fd1498Szrj }
154338fd1498Szrj break;
154438fd1498Szrj
154538fd1498Szrj case ENUMERAL_TYPE:
154638fd1498Szrj break;
154738fd1498Szrj
154838fd1498Szrj default:
154938fd1498Szrj gcc_unreachable ();
155038fd1498Szrj }
155138fd1498Szrj
155238fd1498Szrj if (ix >= 0)
155338fd1498Szrj {
155438fd1498Szrj /* Look for it in the type's vector of small shared ints. */
155538fd1498Szrj if (!TYPE_CACHED_VALUES_P (type))
155638fd1498Szrj {
155738fd1498Szrj TYPE_CACHED_VALUES_P (type) = 1;
155838fd1498Szrj TYPE_CACHED_VALUES (type) = make_tree_vec (limit);
155938fd1498Szrj }
156038fd1498Szrj
156138fd1498Szrj t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix);
156238fd1498Szrj if (t)
156338fd1498Szrj /* Make sure no one is clobbering the shared constant. */
156438fd1498Szrj gcc_checking_assert (TREE_TYPE (t) == type
156538fd1498Szrj && TREE_INT_CST_NUNITS (t) == 1
156638fd1498Szrj && TREE_INT_CST_OFFSET_NUNITS (t) == 1
156738fd1498Szrj && TREE_INT_CST_EXT_NUNITS (t) == 1
156838fd1498Szrj && TREE_INT_CST_ELT (t, 0) == hwi);
156938fd1498Szrj else
157038fd1498Szrj {
157138fd1498Szrj /* Create a new shared int. */
157238fd1498Szrj t = build_new_int_cst (type, cst);
157338fd1498Szrj TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
157438fd1498Szrj }
157538fd1498Szrj }
157638fd1498Szrj else
157738fd1498Szrj {
157838fd1498Szrj /* Use the cache of larger shared ints, using int_cst_node as
157938fd1498Szrj a temporary. */
158038fd1498Szrj
158138fd1498Szrj TREE_INT_CST_ELT (int_cst_node, 0) = hwi;
158238fd1498Szrj TREE_TYPE (int_cst_node) = type;
158338fd1498Szrj
158438fd1498Szrj tree *slot = int_cst_hash_table->find_slot (int_cst_node, INSERT);
158538fd1498Szrj t = *slot;
158638fd1498Szrj if (!t)
158738fd1498Szrj {
158838fd1498Szrj /* Insert this one into the hash table. */
158938fd1498Szrj t = int_cst_node;
159038fd1498Szrj *slot = t;
159138fd1498Szrj /* Make a new node for next time round. */
159238fd1498Szrj int_cst_node = make_int_cst (1, 1);
159338fd1498Szrj }
159438fd1498Szrj }
159538fd1498Szrj }
159638fd1498Szrj else
159738fd1498Szrj {
159838fd1498Szrj /* The value either hashes properly or we drop it on the floor
159938fd1498Szrj for the gc to take care of. There will not be enough of them
160038fd1498Szrj to worry about. */
160138fd1498Szrj
160238fd1498Szrj tree nt = build_new_int_cst (type, cst);
160338fd1498Szrj tree *slot = int_cst_hash_table->find_slot (nt, INSERT);
160438fd1498Szrj t = *slot;
160538fd1498Szrj if (!t)
160638fd1498Szrj {
160738fd1498Szrj /* Insert this one into the hash table. */
160838fd1498Szrj t = nt;
160938fd1498Szrj *slot = t;
161038fd1498Szrj }
161138fd1498Szrj else
161238fd1498Szrj ggc_free (nt);
161338fd1498Szrj }
161438fd1498Szrj
161538fd1498Szrj return t;
161638fd1498Szrj }
161738fd1498Szrj
161838fd1498Szrj hashval_t
hash(tree t)161938fd1498Szrj poly_int_cst_hasher::hash (tree t)
162038fd1498Szrj {
162138fd1498Szrj inchash::hash hstate;
162238fd1498Szrj
162338fd1498Szrj hstate.add_int (TYPE_UID (TREE_TYPE (t)));
162438fd1498Szrj for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
162538fd1498Szrj hstate.add_wide_int (wi::to_wide (POLY_INT_CST_COEFF (t, i)));
162638fd1498Szrj
162738fd1498Szrj return hstate.end ();
162838fd1498Szrj }
162938fd1498Szrj
163038fd1498Szrj bool
equal(tree x,const compare_type & y)163138fd1498Szrj poly_int_cst_hasher::equal (tree x, const compare_type &y)
163238fd1498Szrj {
163338fd1498Szrj if (TREE_TYPE (x) != y.first)
163438fd1498Szrj return false;
163538fd1498Szrj for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
163638fd1498Szrj if (wi::to_wide (POLY_INT_CST_COEFF (x, i)) != y.second->coeffs[i])
163738fd1498Szrj return false;
163838fd1498Szrj return true;
163938fd1498Szrj }
164038fd1498Szrj
164138fd1498Szrj /* Build a POLY_INT_CST node with type TYPE and with the elements in VALUES.
164238fd1498Szrj The elements must also have type TYPE. */
164338fd1498Szrj
164438fd1498Szrj tree
build_poly_int_cst(tree type,const poly_wide_int_ref & values)164538fd1498Szrj build_poly_int_cst (tree type, const poly_wide_int_ref &values)
164638fd1498Szrj {
164738fd1498Szrj unsigned int prec = TYPE_PRECISION (type);
164838fd1498Szrj gcc_assert (prec <= values.coeffs[0].get_precision ());
164938fd1498Szrj poly_wide_int c = poly_wide_int::from (values, prec, SIGNED);
165038fd1498Szrj
165138fd1498Szrj inchash::hash h;
165238fd1498Szrj h.add_int (TYPE_UID (type));
165338fd1498Szrj for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
165438fd1498Szrj h.add_wide_int (c.coeffs[i]);
165538fd1498Szrj poly_int_cst_hasher::compare_type comp (type, &c);
165638fd1498Szrj tree *slot = poly_int_cst_hash_table->find_slot_with_hash (comp, h.end (),
165738fd1498Szrj INSERT);
165838fd1498Szrj if (*slot == NULL_TREE)
165938fd1498Szrj {
166038fd1498Szrj tree coeffs[NUM_POLY_INT_COEFFS];
166138fd1498Szrj for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
166238fd1498Szrj coeffs[i] = wide_int_to_tree_1 (type, c.coeffs[i]);
166338fd1498Szrj *slot = build_new_poly_int_cst (type, coeffs);
166438fd1498Szrj }
166538fd1498Szrj return *slot;
166638fd1498Szrj }
166738fd1498Szrj
166838fd1498Szrj /* Create a constant tree with value VALUE in type TYPE. */
166938fd1498Szrj
167038fd1498Szrj tree
wide_int_to_tree(tree type,const poly_wide_int_ref & value)167138fd1498Szrj wide_int_to_tree (tree type, const poly_wide_int_ref &value)
167238fd1498Szrj {
167338fd1498Szrj if (value.is_constant ())
167438fd1498Szrj return wide_int_to_tree_1 (type, value.coeffs[0]);
167538fd1498Szrj return build_poly_int_cst (type, value);
167638fd1498Szrj }
167738fd1498Szrj
167838fd1498Szrj void
cache_integer_cst(tree t)167938fd1498Szrj cache_integer_cst (tree t)
168038fd1498Szrj {
168138fd1498Szrj tree type = TREE_TYPE (t);
168238fd1498Szrj int ix = -1;
168338fd1498Szrj int limit = 0;
168438fd1498Szrj int prec = TYPE_PRECISION (type);
168538fd1498Szrj
168638fd1498Szrj gcc_assert (!TREE_OVERFLOW (t));
168738fd1498Szrj
168838fd1498Szrj switch (TREE_CODE (type))
168938fd1498Szrj {
169038fd1498Szrj case NULLPTR_TYPE:
169138fd1498Szrj gcc_assert (integer_zerop (t));
169238fd1498Szrj /* Fallthru. */
169338fd1498Szrj
169438fd1498Szrj case POINTER_TYPE:
169538fd1498Szrj case REFERENCE_TYPE:
169638fd1498Szrj /* Cache NULL pointer. */
169738fd1498Szrj if (integer_zerop (t))
169838fd1498Szrj {
169938fd1498Szrj limit = 1;
170038fd1498Szrj ix = 0;
170138fd1498Szrj }
170238fd1498Szrj break;
170338fd1498Szrj
170438fd1498Szrj case BOOLEAN_TYPE:
170538fd1498Szrj /* Cache false or true. */
170638fd1498Szrj limit = 2;
170738fd1498Szrj if (wi::ltu_p (wi::to_wide (t), 2))
170838fd1498Szrj ix = TREE_INT_CST_ELT (t, 0);
170938fd1498Szrj break;
171038fd1498Szrj
171138fd1498Szrj case INTEGER_TYPE:
171238fd1498Szrj case OFFSET_TYPE:
171338fd1498Szrj if (TYPE_UNSIGNED (type))
171438fd1498Szrj {
171538fd1498Szrj /* Cache 0..N */
171638fd1498Szrj limit = INTEGER_SHARE_LIMIT;
171738fd1498Szrj
171838fd1498Szrj /* This is a little hokie, but if the prec is smaller than
171938fd1498Szrj what is necessary to hold INTEGER_SHARE_LIMIT, then the
172038fd1498Szrj obvious test will not get the correct answer. */
172138fd1498Szrj if (prec < HOST_BITS_PER_WIDE_INT)
172238fd1498Szrj {
172338fd1498Szrj if (tree_to_uhwi (t) < (unsigned HOST_WIDE_INT) INTEGER_SHARE_LIMIT)
172438fd1498Szrj ix = tree_to_uhwi (t);
172538fd1498Szrj }
172638fd1498Szrj else if (wi::ltu_p (wi::to_wide (t), INTEGER_SHARE_LIMIT))
172738fd1498Szrj ix = tree_to_uhwi (t);
172838fd1498Szrj }
172938fd1498Szrj else
173038fd1498Szrj {
173138fd1498Szrj /* Cache -1..N */
173238fd1498Szrj limit = INTEGER_SHARE_LIMIT + 1;
173338fd1498Szrj
173438fd1498Szrj if (integer_minus_onep (t))
173538fd1498Szrj ix = 0;
173638fd1498Szrj else if (!wi::neg_p (wi::to_wide (t)))
173738fd1498Szrj {
173838fd1498Szrj if (prec < HOST_BITS_PER_WIDE_INT)
173938fd1498Szrj {
174038fd1498Szrj if (tree_to_shwi (t) < INTEGER_SHARE_LIMIT)
174138fd1498Szrj ix = tree_to_shwi (t) + 1;
174238fd1498Szrj }
174338fd1498Szrj else if (wi::ltu_p (wi::to_wide (t), INTEGER_SHARE_LIMIT))
174438fd1498Szrj ix = tree_to_shwi (t) + 1;
174538fd1498Szrj }
174638fd1498Szrj }
174738fd1498Szrj break;
174838fd1498Szrj
174938fd1498Szrj case ENUMERAL_TYPE:
175038fd1498Szrj break;
175138fd1498Szrj
175238fd1498Szrj default:
175338fd1498Szrj gcc_unreachable ();
175438fd1498Szrj }
175538fd1498Szrj
175638fd1498Szrj if (ix >= 0)
175738fd1498Szrj {
175838fd1498Szrj /* Look for it in the type's vector of small shared ints. */
175938fd1498Szrj if (!TYPE_CACHED_VALUES_P (type))
176038fd1498Szrj {
176138fd1498Szrj TYPE_CACHED_VALUES_P (type) = 1;
176238fd1498Szrj TYPE_CACHED_VALUES (type) = make_tree_vec (limit);
176338fd1498Szrj }
176438fd1498Szrj
176538fd1498Szrj gcc_assert (TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) == NULL_TREE);
176638fd1498Szrj TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
176738fd1498Szrj }
176838fd1498Szrj else
176938fd1498Szrj {
177038fd1498Szrj /* Use the cache of larger shared ints. */
177138fd1498Szrj tree *slot = int_cst_hash_table->find_slot (t, INSERT);
177238fd1498Szrj /* If there is already an entry for the number verify it's the
177338fd1498Szrj same. */
177438fd1498Szrj if (*slot)
177538fd1498Szrj gcc_assert (wi::to_wide (tree (*slot)) == wi::to_wide (t));
177638fd1498Szrj else
177738fd1498Szrj /* Otherwise insert this one into the hash table. */
177838fd1498Szrj *slot = t;
177938fd1498Szrj }
178038fd1498Szrj }
178138fd1498Szrj
178238fd1498Szrj
178338fd1498Szrj /* Builds an integer constant in TYPE such that lowest BITS bits are ones
178438fd1498Szrj and the rest are zeros. */
178538fd1498Szrj
178638fd1498Szrj tree
build_low_bits_mask(tree type,unsigned bits)178738fd1498Szrj build_low_bits_mask (tree type, unsigned bits)
178838fd1498Szrj {
178938fd1498Szrj gcc_assert (bits <= TYPE_PRECISION (type));
179038fd1498Szrj
179138fd1498Szrj return wide_int_to_tree (type, wi::mask (bits, false,
179238fd1498Szrj TYPE_PRECISION (type)));
179338fd1498Szrj }
179438fd1498Szrj
179538fd1498Szrj /* Checks that X is integer constant that can be expressed in (unsigned)
179638fd1498Szrj HOST_WIDE_INT without loss of precision. */
179738fd1498Szrj
179838fd1498Szrj bool
cst_and_fits_in_hwi(const_tree x)179938fd1498Szrj cst_and_fits_in_hwi (const_tree x)
180038fd1498Szrj {
180138fd1498Szrj return (TREE_CODE (x) == INTEGER_CST
180238fd1498Szrj && (tree_fits_shwi_p (x) || tree_fits_uhwi_p (x)));
180338fd1498Szrj }
180438fd1498Szrj
180538fd1498Szrj /* Build a newly constructed VECTOR_CST with the given values of
180638fd1498Szrj (VECTOR_CST_)LOG2_NPATTERNS and (VECTOR_CST_)NELTS_PER_PATTERN. */
180738fd1498Szrj
180838fd1498Szrj tree
make_vector(unsigned log2_npatterns,unsigned int nelts_per_pattern MEM_STAT_DECL)180938fd1498Szrj make_vector (unsigned log2_npatterns,
181038fd1498Szrj unsigned int nelts_per_pattern MEM_STAT_DECL)
181138fd1498Szrj {
181238fd1498Szrj gcc_assert (IN_RANGE (nelts_per_pattern, 1, 3));
181338fd1498Szrj tree t;
181438fd1498Szrj unsigned npatterns = 1 << log2_npatterns;
181538fd1498Szrj unsigned encoded_nelts = npatterns * nelts_per_pattern;
181638fd1498Szrj unsigned length = (sizeof (struct tree_vector)
181738fd1498Szrj + (encoded_nelts - 1) * sizeof (tree));
181838fd1498Szrj
181938fd1498Szrj record_node_allocation_statistics (VECTOR_CST, length);
182038fd1498Szrj
182138fd1498Szrj t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT);
182238fd1498Szrj
182338fd1498Szrj TREE_SET_CODE (t, VECTOR_CST);
182438fd1498Szrj TREE_CONSTANT (t) = 1;
182538fd1498Szrj VECTOR_CST_LOG2_NPATTERNS (t) = log2_npatterns;
182638fd1498Szrj VECTOR_CST_NELTS_PER_PATTERN (t) = nelts_per_pattern;
182738fd1498Szrj
182838fd1498Szrj return t;
182938fd1498Szrj }
183038fd1498Szrj
183138fd1498Szrj /* Return a new VECTOR_CST node whose type is TYPE and whose values
183238fd1498Szrj are extracted from V, a vector of CONSTRUCTOR_ELT. */
183338fd1498Szrj
183438fd1498Szrj tree
build_vector_from_ctor(tree type,vec<constructor_elt,va_gc> * v)183538fd1498Szrj build_vector_from_ctor (tree type, vec<constructor_elt, va_gc> *v)
183638fd1498Szrj {
183738fd1498Szrj unsigned HOST_WIDE_INT idx, nelts;
183838fd1498Szrj tree value;
183938fd1498Szrj
184038fd1498Szrj /* We can't construct a VECTOR_CST for a variable number of elements. */
184138fd1498Szrj nelts = TYPE_VECTOR_SUBPARTS (type).to_constant ();
184238fd1498Szrj tree_vector_builder vec (type, nelts, 1);
184338fd1498Szrj FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
184438fd1498Szrj {
184538fd1498Szrj if (TREE_CODE (value) == VECTOR_CST)
184638fd1498Szrj {
184738fd1498Szrj /* If NELTS is constant then this must be too. */
184838fd1498Szrj unsigned int sub_nelts = VECTOR_CST_NELTS (value).to_constant ();
184938fd1498Szrj for (unsigned i = 0; i < sub_nelts; ++i)
185038fd1498Szrj vec.quick_push (VECTOR_CST_ELT (value, i));
185138fd1498Szrj }
185238fd1498Szrj else
185338fd1498Szrj vec.quick_push (value);
185438fd1498Szrj }
185538fd1498Szrj while (vec.length () < nelts)
185638fd1498Szrj vec.quick_push (build_zero_cst (TREE_TYPE (type)));
185738fd1498Szrj
185838fd1498Szrj return vec.build ();
185938fd1498Szrj }
186038fd1498Szrj
186138fd1498Szrj /* Build a vector of type VECTYPE where all the elements are SCs. */
186238fd1498Szrj tree
build_vector_from_val(tree vectype,tree sc)186338fd1498Szrj build_vector_from_val (tree vectype, tree sc)
186438fd1498Szrj {
186538fd1498Szrj unsigned HOST_WIDE_INT i, nunits;
186638fd1498Szrj
186738fd1498Szrj if (sc == error_mark_node)
186838fd1498Szrj return sc;
186938fd1498Szrj
187038fd1498Szrj /* Verify that the vector type is suitable for SC. Note that there
187138fd1498Szrj is some inconsistency in the type-system with respect to restrict
187238fd1498Szrj qualifications of pointers. Vector types always have a main-variant
187338fd1498Szrj element type and the qualification is applied to the vector-type.
187438fd1498Szrj So TREE_TYPE (vector-type) does not return a properly qualified
187538fd1498Szrj vector element-type. */
187638fd1498Szrj gcc_checking_assert (types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (sc)),
187738fd1498Szrj TREE_TYPE (vectype)));
187838fd1498Szrj
187938fd1498Szrj if (CONSTANT_CLASS_P (sc))
188038fd1498Szrj {
188138fd1498Szrj tree_vector_builder v (vectype, 1, 1);
188238fd1498Szrj v.quick_push (sc);
188338fd1498Szrj return v.build ();
188438fd1498Szrj }
188538fd1498Szrj else if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant (&nunits))
188638fd1498Szrj return fold_build1 (VEC_DUPLICATE_EXPR, vectype, sc);
188738fd1498Szrj else
188838fd1498Szrj {
188938fd1498Szrj vec<constructor_elt, va_gc> *v;
189038fd1498Szrj vec_alloc (v, nunits);
189138fd1498Szrj for (i = 0; i < nunits; ++i)
189238fd1498Szrj CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, sc);
189338fd1498Szrj return build_constructor (vectype, v);
189438fd1498Szrj }
189538fd1498Szrj }
189638fd1498Szrj
189738fd1498Szrj /* Build a vector series of type TYPE in which element I has the value
189838fd1498Szrj BASE + I * STEP. The result is a constant if BASE and STEP are constant
189938fd1498Szrj and a VEC_SERIES_EXPR otherwise. */
190038fd1498Szrj
190138fd1498Szrj tree
build_vec_series(tree type,tree base,tree step)190238fd1498Szrj build_vec_series (tree type, tree base, tree step)
190338fd1498Szrj {
190438fd1498Szrj if (integer_zerop (step))
190538fd1498Szrj return build_vector_from_val (type, base);
190638fd1498Szrj if (TREE_CODE (base) == INTEGER_CST && TREE_CODE (step) == INTEGER_CST)
190738fd1498Szrj {
190838fd1498Szrj tree_vector_builder builder (type, 1, 3);
190938fd1498Szrj tree elt1 = wide_int_to_tree (TREE_TYPE (base),
191038fd1498Szrj wi::to_wide (base) + wi::to_wide (step));
191138fd1498Szrj tree elt2 = wide_int_to_tree (TREE_TYPE (base),
191238fd1498Szrj wi::to_wide (elt1) + wi::to_wide (step));
191338fd1498Szrj builder.quick_push (base);
191438fd1498Szrj builder.quick_push (elt1);
191538fd1498Szrj builder.quick_push (elt2);
191638fd1498Szrj return builder.build ();
191738fd1498Szrj }
191838fd1498Szrj return build2 (VEC_SERIES_EXPR, type, base, step);
191938fd1498Szrj }
192038fd1498Szrj
192138fd1498Szrj /* Return a vector with the same number of units and number of bits
192238fd1498Szrj as VEC_TYPE, but in which the elements are a linear series of unsigned
192338fd1498Szrj integers { BASE, BASE + STEP, BASE + STEP * 2, ... }. */
192438fd1498Szrj
192538fd1498Szrj tree
build_index_vector(tree vec_type,poly_uint64 base,poly_uint64 step)192638fd1498Szrj build_index_vector (tree vec_type, poly_uint64 base, poly_uint64 step)
192738fd1498Szrj {
192838fd1498Szrj tree index_vec_type = vec_type;
192938fd1498Szrj tree index_elt_type = TREE_TYPE (vec_type);
193038fd1498Szrj poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vec_type);
193138fd1498Szrj if (!INTEGRAL_TYPE_P (index_elt_type) || !TYPE_UNSIGNED (index_elt_type))
193238fd1498Szrj {
193338fd1498Szrj index_elt_type = build_nonstandard_integer_type
193438fd1498Szrj (GET_MODE_BITSIZE (SCALAR_TYPE_MODE (index_elt_type)), true);
193538fd1498Szrj index_vec_type = build_vector_type (index_elt_type, nunits);
193638fd1498Szrj }
193738fd1498Szrj
193838fd1498Szrj tree_vector_builder v (index_vec_type, 1, 3);
193938fd1498Szrj for (unsigned int i = 0; i < 3; ++i)
194038fd1498Szrj v.quick_push (build_int_cstu (index_elt_type, base + i * step));
194138fd1498Szrj return v.build ();
194238fd1498Szrj }
194338fd1498Szrj
194438fd1498Szrj /* Something has messed with the elements of CONSTRUCTOR C after it was built;
194538fd1498Szrj calculate TREE_CONSTANT and TREE_SIDE_EFFECTS. */
194638fd1498Szrj
194738fd1498Szrj void
recompute_constructor_flags(tree c)194838fd1498Szrj recompute_constructor_flags (tree c)
194938fd1498Szrj {
195038fd1498Szrj unsigned int i;
195138fd1498Szrj tree val;
195238fd1498Szrj bool constant_p = true;
195338fd1498Szrj bool side_effects_p = false;
195438fd1498Szrj vec<constructor_elt, va_gc> *vals = CONSTRUCTOR_ELTS (c);
195538fd1498Szrj
195638fd1498Szrj FOR_EACH_CONSTRUCTOR_VALUE (vals, i, val)
195738fd1498Szrj {
195838fd1498Szrj /* Mostly ctors will have elts that don't have side-effects, so
195938fd1498Szrj the usual case is to scan all the elements. Hence a single
196038fd1498Szrj loop for both const and side effects, rather than one loop
196138fd1498Szrj each (with early outs). */
196238fd1498Szrj if (!TREE_CONSTANT (val))
196338fd1498Szrj constant_p = false;
196438fd1498Szrj if (TREE_SIDE_EFFECTS (val))
196538fd1498Szrj side_effects_p = true;
196638fd1498Szrj }
196738fd1498Szrj
196838fd1498Szrj TREE_SIDE_EFFECTS (c) = side_effects_p;
196938fd1498Szrj TREE_CONSTANT (c) = constant_p;
197038fd1498Szrj }
197138fd1498Szrj
197238fd1498Szrj /* Make sure that TREE_CONSTANT and TREE_SIDE_EFFECTS are correct for
197338fd1498Szrj CONSTRUCTOR C. */
197438fd1498Szrj
197538fd1498Szrj void
verify_constructor_flags(tree c)197638fd1498Szrj verify_constructor_flags (tree c)
197738fd1498Szrj {
197838fd1498Szrj unsigned int i;
197938fd1498Szrj tree val;
198038fd1498Szrj bool constant_p = TREE_CONSTANT (c);
198138fd1498Szrj bool side_effects_p = TREE_SIDE_EFFECTS (c);
198238fd1498Szrj vec<constructor_elt, va_gc> *vals = CONSTRUCTOR_ELTS (c);
198338fd1498Szrj
198438fd1498Szrj FOR_EACH_CONSTRUCTOR_VALUE (vals, i, val)
198538fd1498Szrj {
198638fd1498Szrj if (constant_p && !TREE_CONSTANT (val))
198738fd1498Szrj internal_error ("non-constant element in constant CONSTRUCTOR");
198838fd1498Szrj if (!side_effects_p && TREE_SIDE_EFFECTS (val))
198938fd1498Szrj internal_error ("side-effects element in no-side-effects CONSTRUCTOR");
199038fd1498Szrj }
199138fd1498Szrj }
199238fd1498Szrj
199338fd1498Szrj /* Return a new CONSTRUCTOR node whose type is TYPE and whose values
199438fd1498Szrj are in the vec pointed to by VALS. */
199538fd1498Szrj tree
build_constructor(tree type,vec<constructor_elt,va_gc> * vals)199638fd1498Szrj build_constructor (tree type, vec<constructor_elt, va_gc> *vals)
199738fd1498Szrj {
199838fd1498Szrj tree c = make_node (CONSTRUCTOR);
199938fd1498Szrj
200038fd1498Szrj TREE_TYPE (c) = type;
200138fd1498Szrj CONSTRUCTOR_ELTS (c) = vals;
200238fd1498Szrj
200338fd1498Szrj recompute_constructor_flags (c);
200438fd1498Szrj
200538fd1498Szrj return c;
200638fd1498Szrj }
200738fd1498Szrj
200838fd1498Szrj /* Build a CONSTRUCTOR node made of a single initializer, with the specified
200938fd1498Szrj INDEX and VALUE. */
201038fd1498Szrj tree
build_constructor_single(tree type,tree index,tree value)201138fd1498Szrj build_constructor_single (tree type, tree index, tree value)
201238fd1498Szrj {
201338fd1498Szrj vec<constructor_elt, va_gc> *v;
201438fd1498Szrj constructor_elt elt = {index, value};
201538fd1498Szrj
201638fd1498Szrj vec_alloc (v, 1);
201738fd1498Szrj v->quick_push (elt);
201838fd1498Szrj
201938fd1498Szrj return build_constructor (type, v);
202038fd1498Szrj }
202138fd1498Szrj
202238fd1498Szrj
202338fd1498Szrj /* Return a new CONSTRUCTOR node whose type is TYPE and whose values
202438fd1498Szrj are in a list pointed to by VALS. */
202538fd1498Szrj tree
build_constructor_from_list(tree type,tree vals)202638fd1498Szrj build_constructor_from_list (tree type, tree vals)
202738fd1498Szrj {
202838fd1498Szrj tree t;
202938fd1498Szrj vec<constructor_elt, va_gc> *v = NULL;
203038fd1498Szrj
203138fd1498Szrj if (vals)
203238fd1498Szrj {
203338fd1498Szrj vec_alloc (v, list_length (vals));
203438fd1498Szrj for (t = vals; t; t = TREE_CHAIN (t))
203538fd1498Szrj CONSTRUCTOR_APPEND_ELT (v, TREE_PURPOSE (t), TREE_VALUE (t));
203638fd1498Szrj }
203738fd1498Szrj
203838fd1498Szrj return build_constructor (type, v);
203938fd1498Szrj }
204038fd1498Szrj
204138fd1498Szrj /* Return a new CONSTRUCTOR node whose type is TYPE. NELTS is the number
204238fd1498Szrj of elements, provided as index/value pairs. */
204338fd1498Szrj
204438fd1498Szrj tree
build_constructor_va(tree type,int nelts,...)204538fd1498Szrj build_constructor_va (tree type, int nelts, ...)
204638fd1498Szrj {
204738fd1498Szrj vec<constructor_elt, va_gc> *v = NULL;
204838fd1498Szrj va_list p;
204938fd1498Szrj
205038fd1498Szrj va_start (p, nelts);
205138fd1498Szrj vec_alloc (v, nelts);
205238fd1498Szrj while (nelts--)
205338fd1498Szrj {
205438fd1498Szrj tree index = va_arg (p, tree);
205538fd1498Szrj tree value = va_arg (p, tree);
205638fd1498Szrj CONSTRUCTOR_APPEND_ELT (v, index, value);
205738fd1498Szrj }
205838fd1498Szrj va_end (p);
205938fd1498Szrj return build_constructor (type, v);
206038fd1498Szrj }
206138fd1498Szrj
206238fd1498Szrj /* Return a new FIXED_CST node whose type is TYPE and value is F. */
206338fd1498Szrj
206438fd1498Szrj tree
build_fixed(tree type,FIXED_VALUE_TYPE f)206538fd1498Szrj build_fixed (tree type, FIXED_VALUE_TYPE f)
206638fd1498Szrj {
206738fd1498Szrj tree v;
206838fd1498Szrj FIXED_VALUE_TYPE *fp;
206938fd1498Szrj
207038fd1498Szrj v = make_node (FIXED_CST);
207138fd1498Szrj fp = ggc_alloc<fixed_value> ();
207238fd1498Szrj memcpy (fp, &f, sizeof (FIXED_VALUE_TYPE));
207338fd1498Szrj
207438fd1498Szrj TREE_TYPE (v) = type;
207538fd1498Szrj TREE_FIXED_CST_PTR (v) = fp;
207638fd1498Szrj return v;
207738fd1498Szrj }
207838fd1498Szrj
207938fd1498Szrj /* Return a new REAL_CST node whose type is TYPE and value is D. */
208038fd1498Szrj
208138fd1498Szrj tree
build_real(tree type,REAL_VALUE_TYPE d)208238fd1498Szrj build_real (tree type, REAL_VALUE_TYPE d)
208338fd1498Szrj {
208438fd1498Szrj tree v;
208538fd1498Szrj REAL_VALUE_TYPE *dp;
208638fd1498Szrj int overflow = 0;
208738fd1498Szrj
208838fd1498Szrj /* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
208938fd1498Szrj Consider doing it via real_convert now. */
209038fd1498Szrj
209138fd1498Szrj v = make_node (REAL_CST);
209238fd1498Szrj dp = ggc_alloc<real_value> ();
209338fd1498Szrj memcpy (dp, &d, sizeof (REAL_VALUE_TYPE));
209438fd1498Szrj
209538fd1498Szrj TREE_TYPE (v) = type;
209638fd1498Szrj TREE_REAL_CST_PTR (v) = dp;
209738fd1498Szrj TREE_OVERFLOW (v) = overflow;
209838fd1498Szrj return v;
209938fd1498Szrj }
210038fd1498Szrj
210138fd1498Szrj /* Like build_real, but first truncate D to the type. */
210238fd1498Szrj
210338fd1498Szrj tree
build_real_truncate(tree type,REAL_VALUE_TYPE d)210438fd1498Szrj build_real_truncate (tree type, REAL_VALUE_TYPE d)
210538fd1498Szrj {
210638fd1498Szrj return build_real (type, real_value_truncate (TYPE_MODE (type), d));
210738fd1498Szrj }
210838fd1498Szrj
210938fd1498Szrj /* Return a new REAL_CST node whose type is TYPE
211038fd1498Szrj and whose value is the integer value of the INTEGER_CST node I. */
211138fd1498Szrj
211238fd1498Szrj REAL_VALUE_TYPE
real_value_from_int_cst(const_tree type,const_tree i)211338fd1498Szrj real_value_from_int_cst (const_tree type, const_tree i)
211438fd1498Szrj {
211538fd1498Szrj REAL_VALUE_TYPE d;
211638fd1498Szrj
211738fd1498Szrj /* Clear all bits of the real value type so that we can later do
211838fd1498Szrj bitwise comparisons to see if two values are the same. */
211938fd1498Szrj memset (&d, 0, sizeof d);
212038fd1498Szrj
212138fd1498Szrj real_from_integer (&d, type ? TYPE_MODE (type) : VOIDmode, wi::to_wide (i),
212238fd1498Szrj TYPE_SIGN (TREE_TYPE (i)));
212338fd1498Szrj return d;
212438fd1498Szrj }
212538fd1498Szrj
212638fd1498Szrj /* Given a tree representing an integer constant I, return a tree
212738fd1498Szrj representing the same value as a floating-point constant of type TYPE. */
212838fd1498Szrj
212938fd1498Szrj tree
build_real_from_int_cst(tree type,const_tree i)213038fd1498Szrj build_real_from_int_cst (tree type, const_tree i)
213138fd1498Szrj {
213238fd1498Szrj tree v;
213338fd1498Szrj int overflow = TREE_OVERFLOW (i);
213438fd1498Szrj
213538fd1498Szrj v = build_real (type, real_value_from_int_cst (type, i));
213638fd1498Szrj
213738fd1498Szrj TREE_OVERFLOW (v) |= overflow;
213838fd1498Szrj return v;
213938fd1498Szrj }
214038fd1498Szrj
214138fd1498Szrj /* Return a newly constructed STRING_CST node whose value is
214238fd1498Szrj the LEN characters at STR.
214338fd1498Szrj Note that for a C string literal, LEN should include the trailing NUL.
214438fd1498Szrj The TREE_TYPE is not initialized. */
214538fd1498Szrj
214638fd1498Szrj tree
build_string(int len,const char * str)214738fd1498Szrj build_string (int len, const char *str)
214838fd1498Szrj {
214938fd1498Szrj tree s;
215038fd1498Szrj size_t length;
215138fd1498Szrj
215238fd1498Szrj /* Do not waste bytes provided by padding of struct tree_string. */
215338fd1498Szrj length = len + offsetof (struct tree_string, str) + 1;
215438fd1498Szrj
215538fd1498Szrj record_node_allocation_statistics (STRING_CST, length);
215638fd1498Szrj
215738fd1498Szrj s = (tree) ggc_internal_alloc (length);
215838fd1498Szrj
215938fd1498Szrj memset (s, 0, sizeof (struct tree_typed));
216038fd1498Szrj TREE_SET_CODE (s, STRING_CST);
216138fd1498Szrj TREE_CONSTANT (s) = 1;
216238fd1498Szrj TREE_STRING_LENGTH (s) = len;
216338fd1498Szrj memcpy (s->string.str, str, len);
216438fd1498Szrj s->string.str[len] = '\0';
216538fd1498Szrj
216638fd1498Szrj return s;
216738fd1498Szrj }
216838fd1498Szrj
216938fd1498Szrj /* Return a newly constructed COMPLEX_CST node whose value is
217038fd1498Szrj specified by the real and imaginary parts REAL and IMAG.
217138fd1498Szrj Both REAL and IMAG should be constant nodes. TYPE, if specified,
217238fd1498Szrj will be the type of the COMPLEX_CST; otherwise a new type will be made. */
217338fd1498Szrj
217438fd1498Szrj tree
build_complex(tree type,tree real,tree imag)217538fd1498Szrj build_complex (tree type, tree real, tree imag)
217638fd1498Szrj {
217738fd1498Szrj tree t = make_node (COMPLEX_CST);
217838fd1498Szrj
217938fd1498Szrj TREE_REALPART (t) = real;
218038fd1498Szrj TREE_IMAGPART (t) = imag;
218138fd1498Szrj TREE_TYPE (t) = type ? type : build_complex_type (TREE_TYPE (real));
218238fd1498Szrj TREE_OVERFLOW (t) = TREE_OVERFLOW (real) | TREE_OVERFLOW (imag);
218338fd1498Szrj return t;
218438fd1498Szrj }
218538fd1498Szrj
218638fd1498Szrj /* Build a complex (inf +- 0i), such as for the result of cproj.
218738fd1498Szrj TYPE is the complex tree type of the result. If NEG is true, the
218838fd1498Szrj imaginary zero is negative. */
218938fd1498Szrj
219038fd1498Szrj tree
build_complex_inf(tree type,bool neg)219138fd1498Szrj build_complex_inf (tree type, bool neg)
219238fd1498Szrj {
219338fd1498Szrj REAL_VALUE_TYPE rinf, rzero = dconst0;
219438fd1498Szrj
219538fd1498Szrj real_inf (&rinf);
219638fd1498Szrj rzero.sign = neg;
219738fd1498Szrj return build_complex (type, build_real (TREE_TYPE (type), rinf),
219838fd1498Szrj build_real (TREE_TYPE (type), rzero));
219938fd1498Szrj }
220038fd1498Szrj
220138fd1498Szrj /* Return the constant 1 in type TYPE. If TYPE has several elements, each
220238fd1498Szrj element is set to 1. In particular, this is 1 + i for complex types. */
220338fd1498Szrj
220438fd1498Szrj tree
build_each_one_cst(tree type)220538fd1498Szrj build_each_one_cst (tree type)
220638fd1498Szrj {
220738fd1498Szrj if (TREE_CODE (type) == COMPLEX_TYPE)
220838fd1498Szrj {
220938fd1498Szrj tree scalar = build_one_cst (TREE_TYPE (type));
221038fd1498Szrj return build_complex (type, scalar, scalar);
221138fd1498Szrj }
221238fd1498Szrj else
221338fd1498Szrj return build_one_cst (type);
221438fd1498Szrj }
221538fd1498Szrj
221638fd1498Szrj /* Return a constant of arithmetic type TYPE which is the
221738fd1498Szrj multiplicative identity of the set TYPE. */
221838fd1498Szrj
221938fd1498Szrj tree
build_one_cst(tree type)222038fd1498Szrj build_one_cst (tree type)
222138fd1498Szrj {
222238fd1498Szrj switch (TREE_CODE (type))
222338fd1498Szrj {
222438fd1498Szrj case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
222538fd1498Szrj case POINTER_TYPE: case REFERENCE_TYPE:
222638fd1498Szrj case OFFSET_TYPE:
222738fd1498Szrj return build_int_cst (type, 1);
222838fd1498Szrj
222938fd1498Szrj case REAL_TYPE:
223038fd1498Szrj return build_real (type, dconst1);
223138fd1498Szrj
223238fd1498Szrj case FIXED_POINT_TYPE:
223338fd1498Szrj /* We can only generate 1 for accum types. */
223438fd1498Szrj gcc_assert (ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type)));
223538fd1498Szrj return build_fixed (type, FCONST1 (TYPE_MODE (type)));
223638fd1498Szrj
223738fd1498Szrj case VECTOR_TYPE:
223838fd1498Szrj {
223938fd1498Szrj tree scalar = build_one_cst (TREE_TYPE (type));
224038fd1498Szrj
224138fd1498Szrj return build_vector_from_val (type, scalar);
224238fd1498Szrj }
224338fd1498Szrj
224438fd1498Szrj case COMPLEX_TYPE:
224538fd1498Szrj return build_complex (type,
224638fd1498Szrj build_one_cst (TREE_TYPE (type)),
224738fd1498Szrj build_zero_cst (TREE_TYPE (type)));
224838fd1498Szrj
224938fd1498Szrj default:
225038fd1498Szrj gcc_unreachable ();
225138fd1498Szrj }
225238fd1498Szrj }
225338fd1498Szrj
225438fd1498Szrj /* Return an integer of type TYPE containing all 1's in as much precision as
225538fd1498Szrj it contains, or a complex or vector whose subparts are such integers. */
225638fd1498Szrj
225738fd1498Szrj tree
build_all_ones_cst(tree type)225838fd1498Szrj build_all_ones_cst (tree type)
225938fd1498Szrj {
226038fd1498Szrj if (TREE_CODE (type) == COMPLEX_TYPE)
226138fd1498Szrj {
226238fd1498Szrj tree scalar = build_all_ones_cst (TREE_TYPE (type));
226338fd1498Szrj return build_complex (type, scalar, scalar);
226438fd1498Szrj }
226538fd1498Szrj else
226638fd1498Szrj return build_minus_one_cst (type);
226738fd1498Szrj }
226838fd1498Szrj
226938fd1498Szrj /* Return a constant of arithmetic type TYPE which is the
227038fd1498Szrj opposite of the multiplicative identity of the set TYPE. */
227138fd1498Szrj
227238fd1498Szrj tree
build_minus_one_cst(tree type)227338fd1498Szrj build_minus_one_cst (tree type)
227438fd1498Szrj {
227538fd1498Szrj switch (TREE_CODE (type))
227638fd1498Szrj {
227738fd1498Szrj case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
227838fd1498Szrj case POINTER_TYPE: case REFERENCE_TYPE:
227938fd1498Szrj case OFFSET_TYPE:
228038fd1498Szrj return build_int_cst (type, -1);
228138fd1498Szrj
228238fd1498Szrj case REAL_TYPE:
228338fd1498Szrj return build_real (type, dconstm1);
228438fd1498Szrj
228538fd1498Szrj case FIXED_POINT_TYPE:
228638fd1498Szrj /* We can only generate 1 for accum types. */
228738fd1498Szrj gcc_assert (ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type)));
228838fd1498Szrj return build_fixed (type,
228938fd1498Szrj fixed_from_double_int (double_int_minus_one,
229038fd1498Szrj SCALAR_TYPE_MODE (type)));
229138fd1498Szrj
229238fd1498Szrj case VECTOR_TYPE:
229338fd1498Szrj {
229438fd1498Szrj tree scalar = build_minus_one_cst (TREE_TYPE (type));
229538fd1498Szrj
229638fd1498Szrj return build_vector_from_val (type, scalar);
229738fd1498Szrj }
229838fd1498Szrj
229938fd1498Szrj case COMPLEX_TYPE:
230038fd1498Szrj return build_complex (type,
230138fd1498Szrj build_minus_one_cst (TREE_TYPE (type)),
230238fd1498Szrj build_zero_cst (TREE_TYPE (type)));
230338fd1498Szrj
230438fd1498Szrj default:
230538fd1498Szrj gcc_unreachable ();
230638fd1498Szrj }
230738fd1498Szrj }
230838fd1498Szrj
230938fd1498Szrj /* Build 0 constant of type TYPE. This is used by constructor folding
231038fd1498Szrj and thus the constant should be represented in memory by
231138fd1498Szrj zero(es). */
231238fd1498Szrj
231338fd1498Szrj tree
build_zero_cst(tree type)231438fd1498Szrj build_zero_cst (tree type)
231538fd1498Szrj {
231638fd1498Szrj switch (TREE_CODE (type))
231738fd1498Szrj {
231838fd1498Szrj case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
231938fd1498Szrj case POINTER_TYPE: case REFERENCE_TYPE:
232038fd1498Szrj case OFFSET_TYPE: case NULLPTR_TYPE:
232138fd1498Szrj return build_int_cst (type, 0);
232238fd1498Szrj
232338fd1498Szrj case REAL_TYPE:
232438fd1498Szrj return build_real (type, dconst0);
232538fd1498Szrj
232638fd1498Szrj case FIXED_POINT_TYPE:
232738fd1498Szrj return build_fixed (type, FCONST0 (TYPE_MODE (type)));
232838fd1498Szrj
232938fd1498Szrj case VECTOR_TYPE:
233038fd1498Szrj {
233138fd1498Szrj tree scalar = build_zero_cst (TREE_TYPE (type));
233238fd1498Szrj
233338fd1498Szrj return build_vector_from_val (type, scalar);
233438fd1498Szrj }
233538fd1498Szrj
233638fd1498Szrj case COMPLEX_TYPE:
233738fd1498Szrj {
233838fd1498Szrj tree zero = build_zero_cst (TREE_TYPE (type));
233938fd1498Szrj
234038fd1498Szrj return build_complex (type, zero, zero);
234138fd1498Szrj }
234238fd1498Szrj
234338fd1498Szrj default:
234438fd1498Szrj if (!AGGREGATE_TYPE_P (type))
234538fd1498Szrj return fold_convert (type, integer_zero_node);
234638fd1498Szrj return build_constructor (type, NULL);
234738fd1498Szrj }
234838fd1498Szrj }
234938fd1498Szrj
235038fd1498Szrj
235138fd1498Szrj /* Build a BINFO with LEN language slots. */
235238fd1498Szrj
235338fd1498Szrj tree
make_tree_binfo(unsigned base_binfos MEM_STAT_DECL)235438fd1498Szrj make_tree_binfo (unsigned base_binfos MEM_STAT_DECL)
235538fd1498Szrj {
235638fd1498Szrj tree t;
235738fd1498Szrj size_t length = (offsetof (struct tree_binfo, base_binfos)
235838fd1498Szrj + vec<tree, va_gc>::embedded_size (base_binfos));
235938fd1498Szrj
236038fd1498Szrj record_node_allocation_statistics (TREE_BINFO, length);
236138fd1498Szrj
236238fd1498Szrj t = ggc_alloc_tree_node_stat (length PASS_MEM_STAT);
236338fd1498Szrj
236438fd1498Szrj memset (t, 0, offsetof (struct tree_binfo, base_binfos));
236538fd1498Szrj
236638fd1498Szrj TREE_SET_CODE (t, TREE_BINFO);
236738fd1498Szrj
236838fd1498Szrj BINFO_BASE_BINFOS (t)->embedded_init (base_binfos);
236938fd1498Szrj
237038fd1498Szrj return t;
237138fd1498Szrj }
237238fd1498Szrj
237338fd1498Szrj /* Create a CASE_LABEL_EXPR tree node and return it. */
237438fd1498Szrj
237538fd1498Szrj tree
build_case_label(tree low_value,tree high_value,tree label_decl)237638fd1498Szrj build_case_label (tree low_value, tree high_value, tree label_decl)
237738fd1498Szrj {
237838fd1498Szrj tree t = make_node (CASE_LABEL_EXPR);
237938fd1498Szrj
238038fd1498Szrj TREE_TYPE (t) = void_type_node;
238138fd1498Szrj SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (label_decl));
238238fd1498Szrj
238338fd1498Szrj CASE_LOW (t) = low_value;
238438fd1498Szrj CASE_HIGH (t) = high_value;
238538fd1498Szrj CASE_LABEL (t) = label_decl;
238638fd1498Szrj CASE_CHAIN (t) = NULL_TREE;
238738fd1498Szrj
238838fd1498Szrj return t;
238938fd1498Szrj }
239038fd1498Szrj
239138fd1498Szrj /* Build a newly constructed INTEGER_CST node. LEN and EXT_LEN are the
239238fd1498Szrj values of TREE_INT_CST_NUNITS and TREE_INT_CST_EXT_NUNITS respectively.
239338fd1498Szrj The latter determines the length of the HOST_WIDE_INT vector. */
239438fd1498Szrj
239538fd1498Szrj tree
make_int_cst(int len,int ext_len MEM_STAT_DECL)239638fd1498Szrj make_int_cst (int len, int ext_len MEM_STAT_DECL)
239738fd1498Szrj {
239838fd1498Szrj tree t;
239938fd1498Szrj int length = ((ext_len - 1) * sizeof (HOST_WIDE_INT)
240038fd1498Szrj + sizeof (struct tree_int_cst));
240138fd1498Szrj
240238fd1498Szrj gcc_assert (len);
240338fd1498Szrj record_node_allocation_statistics (INTEGER_CST, length);
240438fd1498Szrj
240538fd1498Szrj t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT);
240638fd1498Szrj
240738fd1498Szrj TREE_SET_CODE (t, INTEGER_CST);
240838fd1498Szrj TREE_INT_CST_NUNITS (t) = len;
240938fd1498Szrj TREE_INT_CST_EXT_NUNITS (t) = ext_len;
241038fd1498Szrj /* to_offset can only be applied to trees that are offset_int-sized
241138fd1498Szrj or smaller. EXT_LEN is correct if it fits, otherwise the constant
241238fd1498Szrj must be exactly the precision of offset_int and so LEN is correct. */
241338fd1498Szrj if (ext_len <= OFFSET_INT_ELTS)
241438fd1498Szrj TREE_INT_CST_OFFSET_NUNITS (t) = ext_len;
241538fd1498Szrj else
241638fd1498Szrj TREE_INT_CST_OFFSET_NUNITS (t) = len;
241738fd1498Szrj
241838fd1498Szrj TREE_CONSTANT (t) = 1;
241938fd1498Szrj
242038fd1498Szrj return t;
242138fd1498Szrj }
242238fd1498Szrj
242338fd1498Szrj /* Build a newly constructed TREE_VEC node of length LEN. */
242438fd1498Szrj
242538fd1498Szrj tree
make_tree_vec(int len MEM_STAT_DECL)242638fd1498Szrj make_tree_vec (int len MEM_STAT_DECL)
242738fd1498Szrj {
242838fd1498Szrj tree t;
242938fd1498Szrj size_t length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
243038fd1498Szrj
243138fd1498Szrj record_node_allocation_statistics (TREE_VEC, length);
243238fd1498Szrj
243338fd1498Szrj t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT);
243438fd1498Szrj
243538fd1498Szrj TREE_SET_CODE (t, TREE_VEC);
243638fd1498Szrj TREE_VEC_LENGTH (t) = len;
243738fd1498Szrj
243838fd1498Szrj return t;
243938fd1498Szrj }
244038fd1498Szrj
244138fd1498Szrj /* Grow a TREE_VEC node to new length LEN. */
244238fd1498Szrj
244338fd1498Szrj tree
grow_tree_vec(tree v,int len MEM_STAT_DECL)244438fd1498Szrj grow_tree_vec (tree v, int len MEM_STAT_DECL)
244538fd1498Szrj {
244638fd1498Szrj gcc_assert (TREE_CODE (v) == TREE_VEC);
244738fd1498Szrj
244838fd1498Szrj int oldlen = TREE_VEC_LENGTH (v);
244938fd1498Szrj gcc_assert (len > oldlen);
245038fd1498Szrj
245138fd1498Szrj size_t oldlength = (oldlen - 1) * sizeof (tree) + sizeof (struct tree_vec);
245238fd1498Szrj size_t length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
245338fd1498Szrj
245438fd1498Szrj record_node_allocation_statistics (TREE_VEC, length - oldlength);
245538fd1498Szrj
245638fd1498Szrj v = (tree) ggc_realloc (v, length PASS_MEM_STAT);
245738fd1498Szrj
245838fd1498Szrj TREE_VEC_LENGTH (v) = len;
245938fd1498Szrj
246038fd1498Szrj return v;
246138fd1498Szrj }
246238fd1498Szrj
246338fd1498Szrj /* Return 1 if EXPR is the constant zero, whether it is integral, float or
246438fd1498Szrj fixed, and scalar, complex or vector. */
246538fd1498Szrj
246638fd1498Szrj int
zerop(const_tree expr)246738fd1498Szrj zerop (const_tree expr)
246838fd1498Szrj {
246938fd1498Szrj return (integer_zerop (expr)
247038fd1498Szrj || real_zerop (expr)
247138fd1498Szrj || fixed_zerop (expr));
247238fd1498Szrj }
247338fd1498Szrj
247438fd1498Szrj /* Return 1 if EXPR is the integer constant zero or a complex constant
247538fd1498Szrj of zero. */
247638fd1498Szrj
247738fd1498Szrj int
integer_zerop(const_tree expr)247838fd1498Szrj integer_zerop (const_tree expr)
247938fd1498Szrj {
248038fd1498Szrj switch (TREE_CODE (expr))
248138fd1498Szrj {
248238fd1498Szrj case INTEGER_CST:
248338fd1498Szrj return wi::to_wide (expr) == 0;
248438fd1498Szrj case COMPLEX_CST:
248538fd1498Szrj return (integer_zerop (TREE_REALPART (expr))
248638fd1498Szrj && integer_zerop (TREE_IMAGPART (expr)));
248738fd1498Szrj case VECTOR_CST:
248838fd1498Szrj return (VECTOR_CST_NPATTERNS (expr) == 1
248938fd1498Szrj && VECTOR_CST_DUPLICATE_P (expr)
249038fd1498Szrj && integer_zerop (VECTOR_CST_ENCODED_ELT (expr, 0)));
249138fd1498Szrj default:
249238fd1498Szrj return false;
249338fd1498Szrj }
249438fd1498Szrj }
249538fd1498Szrj
249638fd1498Szrj /* Return 1 if EXPR is the integer constant one or the corresponding
249738fd1498Szrj complex constant. */
249838fd1498Szrj
249938fd1498Szrj int
integer_onep(const_tree expr)250038fd1498Szrj integer_onep (const_tree expr)
250138fd1498Szrj {
250238fd1498Szrj switch (TREE_CODE (expr))
250338fd1498Szrj {
250438fd1498Szrj case INTEGER_CST:
250538fd1498Szrj return wi::eq_p (wi::to_widest (expr), 1);
250638fd1498Szrj case COMPLEX_CST:
250738fd1498Szrj return (integer_onep (TREE_REALPART (expr))
250838fd1498Szrj && integer_zerop (TREE_IMAGPART (expr)));
250938fd1498Szrj case VECTOR_CST:
251038fd1498Szrj return (VECTOR_CST_NPATTERNS (expr) == 1
251138fd1498Szrj && VECTOR_CST_DUPLICATE_P (expr)
251238fd1498Szrj && integer_onep (VECTOR_CST_ENCODED_ELT (expr, 0)));
251338fd1498Szrj default:
251438fd1498Szrj return false;
251538fd1498Szrj }
251638fd1498Szrj }
251738fd1498Szrj
251838fd1498Szrj /* Return 1 if EXPR is the integer constant one. For complex and vector,
251938fd1498Szrj return 1 if every piece is the integer constant one. */
252038fd1498Szrj
252138fd1498Szrj int
integer_each_onep(const_tree expr)252238fd1498Szrj integer_each_onep (const_tree expr)
252338fd1498Szrj {
252438fd1498Szrj if (TREE_CODE (expr) == COMPLEX_CST)
252538fd1498Szrj return (integer_onep (TREE_REALPART (expr))
252638fd1498Szrj && integer_onep (TREE_IMAGPART (expr)));
252738fd1498Szrj else
252838fd1498Szrj return integer_onep (expr);
252938fd1498Szrj }
253038fd1498Szrj
253138fd1498Szrj /* Return 1 if EXPR is an integer containing all 1's in as much precision as
253238fd1498Szrj it contains, or a complex or vector whose subparts are such integers. */
253338fd1498Szrj
253438fd1498Szrj int
integer_all_onesp(const_tree expr)253538fd1498Szrj integer_all_onesp (const_tree expr)
253638fd1498Szrj {
253738fd1498Szrj if (TREE_CODE (expr) == COMPLEX_CST
253838fd1498Szrj && integer_all_onesp (TREE_REALPART (expr))
253938fd1498Szrj && integer_all_onesp (TREE_IMAGPART (expr)))
254038fd1498Szrj return 1;
254138fd1498Szrj
254238fd1498Szrj else if (TREE_CODE (expr) == VECTOR_CST)
254338fd1498Szrj return (VECTOR_CST_NPATTERNS (expr) == 1
254438fd1498Szrj && VECTOR_CST_DUPLICATE_P (expr)
254538fd1498Szrj && integer_all_onesp (VECTOR_CST_ENCODED_ELT (expr, 0)));
254638fd1498Szrj
254738fd1498Szrj else if (TREE_CODE (expr) != INTEGER_CST)
254838fd1498Szrj return 0;
254938fd1498Szrj
255038fd1498Szrj return (wi::max_value (TYPE_PRECISION (TREE_TYPE (expr)), UNSIGNED)
255138fd1498Szrj == wi::to_wide (expr));
255238fd1498Szrj }
255338fd1498Szrj
255438fd1498Szrj /* Return 1 if EXPR is the integer constant minus one. */
255538fd1498Szrj
255638fd1498Szrj int
integer_minus_onep(const_tree expr)255738fd1498Szrj integer_minus_onep (const_tree expr)
255838fd1498Szrj {
255938fd1498Szrj if (TREE_CODE (expr) == COMPLEX_CST)
256038fd1498Szrj return (integer_all_onesp (TREE_REALPART (expr))
256138fd1498Szrj && integer_zerop (TREE_IMAGPART (expr)));
256238fd1498Szrj else
256338fd1498Szrj return integer_all_onesp (expr);
256438fd1498Szrj }
256538fd1498Szrj
256638fd1498Szrj /* Return 1 if EXPR is an integer constant that is a power of 2 (i.e., has only
256738fd1498Szrj one bit on). */
256838fd1498Szrj
256938fd1498Szrj int
integer_pow2p(const_tree expr)257038fd1498Szrj integer_pow2p (const_tree expr)
257138fd1498Szrj {
257238fd1498Szrj if (TREE_CODE (expr) == COMPLEX_CST
257338fd1498Szrj && integer_pow2p (TREE_REALPART (expr))
257438fd1498Szrj && integer_zerop (TREE_IMAGPART (expr)))
257538fd1498Szrj return 1;
257638fd1498Szrj
257738fd1498Szrj if (TREE_CODE (expr) != INTEGER_CST)
257838fd1498Szrj return 0;
257938fd1498Szrj
258038fd1498Szrj return wi::popcount (wi::to_wide (expr)) == 1;
258138fd1498Szrj }
258238fd1498Szrj
258338fd1498Szrj /* Return 1 if EXPR is an integer constant other than zero or a
258438fd1498Szrj complex constant other than zero. */
258538fd1498Szrj
258638fd1498Szrj int
integer_nonzerop(const_tree expr)258738fd1498Szrj integer_nonzerop (const_tree expr)
258838fd1498Szrj {
258938fd1498Szrj return ((TREE_CODE (expr) == INTEGER_CST
259038fd1498Szrj && wi::to_wide (expr) != 0)
259138fd1498Szrj || (TREE_CODE (expr) == COMPLEX_CST
259238fd1498Szrj && (integer_nonzerop (TREE_REALPART (expr))
259338fd1498Szrj || integer_nonzerop (TREE_IMAGPART (expr)))));
259438fd1498Szrj }
259538fd1498Szrj
259638fd1498Szrj /* Return 1 if EXPR is the integer constant one. For vector,
259738fd1498Szrj return 1 if every piece is the integer constant minus one
259838fd1498Szrj (representing the value TRUE). */
259938fd1498Szrj
260038fd1498Szrj int
integer_truep(const_tree expr)260138fd1498Szrj integer_truep (const_tree expr)
260238fd1498Szrj {
260338fd1498Szrj if (TREE_CODE (expr) == VECTOR_CST)
260438fd1498Szrj return integer_all_onesp (expr);
260538fd1498Szrj return integer_onep (expr);
260638fd1498Szrj }
260738fd1498Szrj
260838fd1498Szrj /* Return 1 if EXPR is the fixed-point constant zero. */
260938fd1498Szrj
261038fd1498Szrj int
fixed_zerop(const_tree expr)261138fd1498Szrj fixed_zerop (const_tree expr)
261238fd1498Szrj {
261338fd1498Szrj return (TREE_CODE (expr) == FIXED_CST
261438fd1498Szrj && TREE_FIXED_CST (expr).data.is_zero ());
261538fd1498Szrj }
261638fd1498Szrj
261738fd1498Szrj /* Return the power of two represented by a tree node known to be a
261838fd1498Szrj power of two. */
261938fd1498Szrj
262038fd1498Szrj int
tree_log2(const_tree expr)262138fd1498Szrj tree_log2 (const_tree expr)
262238fd1498Szrj {
262338fd1498Szrj if (TREE_CODE (expr) == COMPLEX_CST)
262438fd1498Szrj return tree_log2 (TREE_REALPART (expr));
262538fd1498Szrj
262638fd1498Szrj return wi::exact_log2 (wi::to_wide (expr));
262738fd1498Szrj }
262838fd1498Szrj
262938fd1498Szrj /* Similar, but return the largest integer Y such that 2 ** Y is less
263038fd1498Szrj than or equal to EXPR. */
263138fd1498Szrj
263238fd1498Szrj int
tree_floor_log2(const_tree expr)263338fd1498Szrj tree_floor_log2 (const_tree expr)
263438fd1498Szrj {
263538fd1498Szrj if (TREE_CODE (expr) == COMPLEX_CST)
263638fd1498Szrj return tree_log2 (TREE_REALPART (expr));
263738fd1498Szrj
263838fd1498Szrj return wi::floor_log2 (wi::to_wide (expr));
263938fd1498Szrj }
264038fd1498Szrj
264138fd1498Szrj /* Return number of known trailing zero bits in EXPR, or, if the value of
264238fd1498Szrj EXPR is known to be zero, the precision of it's type. */
264338fd1498Szrj
264438fd1498Szrj unsigned int
tree_ctz(const_tree expr)264538fd1498Szrj tree_ctz (const_tree expr)
264638fd1498Szrj {
264738fd1498Szrj if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
264838fd1498Szrj && !POINTER_TYPE_P (TREE_TYPE (expr)))
264938fd1498Szrj return 0;
265038fd1498Szrj
265138fd1498Szrj unsigned int ret1, ret2, prec = TYPE_PRECISION (TREE_TYPE (expr));
265238fd1498Szrj switch (TREE_CODE (expr))
265338fd1498Szrj {
265438fd1498Szrj case INTEGER_CST:
265538fd1498Szrj ret1 = wi::ctz (wi::to_wide (expr));
265638fd1498Szrj return MIN (ret1, prec);
265738fd1498Szrj case SSA_NAME:
265838fd1498Szrj ret1 = wi::ctz (get_nonzero_bits (expr));
265938fd1498Szrj return MIN (ret1, prec);
266038fd1498Szrj case PLUS_EXPR:
266138fd1498Szrj case MINUS_EXPR:
266238fd1498Szrj case BIT_IOR_EXPR:
266338fd1498Szrj case BIT_XOR_EXPR:
266438fd1498Szrj case MIN_EXPR:
266538fd1498Szrj case MAX_EXPR:
266638fd1498Szrj ret1 = tree_ctz (TREE_OPERAND (expr, 0));
266738fd1498Szrj if (ret1 == 0)
266838fd1498Szrj return ret1;
266938fd1498Szrj ret2 = tree_ctz (TREE_OPERAND (expr, 1));
267038fd1498Szrj return MIN (ret1, ret2);
267138fd1498Szrj case POINTER_PLUS_EXPR:
267238fd1498Szrj ret1 = tree_ctz (TREE_OPERAND (expr, 0));
267338fd1498Szrj ret2 = tree_ctz (TREE_OPERAND (expr, 1));
267438fd1498Szrj /* Second operand is sizetype, which could be in theory
267538fd1498Szrj wider than pointer's precision. Make sure we never
267638fd1498Szrj return more than prec. */
267738fd1498Szrj ret2 = MIN (ret2, prec);
267838fd1498Szrj return MIN (ret1, ret2);
267938fd1498Szrj case BIT_AND_EXPR:
268038fd1498Szrj ret1 = tree_ctz (TREE_OPERAND (expr, 0));
268138fd1498Szrj ret2 = tree_ctz (TREE_OPERAND (expr, 1));
268238fd1498Szrj return MAX (ret1, ret2);
268338fd1498Szrj case MULT_EXPR:
268438fd1498Szrj ret1 = tree_ctz (TREE_OPERAND (expr, 0));
268538fd1498Szrj ret2 = tree_ctz (TREE_OPERAND (expr, 1));
268638fd1498Szrj return MIN (ret1 + ret2, prec);
268738fd1498Szrj case LSHIFT_EXPR:
268838fd1498Szrj ret1 = tree_ctz (TREE_OPERAND (expr, 0));
268938fd1498Szrj if (tree_fits_uhwi_p (TREE_OPERAND (expr, 1))
269038fd1498Szrj && (tree_to_uhwi (TREE_OPERAND (expr, 1)) < prec))
269138fd1498Szrj {
269238fd1498Szrj ret2 = tree_to_uhwi (TREE_OPERAND (expr, 1));
269338fd1498Szrj return MIN (ret1 + ret2, prec);
269438fd1498Szrj }
269538fd1498Szrj return ret1;
269638fd1498Szrj case RSHIFT_EXPR:
269738fd1498Szrj if (tree_fits_uhwi_p (TREE_OPERAND (expr, 1))
269838fd1498Szrj && (tree_to_uhwi (TREE_OPERAND (expr, 1)) < prec))
269938fd1498Szrj {
270038fd1498Szrj ret1 = tree_ctz (TREE_OPERAND (expr, 0));
270138fd1498Szrj ret2 = tree_to_uhwi (TREE_OPERAND (expr, 1));
270238fd1498Szrj if (ret1 > ret2)
270338fd1498Szrj return ret1 - ret2;
270438fd1498Szrj }
270538fd1498Szrj return 0;
270638fd1498Szrj case TRUNC_DIV_EXPR:
270738fd1498Szrj case CEIL_DIV_EXPR:
270838fd1498Szrj case FLOOR_DIV_EXPR:
270938fd1498Szrj case ROUND_DIV_EXPR:
271038fd1498Szrj case EXACT_DIV_EXPR:
271138fd1498Szrj if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST
271238fd1498Szrj && tree_int_cst_sgn (TREE_OPERAND (expr, 1)) == 1)
271338fd1498Szrj {
271438fd1498Szrj int l = tree_log2 (TREE_OPERAND (expr, 1));
271538fd1498Szrj if (l >= 0)
271638fd1498Szrj {
271738fd1498Szrj ret1 = tree_ctz (TREE_OPERAND (expr, 0));
271838fd1498Szrj ret2 = l;
271938fd1498Szrj if (ret1 > ret2)
272038fd1498Szrj return ret1 - ret2;
272138fd1498Szrj }
272238fd1498Szrj }
272338fd1498Szrj return 0;
272438fd1498Szrj CASE_CONVERT:
272538fd1498Szrj ret1 = tree_ctz (TREE_OPERAND (expr, 0));
272638fd1498Szrj if (ret1 && ret1 == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
272738fd1498Szrj ret1 = prec;
272838fd1498Szrj return MIN (ret1, prec);
272938fd1498Szrj case SAVE_EXPR:
273038fd1498Szrj return tree_ctz (TREE_OPERAND (expr, 0));
273138fd1498Szrj case COND_EXPR:
273238fd1498Szrj ret1 = tree_ctz (TREE_OPERAND (expr, 1));
273338fd1498Szrj if (ret1 == 0)
273438fd1498Szrj return 0;
273538fd1498Szrj ret2 = tree_ctz (TREE_OPERAND (expr, 2));
273638fd1498Szrj return MIN (ret1, ret2);
273738fd1498Szrj case COMPOUND_EXPR:
273838fd1498Szrj return tree_ctz (TREE_OPERAND (expr, 1));
273938fd1498Szrj case ADDR_EXPR:
274038fd1498Szrj ret1 = get_pointer_alignment (CONST_CAST_TREE (expr));
274138fd1498Szrj if (ret1 > BITS_PER_UNIT)
274238fd1498Szrj {
274338fd1498Szrj ret1 = ctz_hwi (ret1 / BITS_PER_UNIT);
274438fd1498Szrj return MIN (ret1, prec);
274538fd1498Szrj }
274638fd1498Szrj return 0;
274738fd1498Szrj default:
274838fd1498Szrj return 0;
274938fd1498Szrj }
275038fd1498Szrj }
275138fd1498Szrj
275238fd1498Szrj /* Return 1 if EXPR is the real constant zero. Trailing zeroes matter for
275338fd1498Szrj decimal float constants, so don't return 1 for them. */
275438fd1498Szrj
275538fd1498Szrj int
real_zerop(const_tree expr)275638fd1498Szrj real_zerop (const_tree expr)
275738fd1498Szrj {
275838fd1498Szrj switch (TREE_CODE (expr))
275938fd1498Szrj {
276038fd1498Szrj case REAL_CST:
276138fd1498Szrj return real_equal (&TREE_REAL_CST (expr), &dconst0)
276238fd1498Szrj && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
276338fd1498Szrj case COMPLEX_CST:
276438fd1498Szrj return real_zerop (TREE_REALPART (expr))
276538fd1498Szrj && real_zerop (TREE_IMAGPART (expr));
276638fd1498Szrj case VECTOR_CST:
276738fd1498Szrj {
276838fd1498Szrj /* Don't simply check for a duplicate because the predicate
276938fd1498Szrj accepts both +0.0 and -0.0. */
277038fd1498Szrj unsigned count = vector_cst_encoded_nelts (expr);
277138fd1498Szrj for (unsigned int i = 0; i < count; ++i)
277238fd1498Szrj if (!real_zerop (VECTOR_CST_ENCODED_ELT (expr, i)))
277338fd1498Szrj return false;
277438fd1498Szrj return true;
277538fd1498Szrj }
277638fd1498Szrj default:
277738fd1498Szrj return false;
277838fd1498Szrj }
277938fd1498Szrj }
278038fd1498Szrj
278138fd1498Szrj /* Return 1 if EXPR is the real constant one in real or complex form.
278238fd1498Szrj Trailing zeroes matter for decimal float constants, so don't return
278338fd1498Szrj 1 for them. */
278438fd1498Szrj
278538fd1498Szrj int
real_onep(const_tree expr)278638fd1498Szrj real_onep (const_tree expr)
278738fd1498Szrj {
278838fd1498Szrj switch (TREE_CODE (expr))
278938fd1498Szrj {
279038fd1498Szrj case REAL_CST:
279138fd1498Szrj return real_equal (&TREE_REAL_CST (expr), &dconst1)
279238fd1498Szrj && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
279338fd1498Szrj case COMPLEX_CST:
279438fd1498Szrj return real_onep (TREE_REALPART (expr))
279538fd1498Szrj && real_zerop (TREE_IMAGPART (expr));
279638fd1498Szrj case VECTOR_CST:
279738fd1498Szrj return (VECTOR_CST_NPATTERNS (expr) == 1
279838fd1498Szrj && VECTOR_CST_DUPLICATE_P (expr)
279938fd1498Szrj && real_onep (VECTOR_CST_ENCODED_ELT (expr, 0)));
280038fd1498Szrj default:
280138fd1498Szrj return false;
280238fd1498Szrj }
280338fd1498Szrj }
280438fd1498Szrj
280538fd1498Szrj /* Return 1 if EXPR is the real constant minus one. Trailing zeroes
280638fd1498Szrj matter for decimal float constants, so don't return 1 for them. */
280738fd1498Szrj
280838fd1498Szrj int
real_minus_onep(const_tree expr)280938fd1498Szrj real_minus_onep (const_tree expr)
281038fd1498Szrj {
281138fd1498Szrj switch (TREE_CODE (expr))
281238fd1498Szrj {
281338fd1498Szrj case REAL_CST:
281438fd1498Szrj return real_equal (&TREE_REAL_CST (expr), &dconstm1)
281538fd1498Szrj && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
281638fd1498Szrj case COMPLEX_CST:
281738fd1498Szrj return real_minus_onep (TREE_REALPART (expr))
281838fd1498Szrj && real_zerop (TREE_IMAGPART (expr));
281938fd1498Szrj case VECTOR_CST:
282038fd1498Szrj return (VECTOR_CST_NPATTERNS (expr) == 1
282138fd1498Szrj && VECTOR_CST_DUPLICATE_P (expr)
282238fd1498Szrj && real_minus_onep (VECTOR_CST_ENCODED_ELT (expr, 0)));
282338fd1498Szrj default:
282438fd1498Szrj return false;
282538fd1498Szrj }
282638fd1498Szrj }
282738fd1498Szrj
282838fd1498Szrj /* Nonzero if EXP is a constant or a cast of a constant. */
282938fd1498Szrj
283038fd1498Szrj int
really_constant_p(const_tree exp)283138fd1498Szrj really_constant_p (const_tree exp)
283238fd1498Szrj {
283338fd1498Szrj /* This is not quite the same as STRIP_NOPS. It does more. */
283438fd1498Szrj while (CONVERT_EXPR_P (exp)
283538fd1498Szrj || TREE_CODE (exp) == NON_LVALUE_EXPR)
283638fd1498Szrj exp = TREE_OPERAND (exp, 0);
283738fd1498Szrj return TREE_CONSTANT (exp);
283838fd1498Szrj }
283938fd1498Szrj
284038fd1498Szrj /* Return true if T holds a polynomial pointer difference, storing it in
284138fd1498Szrj *VALUE if so. A true return means that T's precision is no greater
284238fd1498Szrj than 64 bits, which is the largest address space we support, so *VALUE
284338fd1498Szrj never loses precision. However, the signedness of the result does
284438fd1498Szrj not necessarily match the signedness of T: sometimes an unsigned type
284538fd1498Szrj like sizetype is used to encode a value that is actually negative. */
284638fd1498Szrj
284738fd1498Szrj bool
ptrdiff_tree_p(const_tree t,poly_int64_pod * value)284838fd1498Szrj ptrdiff_tree_p (const_tree t, poly_int64_pod *value)
284938fd1498Szrj {
285038fd1498Szrj if (!t)
285138fd1498Szrj return false;
285238fd1498Szrj if (TREE_CODE (t) == INTEGER_CST)
285338fd1498Szrj {
285438fd1498Szrj if (!cst_and_fits_in_hwi (t))
285538fd1498Szrj return false;
285638fd1498Szrj *value = int_cst_value (t);
285738fd1498Szrj return true;
285838fd1498Szrj }
285938fd1498Szrj if (POLY_INT_CST_P (t))
286038fd1498Szrj {
286138fd1498Szrj for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
286238fd1498Szrj if (!cst_and_fits_in_hwi (POLY_INT_CST_COEFF (t, i)))
286338fd1498Szrj return false;
286438fd1498Szrj for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
286538fd1498Szrj value->coeffs[i] = int_cst_value (POLY_INT_CST_COEFF (t, i));
286638fd1498Szrj return true;
286738fd1498Szrj }
286838fd1498Szrj return false;
286938fd1498Szrj }
287038fd1498Szrj
287138fd1498Szrj poly_int64
tree_to_poly_int64(const_tree t)287238fd1498Szrj tree_to_poly_int64 (const_tree t)
287338fd1498Szrj {
287438fd1498Szrj gcc_assert (tree_fits_poly_int64_p (t));
287538fd1498Szrj if (POLY_INT_CST_P (t))
287638fd1498Szrj return poly_int_cst_value (t).force_shwi ();
287738fd1498Szrj return TREE_INT_CST_LOW (t);
287838fd1498Szrj }
287938fd1498Szrj
288038fd1498Szrj poly_uint64
tree_to_poly_uint64(const_tree t)288138fd1498Szrj tree_to_poly_uint64 (const_tree t)
288238fd1498Szrj {
288338fd1498Szrj gcc_assert (tree_fits_poly_uint64_p (t));
288438fd1498Szrj if (POLY_INT_CST_P (t))
288538fd1498Szrj return poly_int_cst_value (t).force_uhwi ();
288638fd1498Szrj return TREE_INT_CST_LOW (t);
288738fd1498Szrj }
288838fd1498Szrj
288938fd1498Szrj /* Return first list element whose TREE_VALUE is ELEM.
289038fd1498Szrj Return 0 if ELEM is not in LIST. */
289138fd1498Szrj
289238fd1498Szrj tree
value_member(tree elem,tree list)289338fd1498Szrj value_member (tree elem, tree list)
289438fd1498Szrj {
289538fd1498Szrj while (list)
289638fd1498Szrj {
289738fd1498Szrj if (elem == TREE_VALUE (list))
289838fd1498Szrj return list;
289938fd1498Szrj list = TREE_CHAIN (list);
290038fd1498Szrj }
290138fd1498Szrj return NULL_TREE;
290238fd1498Szrj }
290338fd1498Szrj
290438fd1498Szrj /* Return first list element whose TREE_PURPOSE is ELEM.
290538fd1498Szrj Return 0 if ELEM is not in LIST. */
290638fd1498Szrj
290738fd1498Szrj tree
purpose_member(const_tree elem,tree list)290838fd1498Szrj purpose_member (const_tree elem, tree list)
290938fd1498Szrj {
291038fd1498Szrj while (list)
291138fd1498Szrj {
291238fd1498Szrj if (elem == TREE_PURPOSE (list))
291338fd1498Szrj return list;
291438fd1498Szrj list = TREE_CHAIN (list);
291538fd1498Szrj }
291638fd1498Szrj return NULL_TREE;
291738fd1498Szrj }
291838fd1498Szrj
291938fd1498Szrj /* Return true if ELEM is in V. */
292038fd1498Szrj
292138fd1498Szrj bool
vec_member(const_tree elem,vec<tree,va_gc> * v)292238fd1498Szrj vec_member (const_tree elem, vec<tree, va_gc> *v)
292338fd1498Szrj {
292438fd1498Szrj unsigned ix;
292538fd1498Szrj tree t;
292638fd1498Szrj FOR_EACH_VEC_SAFE_ELT (v, ix, t)
292738fd1498Szrj if (elem == t)
292838fd1498Szrj return true;
292938fd1498Szrj return false;
293038fd1498Szrj }
293138fd1498Szrj
293238fd1498Szrj /* Returns element number IDX (zero-origin) of chain CHAIN, or
293338fd1498Szrj NULL_TREE. */
293438fd1498Szrj
293538fd1498Szrj tree
chain_index(int idx,tree chain)293638fd1498Szrj chain_index (int idx, tree chain)
293738fd1498Szrj {
293838fd1498Szrj for (; chain && idx > 0; --idx)
293938fd1498Szrj chain = TREE_CHAIN (chain);
294038fd1498Szrj return chain;
294138fd1498Szrj }
294238fd1498Szrj
294338fd1498Szrj /* Return nonzero if ELEM is part of the chain CHAIN. */
294438fd1498Szrj
294538fd1498Szrj int
chain_member(const_tree elem,const_tree chain)294638fd1498Szrj chain_member (const_tree elem, const_tree chain)
294738fd1498Szrj {
294838fd1498Szrj while (chain)
294938fd1498Szrj {
295038fd1498Szrj if (elem == chain)
295138fd1498Szrj return 1;
295238fd1498Szrj chain = DECL_CHAIN (chain);
295338fd1498Szrj }
295438fd1498Szrj
295538fd1498Szrj return 0;
295638fd1498Szrj }
295738fd1498Szrj
295838fd1498Szrj /* Return the length of a chain of nodes chained through TREE_CHAIN.
295938fd1498Szrj We expect a null pointer to mark the end of the chain.
296038fd1498Szrj This is the Lisp primitive `length'. */
296138fd1498Szrj
296238fd1498Szrj int
list_length(const_tree t)296338fd1498Szrj list_length (const_tree t)
296438fd1498Szrj {
296538fd1498Szrj const_tree p = t;
296638fd1498Szrj #ifdef ENABLE_TREE_CHECKING
296738fd1498Szrj const_tree q = t;
296838fd1498Szrj #endif
296938fd1498Szrj int len = 0;
297038fd1498Szrj
297138fd1498Szrj while (p)
297238fd1498Szrj {
297338fd1498Szrj p = TREE_CHAIN (p);
297438fd1498Szrj #ifdef ENABLE_TREE_CHECKING
297538fd1498Szrj if (len % 2)
297638fd1498Szrj q = TREE_CHAIN (q);
297738fd1498Szrj gcc_assert (p != q);
297838fd1498Szrj #endif
297938fd1498Szrj len++;
298038fd1498Szrj }
298138fd1498Szrj
298238fd1498Szrj return len;
298338fd1498Szrj }
298438fd1498Szrj
298538fd1498Szrj /* Returns the first FIELD_DECL in the TYPE_FIELDS of the RECORD_TYPE or
298638fd1498Szrj UNION_TYPE TYPE, or NULL_TREE if none. */
298738fd1498Szrj
298838fd1498Szrj tree
first_field(const_tree type)298938fd1498Szrj first_field (const_tree type)
299038fd1498Szrj {
299138fd1498Szrj tree t = TYPE_FIELDS (type);
299238fd1498Szrj while (t && TREE_CODE (t) != FIELD_DECL)
299338fd1498Szrj t = TREE_CHAIN (t);
299438fd1498Szrj return t;
299538fd1498Szrj }
299638fd1498Szrj
299738fd1498Szrj /* Concatenate two chains of nodes (chained through TREE_CHAIN)
299838fd1498Szrj by modifying the last node in chain 1 to point to chain 2.
299938fd1498Szrj This is the Lisp primitive `nconc'. */
300038fd1498Szrj
300138fd1498Szrj tree
chainon(tree op1,tree op2)300238fd1498Szrj chainon (tree op1, tree op2)
300338fd1498Szrj {
300438fd1498Szrj tree t1;
300538fd1498Szrj
300638fd1498Szrj if (!op1)
300738fd1498Szrj return op2;
300838fd1498Szrj if (!op2)
300938fd1498Szrj return op1;
301038fd1498Szrj
301138fd1498Szrj for (t1 = op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1))
301238fd1498Szrj continue;
301338fd1498Szrj TREE_CHAIN (t1) = op2;
301438fd1498Szrj
301538fd1498Szrj #ifdef ENABLE_TREE_CHECKING
301638fd1498Szrj {
301738fd1498Szrj tree t2;
301838fd1498Szrj for (t2 = op2; t2; t2 = TREE_CHAIN (t2))
301938fd1498Szrj gcc_assert (t2 != t1);
302038fd1498Szrj }
302138fd1498Szrj #endif
302238fd1498Szrj
302338fd1498Szrj return op1;
302438fd1498Szrj }
302538fd1498Szrj
302638fd1498Szrj /* Return the last node in a chain of nodes (chained through TREE_CHAIN). */
302738fd1498Szrj
302838fd1498Szrj tree
tree_last(tree chain)302938fd1498Szrj tree_last (tree chain)
303038fd1498Szrj {
303138fd1498Szrj tree next;
303238fd1498Szrj if (chain)
303338fd1498Szrj while ((next = TREE_CHAIN (chain)))
303438fd1498Szrj chain = next;
303538fd1498Szrj return chain;
303638fd1498Szrj }
303738fd1498Szrj
303838fd1498Szrj /* Reverse the order of elements in the chain T,
303938fd1498Szrj and return the new head of the chain (old last element). */
304038fd1498Szrj
304138fd1498Szrj tree
nreverse(tree t)304238fd1498Szrj nreverse (tree t)
304338fd1498Szrj {
304438fd1498Szrj tree prev = 0, decl, next;
304538fd1498Szrj for (decl = t; decl; decl = next)
304638fd1498Szrj {
304738fd1498Szrj /* We shouldn't be using this function to reverse BLOCK chains; we
304838fd1498Szrj have blocks_nreverse for that. */
304938fd1498Szrj gcc_checking_assert (TREE_CODE (decl) != BLOCK);
305038fd1498Szrj next = TREE_CHAIN (decl);
305138fd1498Szrj TREE_CHAIN (decl) = prev;
305238fd1498Szrj prev = decl;
305338fd1498Szrj }
305438fd1498Szrj return prev;
305538fd1498Szrj }
305638fd1498Szrj
305738fd1498Szrj /* Return a newly created TREE_LIST node whose
305838fd1498Szrj purpose and value fields are PARM and VALUE. */
305938fd1498Szrj
306038fd1498Szrj tree
build_tree_list(tree parm,tree value MEM_STAT_DECL)306138fd1498Szrj build_tree_list (tree parm, tree value MEM_STAT_DECL)
306238fd1498Szrj {
306338fd1498Szrj tree t = make_node (TREE_LIST PASS_MEM_STAT);
306438fd1498Szrj TREE_PURPOSE (t) = parm;
306538fd1498Szrj TREE_VALUE (t) = value;
306638fd1498Szrj return t;
306738fd1498Szrj }
306838fd1498Szrj
306938fd1498Szrj /* Build a chain of TREE_LIST nodes from a vector. */
307038fd1498Szrj
307138fd1498Szrj tree
build_tree_list_vec(const vec<tree,va_gc> * vec MEM_STAT_DECL)307238fd1498Szrj build_tree_list_vec (const vec<tree, va_gc> *vec MEM_STAT_DECL)
307338fd1498Szrj {
307438fd1498Szrj tree ret = NULL_TREE;
307538fd1498Szrj tree *pp = &ret;
307638fd1498Szrj unsigned int i;
307738fd1498Szrj tree t;
307838fd1498Szrj FOR_EACH_VEC_SAFE_ELT (vec, i, t)
307938fd1498Szrj {
308038fd1498Szrj *pp = build_tree_list (NULL, t PASS_MEM_STAT);
308138fd1498Szrj pp = &TREE_CHAIN (*pp);
308238fd1498Szrj }
308338fd1498Szrj return ret;
308438fd1498Szrj }
308538fd1498Szrj
308638fd1498Szrj /* Return a newly created TREE_LIST node whose
308738fd1498Szrj purpose and value fields are PURPOSE and VALUE
308838fd1498Szrj and whose TREE_CHAIN is CHAIN. */
308938fd1498Szrj
309038fd1498Szrj tree
tree_cons(tree purpose,tree value,tree chain MEM_STAT_DECL)309138fd1498Szrj tree_cons (tree purpose, tree value, tree chain MEM_STAT_DECL)
309238fd1498Szrj {
309338fd1498Szrj tree node;
309438fd1498Szrj
309538fd1498Szrj node = ggc_alloc_tree_node_stat (sizeof (struct tree_list) PASS_MEM_STAT);
309638fd1498Szrj memset (node, 0, sizeof (struct tree_common));
309738fd1498Szrj
309838fd1498Szrj record_node_allocation_statistics (TREE_LIST, sizeof (struct tree_list));
309938fd1498Szrj
310038fd1498Szrj TREE_SET_CODE (node, TREE_LIST);
310138fd1498Szrj TREE_CHAIN (node) = chain;
310238fd1498Szrj TREE_PURPOSE (node) = purpose;
310338fd1498Szrj TREE_VALUE (node) = value;
310438fd1498Szrj return node;
310538fd1498Szrj }
310638fd1498Szrj
310738fd1498Szrj /* Return the values of the elements of a CONSTRUCTOR as a vector of
310838fd1498Szrj trees. */
310938fd1498Szrj
311038fd1498Szrj vec<tree, va_gc> *
ctor_to_vec(tree ctor)311138fd1498Szrj ctor_to_vec (tree ctor)
311238fd1498Szrj {
311338fd1498Szrj vec<tree, va_gc> *vec;
311438fd1498Szrj vec_alloc (vec, CONSTRUCTOR_NELTS (ctor));
311538fd1498Szrj unsigned int ix;
311638fd1498Szrj tree val;
311738fd1498Szrj
311838fd1498Szrj FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), ix, val)
311938fd1498Szrj vec->quick_push (val);
312038fd1498Szrj
312138fd1498Szrj return vec;
312238fd1498Szrj }
312338fd1498Szrj
312438fd1498Szrj /* Return the size nominally occupied by an object of type TYPE
312538fd1498Szrj when it resides in memory. The value is measured in units of bytes,
312638fd1498Szrj and its data type is that normally used for type sizes
312738fd1498Szrj (which is the first type created by make_signed_type or
312838fd1498Szrj make_unsigned_type). */
312938fd1498Szrj
313038fd1498Szrj tree
size_in_bytes_loc(location_t loc,const_tree type)313138fd1498Szrj size_in_bytes_loc (location_t loc, const_tree type)
313238fd1498Szrj {
313338fd1498Szrj tree t;
313438fd1498Szrj
313538fd1498Szrj if (type == error_mark_node)
313638fd1498Szrj return integer_zero_node;
313738fd1498Szrj
313838fd1498Szrj type = TYPE_MAIN_VARIANT (type);
313938fd1498Szrj t = TYPE_SIZE_UNIT (type);
314038fd1498Szrj
314138fd1498Szrj if (t == 0)
314238fd1498Szrj {
314338fd1498Szrj lang_hooks.types.incomplete_type_error (loc, NULL_TREE, type);
314438fd1498Szrj return size_zero_node;
314538fd1498Szrj }
314638fd1498Szrj
314738fd1498Szrj return t;
314838fd1498Szrj }
314938fd1498Szrj
315038fd1498Szrj /* Return the size of TYPE (in bytes) as a wide integer
315138fd1498Szrj or return -1 if the size can vary or is larger than an integer. */
315238fd1498Szrj
315338fd1498Szrj HOST_WIDE_INT
int_size_in_bytes(const_tree type)315438fd1498Szrj int_size_in_bytes (const_tree type)
315538fd1498Szrj {
315638fd1498Szrj tree t;
315738fd1498Szrj
315838fd1498Szrj if (type == error_mark_node)
315938fd1498Szrj return 0;
316038fd1498Szrj
316138fd1498Szrj type = TYPE_MAIN_VARIANT (type);
316238fd1498Szrj t = TYPE_SIZE_UNIT (type);
316338fd1498Szrj
316438fd1498Szrj if (t && tree_fits_uhwi_p (t))
316538fd1498Szrj return TREE_INT_CST_LOW (t);
316638fd1498Szrj else
316738fd1498Szrj return -1;
316838fd1498Szrj }
316938fd1498Szrj
317038fd1498Szrj /* Return the maximum size of TYPE (in bytes) as a wide integer
317138fd1498Szrj or return -1 if the size can vary or is larger than an integer. */
317238fd1498Szrj
317338fd1498Szrj HOST_WIDE_INT
max_int_size_in_bytes(const_tree type)317438fd1498Szrj max_int_size_in_bytes (const_tree type)
317538fd1498Szrj {
317638fd1498Szrj HOST_WIDE_INT size = -1;
317738fd1498Szrj tree size_tree;
317838fd1498Szrj
317938fd1498Szrj /* If this is an array type, check for a possible MAX_SIZE attached. */
318038fd1498Szrj
318138fd1498Szrj if (TREE_CODE (type) == ARRAY_TYPE)
318238fd1498Szrj {
318338fd1498Szrj size_tree = TYPE_ARRAY_MAX_SIZE (type);
318438fd1498Szrj
318538fd1498Szrj if (size_tree && tree_fits_uhwi_p (size_tree))
318638fd1498Szrj size = tree_to_uhwi (size_tree);
318738fd1498Szrj }
318838fd1498Szrj
318938fd1498Szrj /* If we still haven't been able to get a size, see if the language
319038fd1498Szrj can compute a maximum size. */
319138fd1498Szrj
319238fd1498Szrj if (size == -1)
319338fd1498Szrj {
319438fd1498Szrj size_tree = lang_hooks.types.max_size (type);
319538fd1498Szrj
319638fd1498Szrj if (size_tree && tree_fits_uhwi_p (size_tree))
319738fd1498Szrj size = tree_to_uhwi (size_tree);
319838fd1498Szrj }
319938fd1498Szrj
320038fd1498Szrj return size;
320138fd1498Szrj }
320238fd1498Szrj
320338fd1498Szrj /* Return the bit position of FIELD, in bits from the start of the record.
320438fd1498Szrj This is a tree of type bitsizetype. */
320538fd1498Szrj
320638fd1498Szrj tree
bit_position(const_tree field)320738fd1498Szrj bit_position (const_tree field)
320838fd1498Szrj {
320938fd1498Szrj return bit_from_pos (DECL_FIELD_OFFSET (field),
321038fd1498Szrj DECL_FIELD_BIT_OFFSET (field));
321138fd1498Szrj }
321238fd1498Szrj
321338fd1498Szrj /* Return the byte position of FIELD, in bytes from the start of the record.
321438fd1498Szrj This is a tree of type sizetype. */
321538fd1498Szrj
321638fd1498Szrj tree
byte_position(const_tree field)321738fd1498Szrj byte_position (const_tree field)
321838fd1498Szrj {
321938fd1498Szrj return byte_from_pos (DECL_FIELD_OFFSET (field),
322038fd1498Szrj DECL_FIELD_BIT_OFFSET (field));
322138fd1498Szrj }
322238fd1498Szrj
322338fd1498Szrj /* Likewise, but return as an integer. It must be representable in
322438fd1498Szrj that way (since it could be a signed value, we don't have the
322538fd1498Szrj option of returning -1 like int_size_in_byte can. */
322638fd1498Szrj
322738fd1498Szrj HOST_WIDE_INT
int_byte_position(const_tree field)322838fd1498Szrj int_byte_position (const_tree field)
322938fd1498Szrj {
323038fd1498Szrj return tree_to_shwi (byte_position (field));
323138fd1498Szrj }
323238fd1498Szrj
323338fd1498Szrj /* Return the strictest alignment, in bits, that T is known to have. */
323438fd1498Szrj
323538fd1498Szrj unsigned int
expr_align(const_tree t)323638fd1498Szrj expr_align (const_tree t)
323738fd1498Szrj {
323838fd1498Szrj unsigned int align0, align1;
323938fd1498Szrj
324038fd1498Szrj switch (TREE_CODE (t))
324138fd1498Szrj {
324238fd1498Szrj CASE_CONVERT: case NON_LVALUE_EXPR:
324338fd1498Szrj /* If we have conversions, we know that the alignment of the
324438fd1498Szrj object must meet each of the alignments of the types. */
324538fd1498Szrj align0 = expr_align (TREE_OPERAND (t, 0));
324638fd1498Szrj align1 = TYPE_ALIGN (TREE_TYPE (t));
324738fd1498Szrj return MAX (align0, align1);
324838fd1498Szrj
324938fd1498Szrj case SAVE_EXPR: case COMPOUND_EXPR: case MODIFY_EXPR:
325038fd1498Szrj case INIT_EXPR: case TARGET_EXPR: case WITH_CLEANUP_EXPR:
325138fd1498Szrj case CLEANUP_POINT_EXPR:
325238fd1498Szrj /* These don't change the alignment of an object. */
325338fd1498Szrj return expr_align (TREE_OPERAND (t, 0));
325438fd1498Szrj
325538fd1498Szrj case COND_EXPR:
325638fd1498Szrj /* The best we can do is say that the alignment is the least aligned
325738fd1498Szrj of the two arms. */
325838fd1498Szrj align0 = expr_align (TREE_OPERAND (t, 1));
325938fd1498Szrj align1 = expr_align (TREE_OPERAND (t, 2));
326038fd1498Szrj return MIN (align0, align1);
326138fd1498Szrj
326238fd1498Szrj /* FIXME: LABEL_DECL and CONST_DECL never have DECL_ALIGN set
326338fd1498Szrj meaningfully, it's always 1. */
326438fd1498Szrj case LABEL_DECL: case CONST_DECL:
326538fd1498Szrj case VAR_DECL: case PARM_DECL: case RESULT_DECL:
326638fd1498Szrj case FUNCTION_DECL:
326738fd1498Szrj gcc_assert (DECL_ALIGN (t) != 0);
326838fd1498Szrj return DECL_ALIGN (t);
326938fd1498Szrj
327038fd1498Szrj default:
327138fd1498Szrj break;
327238fd1498Szrj }
327338fd1498Szrj
327438fd1498Szrj /* Otherwise take the alignment from that of the type. */
327538fd1498Szrj return TYPE_ALIGN (TREE_TYPE (t));
327638fd1498Szrj }
327738fd1498Szrj
327838fd1498Szrj /* Return, as a tree node, the number of elements for TYPE (which is an
327938fd1498Szrj ARRAY_TYPE) minus one. This counts only elements of the top array. */
328038fd1498Szrj
328138fd1498Szrj tree
array_type_nelts(const_tree type)328238fd1498Szrj array_type_nelts (const_tree type)
328338fd1498Szrj {
328438fd1498Szrj tree index_type, min, max;
328538fd1498Szrj
328638fd1498Szrj /* If they did it with unspecified bounds, then we should have already
328738fd1498Szrj given an error about it before we got here. */
328838fd1498Szrj if (! TYPE_DOMAIN (type))
328938fd1498Szrj return error_mark_node;
329038fd1498Szrj
329138fd1498Szrj index_type = TYPE_DOMAIN (type);
329238fd1498Szrj min = TYPE_MIN_VALUE (index_type);
329338fd1498Szrj max = TYPE_MAX_VALUE (index_type);
329438fd1498Szrj
329538fd1498Szrj /* TYPE_MAX_VALUE may not be set if the array has unknown length. */
329638fd1498Szrj if (!max)
329738fd1498Szrj return error_mark_node;
329838fd1498Szrj
329938fd1498Szrj return (integer_zerop (min)
330038fd1498Szrj ? max
330138fd1498Szrj : fold_build2 (MINUS_EXPR, TREE_TYPE (max), max, min));
330238fd1498Szrj }
330338fd1498Szrj
330438fd1498Szrj /* If arg is static -- a reference to an object in static storage -- then
330538fd1498Szrj return the object. This is not the same as the C meaning of `static'.
330638fd1498Szrj If arg isn't static, return NULL. */
330738fd1498Szrj
330838fd1498Szrj tree
staticp(tree arg)330938fd1498Szrj staticp (tree arg)
331038fd1498Szrj {
331138fd1498Szrj switch (TREE_CODE (arg))
331238fd1498Szrj {
331338fd1498Szrj case FUNCTION_DECL:
331438fd1498Szrj /* Nested functions are static, even though taking their address will
331538fd1498Szrj involve a trampoline as we unnest the nested function and create
331638fd1498Szrj the trampoline on the tree level. */
331738fd1498Szrj return arg;
331838fd1498Szrj
331938fd1498Szrj case VAR_DECL:
332038fd1498Szrj return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
332138fd1498Szrj && ! DECL_THREAD_LOCAL_P (arg)
332238fd1498Szrj && ! DECL_DLLIMPORT_P (arg)
332338fd1498Szrj ? arg : NULL);
332438fd1498Szrj
332538fd1498Szrj case CONST_DECL:
332638fd1498Szrj return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
332738fd1498Szrj ? arg : NULL);
332838fd1498Szrj
332938fd1498Szrj case CONSTRUCTOR:
333038fd1498Szrj return TREE_STATIC (arg) ? arg : NULL;
333138fd1498Szrj
333238fd1498Szrj case LABEL_DECL:
333338fd1498Szrj case STRING_CST:
333438fd1498Szrj return arg;
333538fd1498Szrj
333638fd1498Szrj case COMPONENT_REF:
333738fd1498Szrj /* If the thing being referenced is not a field, then it is
333838fd1498Szrj something language specific. */
333938fd1498Szrj gcc_assert (TREE_CODE (TREE_OPERAND (arg, 1)) == FIELD_DECL);
334038fd1498Szrj
334138fd1498Szrj /* If we are referencing a bitfield, we can't evaluate an
334238fd1498Szrj ADDR_EXPR at compile time and so it isn't a constant. */
334338fd1498Szrj if (DECL_BIT_FIELD (TREE_OPERAND (arg, 1)))
334438fd1498Szrj return NULL;
334538fd1498Szrj
334638fd1498Szrj return staticp (TREE_OPERAND (arg, 0));
334738fd1498Szrj
334838fd1498Szrj case BIT_FIELD_REF:
334938fd1498Szrj return NULL;
335038fd1498Szrj
335138fd1498Szrj case INDIRECT_REF:
335238fd1498Szrj return TREE_CONSTANT (TREE_OPERAND (arg, 0)) ? arg : NULL;
335338fd1498Szrj
335438fd1498Szrj case ARRAY_REF:
335538fd1498Szrj case ARRAY_RANGE_REF:
335638fd1498Szrj if (TREE_CODE (TYPE_SIZE (TREE_TYPE (arg))) == INTEGER_CST
335738fd1498Szrj && TREE_CODE (TREE_OPERAND (arg, 1)) == INTEGER_CST)
335838fd1498Szrj return staticp (TREE_OPERAND (arg, 0));
335938fd1498Szrj else
336038fd1498Szrj return NULL;
336138fd1498Szrj
336238fd1498Szrj case COMPOUND_LITERAL_EXPR:
336338fd1498Szrj return TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (arg)) ? arg : NULL;
336438fd1498Szrj
336538fd1498Szrj default:
336638fd1498Szrj return NULL;
336738fd1498Szrj }
336838fd1498Szrj }
336938fd1498Szrj
337038fd1498Szrj
337138fd1498Szrj
337238fd1498Szrj
337338fd1498Szrj /* Return whether OP is a DECL whose address is function-invariant. */
337438fd1498Szrj
337538fd1498Szrj bool
decl_address_invariant_p(const_tree op)337638fd1498Szrj decl_address_invariant_p (const_tree op)
337738fd1498Szrj {
337838fd1498Szrj /* The conditions below are slightly less strict than the one in
337938fd1498Szrj staticp. */
338038fd1498Szrj
338138fd1498Szrj switch (TREE_CODE (op))
338238fd1498Szrj {
338338fd1498Szrj case PARM_DECL:
338438fd1498Szrj case RESULT_DECL:
338538fd1498Szrj case LABEL_DECL:
338638fd1498Szrj case FUNCTION_DECL:
338738fd1498Szrj return true;
338838fd1498Szrj
338938fd1498Szrj case VAR_DECL:
339038fd1498Szrj if ((TREE_STATIC (op) || DECL_EXTERNAL (op))
339138fd1498Szrj || DECL_THREAD_LOCAL_P (op)
339238fd1498Szrj || DECL_CONTEXT (op) == current_function_decl
339338fd1498Szrj || decl_function_context (op) == current_function_decl)
339438fd1498Szrj return true;
339538fd1498Szrj break;
339638fd1498Szrj
339738fd1498Szrj case CONST_DECL:
339838fd1498Szrj if ((TREE_STATIC (op) || DECL_EXTERNAL (op))
339938fd1498Szrj || decl_function_context (op) == current_function_decl)
340038fd1498Szrj return true;
340138fd1498Szrj break;
340238fd1498Szrj
340338fd1498Szrj default:
340438fd1498Szrj break;
340538fd1498Szrj }
340638fd1498Szrj
340738fd1498Szrj return false;
340838fd1498Szrj }
340938fd1498Szrj
341038fd1498Szrj /* Return whether OP is a DECL whose address is interprocedural-invariant. */
341138fd1498Szrj
341238fd1498Szrj bool
decl_address_ip_invariant_p(const_tree op)341338fd1498Szrj decl_address_ip_invariant_p (const_tree op)
341438fd1498Szrj {
341538fd1498Szrj /* The conditions below are slightly less strict than the one in
341638fd1498Szrj staticp. */
341738fd1498Szrj
341838fd1498Szrj switch (TREE_CODE (op))
341938fd1498Szrj {
342038fd1498Szrj case LABEL_DECL:
342138fd1498Szrj case FUNCTION_DECL:
342238fd1498Szrj case STRING_CST:
342338fd1498Szrj return true;
342438fd1498Szrj
342538fd1498Szrj case VAR_DECL:
342638fd1498Szrj if (((TREE_STATIC (op) || DECL_EXTERNAL (op))
342738fd1498Szrj && !DECL_DLLIMPORT_P (op))
342838fd1498Szrj || DECL_THREAD_LOCAL_P (op))
342938fd1498Szrj return true;
343038fd1498Szrj break;
343138fd1498Szrj
343238fd1498Szrj case CONST_DECL:
343338fd1498Szrj if ((TREE_STATIC (op) || DECL_EXTERNAL (op)))
343438fd1498Szrj return true;
343538fd1498Szrj break;
343638fd1498Szrj
343738fd1498Szrj default:
343838fd1498Szrj break;
343938fd1498Szrj }
344038fd1498Szrj
344138fd1498Szrj return false;
344238fd1498Szrj }
344338fd1498Szrj
344438fd1498Szrj
344538fd1498Szrj /* Return true if T is function-invariant (internal function, does
344638fd1498Szrj not handle arithmetic; that's handled in skip_simple_arithmetic and
344738fd1498Szrj tree_invariant_p). */
344838fd1498Szrj
344938fd1498Szrj static bool
tree_invariant_p_1(tree t)345038fd1498Szrj tree_invariant_p_1 (tree t)
345138fd1498Szrj {
345238fd1498Szrj tree op;
345338fd1498Szrj
345438fd1498Szrj if (TREE_CONSTANT (t)
345538fd1498Szrj || (TREE_READONLY (t) && !TREE_SIDE_EFFECTS (t)))
345638fd1498Szrj return true;
345738fd1498Szrj
345838fd1498Szrj switch (TREE_CODE (t))
345938fd1498Szrj {
346038fd1498Szrj case SAVE_EXPR:
346138fd1498Szrj return true;
346238fd1498Szrj
346338fd1498Szrj case ADDR_EXPR:
346438fd1498Szrj op = TREE_OPERAND (t, 0);
346538fd1498Szrj while (handled_component_p (op))
346638fd1498Szrj {
346738fd1498Szrj switch (TREE_CODE (op))
346838fd1498Szrj {
346938fd1498Szrj case ARRAY_REF:
347038fd1498Szrj case ARRAY_RANGE_REF:
347138fd1498Szrj if (!tree_invariant_p (TREE_OPERAND (op, 1))
347238fd1498Szrj || TREE_OPERAND (op, 2) != NULL_TREE
347338fd1498Szrj || TREE_OPERAND (op, 3) != NULL_TREE)
347438fd1498Szrj return false;
347538fd1498Szrj break;
347638fd1498Szrj
347738fd1498Szrj case COMPONENT_REF:
347838fd1498Szrj if (TREE_OPERAND (op, 2) != NULL_TREE)
347938fd1498Szrj return false;
348038fd1498Szrj break;
348138fd1498Szrj
348238fd1498Szrj default:;
348338fd1498Szrj }
348438fd1498Szrj op = TREE_OPERAND (op, 0);
348538fd1498Szrj }
348638fd1498Szrj
348738fd1498Szrj return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op);
348838fd1498Szrj
348938fd1498Szrj default:
349038fd1498Szrj break;
349138fd1498Szrj }
349238fd1498Szrj
349338fd1498Szrj return false;
349438fd1498Szrj }
349538fd1498Szrj
349638fd1498Szrj /* Return true if T is function-invariant. */
349738fd1498Szrj
349838fd1498Szrj bool
tree_invariant_p(tree t)349938fd1498Szrj tree_invariant_p (tree t)
350038fd1498Szrj {
350138fd1498Szrj tree inner = skip_simple_arithmetic (t);
350238fd1498Szrj return tree_invariant_p_1 (inner);
350338fd1498Szrj }
350438fd1498Szrj
350538fd1498Szrj /* Wrap a SAVE_EXPR around EXPR, if appropriate.
350638fd1498Szrj Do this to any expression which may be used in more than one place,
350738fd1498Szrj but must be evaluated only once.
350838fd1498Szrj
350938fd1498Szrj Normally, expand_expr would reevaluate the expression each time.
351038fd1498Szrj Calling save_expr produces something that is evaluated and recorded
351138fd1498Szrj the first time expand_expr is called on it. Subsequent calls to
351238fd1498Szrj expand_expr just reuse the recorded value.
351338fd1498Szrj
351438fd1498Szrj The call to expand_expr that generates code that actually computes
351538fd1498Szrj the value is the first call *at compile time*. Subsequent calls
351638fd1498Szrj *at compile time* generate code to use the saved value.
351738fd1498Szrj This produces correct result provided that *at run time* control
351838fd1498Szrj always flows through the insns made by the first expand_expr
351938fd1498Szrj before reaching the other places where the save_expr was evaluated.
352038fd1498Szrj You, the caller of save_expr, must make sure this is so.
352138fd1498Szrj
352238fd1498Szrj Constants, and certain read-only nodes, are returned with no
352338fd1498Szrj SAVE_EXPR because that is safe. Expressions containing placeholders
352438fd1498Szrj are not touched; see tree.def for an explanation of what these
352538fd1498Szrj are used for. */
352638fd1498Szrj
352738fd1498Szrj tree
save_expr(tree expr)352838fd1498Szrj save_expr (tree expr)
352938fd1498Szrj {
353038fd1498Szrj tree inner;
353138fd1498Szrj
353238fd1498Szrj /* If the tree evaluates to a constant, then we don't want to hide that
353338fd1498Szrj fact (i.e. this allows further folding, and direct checks for constants).
353438fd1498Szrj However, a read-only object that has side effects cannot be bypassed.
353538fd1498Szrj Since it is no problem to reevaluate literals, we just return the
353638fd1498Szrj literal node. */
353738fd1498Szrj inner = skip_simple_arithmetic (expr);
353838fd1498Szrj if (TREE_CODE (inner) == ERROR_MARK)
353938fd1498Szrj return inner;
354038fd1498Szrj
354138fd1498Szrj if (tree_invariant_p_1 (inner))
354238fd1498Szrj return expr;
354338fd1498Szrj
354438fd1498Szrj /* If INNER contains a PLACEHOLDER_EXPR, we must evaluate it each time, since
354538fd1498Szrj it means that the size or offset of some field of an object depends on
354638fd1498Szrj the value within another field.
354738fd1498Szrj
354838fd1498Szrj Note that it must not be the case that EXPR contains both a PLACEHOLDER_EXPR
354938fd1498Szrj and some variable since it would then need to be both evaluated once and
355038fd1498Szrj evaluated more than once. Front-ends must assure this case cannot
355138fd1498Szrj happen by surrounding any such subexpressions in their own SAVE_EXPR
355238fd1498Szrj and forcing evaluation at the proper time. */
355338fd1498Szrj if (contains_placeholder_p (inner))
355438fd1498Szrj return expr;
355538fd1498Szrj
355638fd1498Szrj expr = build1_loc (EXPR_LOCATION (expr), SAVE_EXPR, TREE_TYPE (expr), expr);
355738fd1498Szrj
355838fd1498Szrj /* This expression might be placed ahead of a jump to ensure that the
355938fd1498Szrj value was computed on both sides of the jump. So make sure it isn't
356038fd1498Szrj eliminated as dead. */
356138fd1498Szrj TREE_SIDE_EFFECTS (expr) = 1;
356238fd1498Szrj return expr;
356338fd1498Szrj }
356438fd1498Szrj
356538fd1498Szrj /* Look inside EXPR into any simple arithmetic operations. Return the
356638fd1498Szrj outermost non-arithmetic or non-invariant node. */
356738fd1498Szrj
356838fd1498Szrj tree
skip_simple_arithmetic(tree expr)356938fd1498Szrj skip_simple_arithmetic (tree expr)
357038fd1498Szrj {
357138fd1498Szrj /* We don't care about whether this can be used as an lvalue in this
357238fd1498Szrj context. */
357338fd1498Szrj while (TREE_CODE (expr) == NON_LVALUE_EXPR)
357438fd1498Szrj expr = TREE_OPERAND (expr, 0);
357538fd1498Szrj
357638fd1498Szrj /* If we have simple operations applied to a SAVE_EXPR or to a SAVE_EXPR and
357738fd1498Szrj a constant, it will be more efficient to not make another SAVE_EXPR since
357838fd1498Szrj it will allow better simplification and GCSE will be able to merge the
357938fd1498Szrj computations if they actually occur. */
358038fd1498Szrj while (true)
358138fd1498Szrj {
358238fd1498Szrj if (UNARY_CLASS_P (expr))
358338fd1498Szrj expr = TREE_OPERAND (expr, 0);
358438fd1498Szrj else if (BINARY_CLASS_P (expr))
358538fd1498Szrj {
358638fd1498Szrj if (tree_invariant_p (TREE_OPERAND (expr, 1)))
358738fd1498Szrj expr = TREE_OPERAND (expr, 0);
358838fd1498Szrj else if (tree_invariant_p (TREE_OPERAND (expr, 0)))
358938fd1498Szrj expr = TREE_OPERAND (expr, 1);
359038fd1498Szrj else
359138fd1498Szrj break;
359238fd1498Szrj }
359338fd1498Szrj else
359438fd1498Szrj break;
359538fd1498Szrj }
359638fd1498Szrj
359738fd1498Szrj return expr;
359838fd1498Szrj }
359938fd1498Szrj
360038fd1498Szrj /* Look inside EXPR into simple arithmetic operations involving constants.
360138fd1498Szrj Return the outermost non-arithmetic or non-constant node. */
360238fd1498Szrj
360338fd1498Szrj tree
skip_simple_constant_arithmetic(tree expr)360438fd1498Szrj skip_simple_constant_arithmetic (tree expr)
360538fd1498Szrj {
360638fd1498Szrj while (TREE_CODE (expr) == NON_LVALUE_EXPR)
360738fd1498Szrj expr = TREE_OPERAND (expr, 0);
360838fd1498Szrj
360938fd1498Szrj while (true)
361038fd1498Szrj {
361138fd1498Szrj if (UNARY_CLASS_P (expr))
361238fd1498Szrj expr = TREE_OPERAND (expr, 0);
361338fd1498Szrj else if (BINARY_CLASS_P (expr))
361438fd1498Szrj {
361538fd1498Szrj if (TREE_CONSTANT (TREE_OPERAND (expr, 1)))
361638fd1498Szrj expr = TREE_OPERAND (expr, 0);
361738fd1498Szrj else if (TREE_CONSTANT (TREE_OPERAND (expr, 0)))
361838fd1498Szrj expr = TREE_OPERAND (expr, 1);
361938fd1498Szrj else
362038fd1498Szrj break;
362138fd1498Szrj }
362238fd1498Szrj else
362338fd1498Szrj break;
362438fd1498Szrj }
362538fd1498Szrj
362638fd1498Szrj return expr;
362738fd1498Szrj }
362838fd1498Szrj
362938fd1498Szrj /* Return which tree structure is used by T. */
363038fd1498Szrj
363138fd1498Szrj enum tree_node_structure_enum
tree_node_structure(const_tree t)363238fd1498Szrj tree_node_structure (const_tree t)
363338fd1498Szrj {
363438fd1498Szrj const enum tree_code code = TREE_CODE (t);
363538fd1498Szrj return tree_node_structure_for_code (code);
363638fd1498Szrj }
363738fd1498Szrj
363838fd1498Szrj /* Set various status flags when building a CALL_EXPR object T. */
363938fd1498Szrj
364038fd1498Szrj static void
process_call_operands(tree t)364138fd1498Szrj process_call_operands (tree t)
364238fd1498Szrj {
364338fd1498Szrj bool side_effects = TREE_SIDE_EFFECTS (t);
364438fd1498Szrj bool read_only = false;
364538fd1498Szrj int i = call_expr_flags (t);
364638fd1498Szrj
364738fd1498Szrj /* Calls have side-effects, except those to const or pure functions. */
364838fd1498Szrj if ((i & ECF_LOOPING_CONST_OR_PURE) || !(i & (ECF_CONST | ECF_PURE)))
364938fd1498Szrj side_effects = true;
365038fd1498Szrj /* Propagate TREE_READONLY of arguments for const functions. */
365138fd1498Szrj if (i & ECF_CONST)
365238fd1498Szrj read_only = true;
365338fd1498Szrj
365438fd1498Szrj if (!side_effects || read_only)
365538fd1498Szrj for (i = 1; i < TREE_OPERAND_LENGTH (t); i++)
365638fd1498Szrj {
365738fd1498Szrj tree op = TREE_OPERAND (t, i);
365838fd1498Szrj if (op && TREE_SIDE_EFFECTS (op))
365938fd1498Szrj side_effects = true;
366038fd1498Szrj if (op && !TREE_READONLY (op) && !CONSTANT_CLASS_P (op))
366138fd1498Szrj read_only = false;
366238fd1498Szrj }
366338fd1498Szrj
366438fd1498Szrj TREE_SIDE_EFFECTS (t) = side_effects;
366538fd1498Szrj TREE_READONLY (t) = read_only;
366638fd1498Szrj }
366738fd1498Szrj
366838fd1498Szrj /* Return true if EXP contains a PLACEHOLDER_EXPR, i.e. if it represents a
366938fd1498Szrj size or offset that depends on a field within a record. */
367038fd1498Szrj
367138fd1498Szrj bool
contains_placeholder_p(const_tree exp)367238fd1498Szrj contains_placeholder_p (const_tree exp)
367338fd1498Szrj {
367438fd1498Szrj enum tree_code code;
367538fd1498Szrj
367638fd1498Szrj if (!exp)
367738fd1498Szrj return 0;
367838fd1498Szrj
367938fd1498Szrj code = TREE_CODE (exp);
368038fd1498Szrj if (code == PLACEHOLDER_EXPR)
368138fd1498Szrj return 1;
368238fd1498Szrj
368338fd1498Szrj switch (TREE_CODE_CLASS (code))
368438fd1498Szrj {
368538fd1498Szrj case tcc_reference:
368638fd1498Szrj /* Don't look at any PLACEHOLDER_EXPRs that might be in index or bit
368738fd1498Szrj position computations since they will be converted into a
368838fd1498Szrj WITH_RECORD_EXPR involving the reference, which will assume
368938fd1498Szrj here will be valid. */
369038fd1498Szrj return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
369138fd1498Szrj
369238fd1498Szrj case tcc_exceptional:
369338fd1498Szrj if (code == TREE_LIST)
369438fd1498Szrj return (CONTAINS_PLACEHOLDER_P (TREE_VALUE (exp))
369538fd1498Szrj || CONTAINS_PLACEHOLDER_P (TREE_CHAIN (exp)));
369638fd1498Szrj break;
369738fd1498Szrj
369838fd1498Szrj case tcc_unary:
369938fd1498Szrj case tcc_binary:
370038fd1498Szrj case tcc_comparison:
370138fd1498Szrj case tcc_expression:
370238fd1498Szrj switch (code)
370338fd1498Szrj {
370438fd1498Szrj case COMPOUND_EXPR:
370538fd1498Szrj /* Ignoring the first operand isn't quite right, but works best. */
370638fd1498Szrj return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1));
370738fd1498Szrj
370838fd1498Szrj case COND_EXPR:
370938fd1498Szrj return (CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0))
371038fd1498Szrj || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1))
371138fd1498Szrj || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2)));
371238fd1498Szrj
371338fd1498Szrj case SAVE_EXPR:
371438fd1498Szrj /* The save_expr function never wraps anything containing
371538fd1498Szrj a PLACEHOLDER_EXPR. */
371638fd1498Szrj return 0;
371738fd1498Szrj
371838fd1498Szrj default:
371938fd1498Szrj break;
372038fd1498Szrj }
372138fd1498Szrj
372238fd1498Szrj switch (TREE_CODE_LENGTH (code))
372338fd1498Szrj {
372438fd1498Szrj case 1:
372538fd1498Szrj return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
372638fd1498Szrj case 2:
372738fd1498Szrj return (CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0))
372838fd1498Szrj || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)));
372938fd1498Szrj default:
373038fd1498Szrj return 0;
373138fd1498Szrj }
373238fd1498Szrj
373338fd1498Szrj case tcc_vl_exp:
373438fd1498Szrj switch (code)
373538fd1498Szrj {
373638fd1498Szrj case CALL_EXPR:
373738fd1498Szrj {
373838fd1498Szrj const_tree arg;
373938fd1498Szrj const_call_expr_arg_iterator iter;
374038fd1498Szrj FOR_EACH_CONST_CALL_EXPR_ARG (arg, iter, exp)
374138fd1498Szrj if (CONTAINS_PLACEHOLDER_P (arg))
374238fd1498Szrj return 1;
374338fd1498Szrj return 0;
374438fd1498Szrj }
374538fd1498Szrj default:
374638fd1498Szrj return 0;
374738fd1498Szrj }
374838fd1498Szrj
374938fd1498Szrj default:
375038fd1498Szrj return 0;
375138fd1498Szrj }
375238fd1498Szrj return 0;
375338fd1498Szrj }
375438fd1498Szrj
375538fd1498Szrj /* Return true if any part of the structure of TYPE involves a PLACEHOLDER_EXPR
375638fd1498Szrj directly. This includes size, bounds, qualifiers (for QUAL_UNION_TYPE) and
375738fd1498Szrj field positions. */
375838fd1498Szrj
375938fd1498Szrj static bool
type_contains_placeholder_1(const_tree type)376038fd1498Szrj type_contains_placeholder_1 (const_tree type)
376138fd1498Szrj {
376238fd1498Szrj /* If the size contains a placeholder or the parent type (component type in
376338fd1498Szrj the case of arrays) type involves a placeholder, this type does. */
376438fd1498Szrj if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (type))
376538fd1498Szrj || CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (type))
376638fd1498Szrj || (!POINTER_TYPE_P (type)
376738fd1498Szrj && TREE_TYPE (type)
376838fd1498Szrj && type_contains_placeholder_p (TREE_TYPE (type))))
376938fd1498Szrj return true;
377038fd1498Szrj
377138fd1498Szrj /* Now do type-specific checks. Note that the last part of the check above
377238fd1498Szrj greatly limits what we have to do below. */
377338fd1498Szrj switch (TREE_CODE (type))
377438fd1498Szrj {
377538fd1498Szrj case VOID_TYPE:
377638fd1498Szrj case POINTER_BOUNDS_TYPE:
377738fd1498Szrj case COMPLEX_TYPE:
377838fd1498Szrj case ENUMERAL_TYPE:
377938fd1498Szrj case BOOLEAN_TYPE:
378038fd1498Szrj case POINTER_TYPE:
378138fd1498Szrj case OFFSET_TYPE:
378238fd1498Szrj case REFERENCE_TYPE:
378338fd1498Szrj case METHOD_TYPE:
378438fd1498Szrj case FUNCTION_TYPE:
378538fd1498Szrj case VECTOR_TYPE:
378638fd1498Szrj case NULLPTR_TYPE:
378738fd1498Szrj return false;
378838fd1498Szrj
378938fd1498Szrj case INTEGER_TYPE:
379038fd1498Szrj case REAL_TYPE:
379138fd1498Szrj case FIXED_POINT_TYPE:
379238fd1498Szrj /* Here we just check the bounds. */
379338fd1498Szrj return (CONTAINS_PLACEHOLDER_P (TYPE_MIN_VALUE (type))
379438fd1498Szrj || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type)));
379538fd1498Szrj
379638fd1498Szrj case ARRAY_TYPE:
379738fd1498Szrj /* We have already checked the component type above, so just check
379838fd1498Szrj the domain type. Flexible array members have a null domain. */
379938fd1498Szrj return TYPE_DOMAIN (type) ?
380038fd1498Szrj type_contains_placeholder_p (TYPE_DOMAIN (type)) : false;
380138fd1498Szrj
380238fd1498Szrj case RECORD_TYPE:
380338fd1498Szrj case UNION_TYPE:
380438fd1498Szrj case QUAL_UNION_TYPE:
380538fd1498Szrj {
380638fd1498Szrj tree field;
380738fd1498Szrj
380838fd1498Szrj for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
380938fd1498Szrj if (TREE_CODE (field) == FIELD_DECL
381038fd1498Szrj && (CONTAINS_PLACEHOLDER_P (DECL_FIELD_OFFSET (field))
381138fd1498Szrj || (TREE_CODE (type) == QUAL_UNION_TYPE
381238fd1498Szrj && CONTAINS_PLACEHOLDER_P (DECL_QUALIFIER (field)))
381338fd1498Szrj || type_contains_placeholder_p (TREE_TYPE (field))))
381438fd1498Szrj return true;
381538fd1498Szrj
381638fd1498Szrj return false;
381738fd1498Szrj }
381838fd1498Szrj
381938fd1498Szrj default:
382038fd1498Szrj gcc_unreachable ();
382138fd1498Szrj }
382238fd1498Szrj }
382338fd1498Szrj
382438fd1498Szrj /* Wrapper around above function used to cache its result. */
382538fd1498Szrj
382638fd1498Szrj bool
type_contains_placeholder_p(tree type)382738fd1498Szrj type_contains_placeholder_p (tree type)
382838fd1498Szrj {
382938fd1498Szrj bool result;
383038fd1498Szrj
383138fd1498Szrj /* If the contains_placeholder_bits field has been initialized,
383238fd1498Szrj then we know the answer. */
383338fd1498Szrj if (TYPE_CONTAINS_PLACEHOLDER_INTERNAL (type) > 0)
383438fd1498Szrj return TYPE_CONTAINS_PLACEHOLDER_INTERNAL (type) - 1;
383538fd1498Szrj
383638fd1498Szrj /* Indicate that we've seen this type node, and the answer is false.
383738fd1498Szrj This is what we want to return if we run into recursion via fields. */
383838fd1498Szrj TYPE_CONTAINS_PLACEHOLDER_INTERNAL (type) = 1;
383938fd1498Szrj
384038fd1498Szrj /* Compute the real value. */
384138fd1498Szrj result = type_contains_placeholder_1 (type);
384238fd1498Szrj
384338fd1498Szrj /* Store the real value. */
384438fd1498Szrj TYPE_CONTAINS_PLACEHOLDER_INTERNAL (type) = result + 1;
384538fd1498Szrj
384638fd1498Szrj return result;
384738fd1498Szrj }
384838fd1498Szrj
384938fd1498Szrj /* Push tree EXP onto vector QUEUE if it is not already present. */
385038fd1498Szrj
385138fd1498Szrj static void
push_without_duplicates(tree exp,vec<tree> * queue)385238fd1498Szrj push_without_duplicates (tree exp, vec<tree> *queue)
385338fd1498Szrj {
385438fd1498Szrj unsigned int i;
385538fd1498Szrj tree iter;
385638fd1498Szrj
385738fd1498Szrj FOR_EACH_VEC_ELT (*queue, i, iter)
385838fd1498Szrj if (simple_cst_equal (iter, exp) == 1)
385938fd1498Szrj break;
386038fd1498Szrj
386138fd1498Szrj if (!iter)
386238fd1498Szrj queue->safe_push (exp);
386338fd1498Szrj }
386438fd1498Szrj
386538fd1498Szrj /* Given a tree EXP, find all occurrences of references to fields
386638fd1498Szrj in a PLACEHOLDER_EXPR and place them in vector REFS without
386738fd1498Szrj duplicates. Also record VAR_DECLs and CONST_DECLs. Note that
386838fd1498Szrj we assume here that EXP contains only arithmetic expressions
386938fd1498Szrj or CALL_EXPRs with PLACEHOLDER_EXPRs occurring only in their
387038fd1498Szrj argument list. */
387138fd1498Szrj
387238fd1498Szrj void
find_placeholder_in_expr(tree exp,vec<tree> * refs)387338fd1498Szrj find_placeholder_in_expr (tree exp, vec<tree> *refs)
387438fd1498Szrj {
387538fd1498Szrj enum tree_code code = TREE_CODE (exp);
387638fd1498Szrj tree inner;
387738fd1498Szrj int i;
387838fd1498Szrj
387938fd1498Szrj /* We handle TREE_LIST and COMPONENT_REF separately. */
388038fd1498Szrj if (code == TREE_LIST)
388138fd1498Szrj {
388238fd1498Szrj FIND_PLACEHOLDER_IN_EXPR (TREE_CHAIN (exp), refs);
388338fd1498Szrj FIND_PLACEHOLDER_IN_EXPR (TREE_VALUE (exp), refs);
388438fd1498Szrj }
388538fd1498Szrj else if (code == COMPONENT_REF)
388638fd1498Szrj {
388738fd1498Szrj for (inner = TREE_OPERAND (exp, 0);
388838fd1498Szrj REFERENCE_CLASS_P (inner);
388938fd1498Szrj inner = TREE_OPERAND (inner, 0))
389038fd1498Szrj ;
389138fd1498Szrj
389238fd1498Szrj if (TREE_CODE (inner) == PLACEHOLDER_EXPR)
389338fd1498Szrj push_without_duplicates (exp, refs);
389438fd1498Szrj else
389538fd1498Szrj FIND_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), refs);
389638fd1498Szrj }
389738fd1498Szrj else
389838fd1498Szrj switch (TREE_CODE_CLASS (code))
389938fd1498Szrj {
390038fd1498Szrj case tcc_constant:
390138fd1498Szrj break;
390238fd1498Szrj
390338fd1498Szrj case tcc_declaration:
390438fd1498Szrj /* Variables allocated to static storage can stay. */
390538fd1498Szrj if (!TREE_STATIC (exp))
390638fd1498Szrj push_without_duplicates (exp, refs);
390738fd1498Szrj break;
390838fd1498Szrj
390938fd1498Szrj case tcc_expression:
391038fd1498Szrj /* This is the pattern built in ada/make_aligning_type. */
391138fd1498Szrj if (code == ADDR_EXPR
391238fd1498Szrj && TREE_CODE (TREE_OPERAND (exp, 0)) == PLACEHOLDER_EXPR)
391338fd1498Szrj {
391438fd1498Szrj push_without_duplicates (exp, refs);
391538fd1498Szrj break;
391638fd1498Szrj }
391738fd1498Szrj
391838fd1498Szrj /* Fall through. */
391938fd1498Szrj
392038fd1498Szrj case tcc_exceptional:
392138fd1498Szrj case tcc_unary:
392238fd1498Szrj case tcc_binary:
392338fd1498Szrj case tcc_comparison:
392438fd1498Szrj case tcc_reference:
392538fd1498Szrj for (i = 0; i < TREE_CODE_LENGTH (code); i++)
392638fd1498Szrj FIND_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, i), refs);
392738fd1498Szrj break;
392838fd1498Szrj
392938fd1498Szrj case tcc_vl_exp:
393038fd1498Szrj for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++)
393138fd1498Szrj FIND_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, i), refs);
393238fd1498Szrj break;
393338fd1498Szrj
393438fd1498Szrj default:
393538fd1498Szrj gcc_unreachable ();
393638fd1498Szrj }
393738fd1498Szrj }
393838fd1498Szrj
393938fd1498Szrj /* Given a tree EXP, a FIELD_DECL F, and a replacement value R,
394038fd1498Szrj return a tree with all occurrences of references to F in a
394138fd1498Szrj PLACEHOLDER_EXPR replaced by R. Also handle VAR_DECLs and
394238fd1498Szrj CONST_DECLs. Note that we assume here that EXP contains only
394338fd1498Szrj arithmetic expressions or CALL_EXPRs with PLACEHOLDER_EXPRs
394438fd1498Szrj occurring only in their argument list. */
394538fd1498Szrj
394638fd1498Szrj tree
substitute_in_expr(tree exp,tree f,tree r)394738fd1498Szrj substitute_in_expr (tree exp, tree f, tree r)
394838fd1498Szrj {
394938fd1498Szrj enum tree_code code = TREE_CODE (exp);
395038fd1498Szrj tree op0, op1, op2, op3;
395138fd1498Szrj tree new_tree;
395238fd1498Szrj
395338fd1498Szrj /* We handle TREE_LIST and COMPONENT_REF separately. */
395438fd1498Szrj if (code == TREE_LIST)
395538fd1498Szrj {
395638fd1498Szrj op0 = SUBSTITUTE_IN_EXPR (TREE_CHAIN (exp), f, r);
395738fd1498Szrj op1 = SUBSTITUTE_IN_EXPR (TREE_VALUE (exp), f, r);
395838fd1498Szrj if (op0 == TREE_CHAIN (exp) && op1 == TREE_VALUE (exp))
395938fd1498Szrj return exp;
396038fd1498Szrj
396138fd1498Szrj return tree_cons (TREE_PURPOSE (exp), op1, op0);
396238fd1498Szrj }
396338fd1498Szrj else if (code == COMPONENT_REF)
396438fd1498Szrj {
396538fd1498Szrj tree inner;
396638fd1498Szrj
396738fd1498Szrj /* If this expression is getting a value from a PLACEHOLDER_EXPR
396838fd1498Szrj and it is the right field, replace it with R. */
396938fd1498Szrj for (inner = TREE_OPERAND (exp, 0);
397038fd1498Szrj REFERENCE_CLASS_P (inner);
397138fd1498Szrj inner = TREE_OPERAND (inner, 0))
397238fd1498Szrj ;
397338fd1498Szrj
397438fd1498Szrj /* The field. */
397538fd1498Szrj op1 = TREE_OPERAND (exp, 1);
397638fd1498Szrj
397738fd1498Szrj if (TREE_CODE (inner) == PLACEHOLDER_EXPR && op1 == f)
397838fd1498Szrj return r;
397938fd1498Szrj
398038fd1498Szrj /* If this expression hasn't been completed let, leave it alone. */
398138fd1498Szrj if (TREE_CODE (inner) == PLACEHOLDER_EXPR && !TREE_TYPE (inner))
398238fd1498Szrj return exp;
398338fd1498Szrj
398438fd1498Szrj op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
398538fd1498Szrj if (op0 == TREE_OPERAND (exp, 0))
398638fd1498Szrj return exp;
398738fd1498Szrj
398838fd1498Szrj new_tree
398938fd1498Szrj = fold_build3 (COMPONENT_REF, TREE_TYPE (exp), op0, op1, NULL_TREE);
399038fd1498Szrj }
399138fd1498Szrj else
399238fd1498Szrj switch (TREE_CODE_CLASS (code))
399338fd1498Szrj {
399438fd1498Szrj case tcc_constant:
399538fd1498Szrj return exp;
399638fd1498Szrj
399738fd1498Szrj case tcc_declaration:
399838fd1498Szrj if (exp == f)
399938fd1498Szrj return r;
400038fd1498Szrj else
400138fd1498Szrj return exp;
400238fd1498Szrj
400338fd1498Szrj case tcc_expression:
400438fd1498Szrj if (exp == f)
400538fd1498Szrj return r;
400638fd1498Szrj
400738fd1498Szrj /* Fall through. */
400838fd1498Szrj
400938fd1498Szrj case tcc_exceptional:
401038fd1498Szrj case tcc_unary:
401138fd1498Szrj case tcc_binary:
401238fd1498Szrj case tcc_comparison:
401338fd1498Szrj case tcc_reference:
401438fd1498Szrj switch (TREE_CODE_LENGTH (code))
401538fd1498Szrj {
401638fd1498Szrj case 0:
401738fd1498Szrj return exp;
401838fd1498Szrj
401938fd1498Szrj case 1:
402038fd1498Szrj op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
402138fd1498Szrj if (op0 == TREE_OPERAND (exp, 0))
402238fd1498Szrj return exp;
402338fd1498Szrj
402438fd1498Szrj new_tree = fold_build1 (code, TREE_TYPE (exp), op0);
402538fd1498Szrj break;
402638fd1498Szrj
402738fd1498Szrj case 2:
402838fd1498Szrj op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
402938fd1498Szrj op1 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 1), f, r);
403038fd1498Szrj
403138fd1498Szrj if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
403238fd1498Szrj return exp;
403338fd1498Szrj
403438fd1498Szrj new_tree = fold_build2 (code, TREE_TYPE (exp), op0, op1);
403538fd1498Szrj break;
403638fd1498Szrj
403738fd1498Szrj case 3:
403838fd1498Szrj op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
403938fd1498Szrj op1 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 1), f, r);
404038fd1498Szrj op2 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 2), f, r);
404138fd1498Szrj
404238fd1498Szrj if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
404338fd1498Szrj && op2 == TREE_OPERAND (exp, 2))
404438fd1498Szrj return exp;
404538fd1498Szrj
404638fd1498Szrj new_tree = fold_build3 (code, TREE_TYPE (exp), op0, op1, op2);
404738fd1498Szrj break;
404838fd1498Szrj
404938fd1498Szrj case 4:
405038fd1498Szrj op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
405138fd1498Szrj op1 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 1), f, r);
405238fd1498Szrj op2 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 2), f, r);
405338fd1498Szrj op3 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 3), f, r);
405438fd1498Szrj
405538fd1498Szrj if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
405638fd1498Szrj && op2 == TREE_OPERAND (exp, 2)
405738fd1498Szrj && op3 == TREE_OPERAND (exp, 3))
405838fd1498Szrj return exp;
405938fd1498Szrj
406038fd1498Szrj new_tree
406138fd1498Szrj = fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3));
406238fd1498Szrj break;
406338fd1498Szrj
406438fd1498Szrj default:
406538fd1498Szrj gcc_unreachable ();
406638fd1498Szrj }
406738fd1498Szrj break;
406838fd1498Szrj
406938fd1498Szrj case tcc_vl_exp:
407038fd1498Szrj {
407138fd1498Szrj int i;
407238fd1498Szrj
407338fd1498Szrj new_tree = NULL_TREE;
407438fd1498Szrj
407538fd1498Szrj /* If we are trying to replace F with a constant or with another
407638fd1498Szrj instance of one of the arguments of the call, inline back
407738fd1498Szrj functions which do nothing else than computing a value from
407838fd1498Szrj the arguments they are passed. This makes it possible to
407938fd1498Szrj fold partially or entirely the replacement expression. */
408038fd1498Szrj if (code == CALL_EXPR)
408138fd1498Szrj {
408238fd1498Szrj bool maybe_inline = false;
408338fd1498Szrj if (CONSTANT_CLASS_P (r))
408438fd1498Szrj maybe_inline = true;
408538fd1498Szrj else
408638fd1498Szrj for (i = 3; i < TREE_OPERAND_LENGTH (exp); i++)
408738fd1498Szrj if (operand_equal_p (TREE_OPERAND (exp, i), r, 0))
408838fd1498Szrj {
408938fd1498Szrj maybe_inline = true;
409038fd1498Szrj break;
409138fd1498Szrj }
409238fd1498Szrj if (maybe_inline)
409338fd1498Szrj {
409438fd1498Szrj tree t = maybe_inline_call_in_expr (exp);
409538fd1498Szrj if (t)
409638fd1498Szrj return SUBSTITUTE_IN_EXPR (t, f, r);
409738fd1498Szrj }
409838fd1498Szrj }
409938fd1498Szrj
410038fd1498Szrj for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++)
410138fd1498Szrj {
410238fd1498Szrj tree op = TREE_OPERAND (exp, i);
410338fd1498Szrj tree new_op = SUBSTITUTE_IN_EXPR (op, f, r);
410438fd1498Szrj if (new_op != op)
410538fd1498Szrj {
410638fd1498Szrj if (!new_tree)
410738fd1498Szrj new_tree = copy_node (exp);
410838fd1498Szrj TREE_OPERAND (new_tree, i) = new_op;
410938fd1498Szrj }
411038fd1498Szrj }
411138fd1498Szrj
411238fd1498Szrj if (new_tree)
411338fd1498Szrj {
411438fd1498Szrj new_tree = fold (new_tree);
411538fd1498Szrj if (TREE_CODE (new_tree) == CALL_EXPR)
411638fd1498Szrj process_call_operands (new_tree);
411738fd1498Szrj }
411838fd1498Szrj else
411938fd1498Szrj return exp;
412038fd1498Szrj }
412138fd1498Szrj break;
412238fd1498Szrj
412338fd1498Szrj default:
412438fd1498Szrj gcc_unreachable ();
412538fd1498Szrj }
412638fd1498Szrj
412738fd1498Szrj TREE_READONLY (new_tree) |= TREE_READONLY (exp);
412838fd1498Szrj
412938fd1498Szrj if (code == INDIRECT_REF || code == ARRAY_REF || code == ARRAY_RANGE_REF)
413038fd1498Szrj TREE_THIS_NOTRAP (new_tree) |= TREE_THIS_NOTRAP (exp);
413138fd1498Szrj
413238fd1498Szrj return new_tree;
413338fd1498Szrj }
413438fd1498Szrj
413538fd1498Szrj /* Similar, but look for a PLACEHOLDER_EXPR in EXP and find a replacement
413638fd1498Szrj for it within OBJ, a tree that is an object or a chain of references. */
413738fd1498Szrj
413838fd1498Szrj tree
substitute_placeholder_in_expr(tree exp,tree obj)413938fd1498Szrj substitute_placeholder_in_expr (tree exp, tree obj)
414038fd1498Szrj {
414138fd1498Szrj enum tree_code code = TREE_CODE (exp);
414238fd1498Szrj tree op0, op1, op2, op3;
414338fd1498Szrj tree new_tree;
414438fd1498Szrj
414538fd1498Szrj /* If this is a PLACEHOLDER_EXPR, see if we find a corresponding type
414638fd1498Szrj in the chain of OBJ. */
414738fd1498Szrj if (code == PLACEHOLDER_EXPR)
414838fd1498Szrj {
414938fd1498Szrj tree need_type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
415038fd1498Szrj tree elt;
415138fd1498Szrj
415238fd1498Szrj for (elt = obj; elt != 0;
415338fd1498Szrj elt = ((TREE_CODE (elt) == COMPOUND_EXPR
415438fd1498Szrj || TREE_CODE (elt) == COND_EXPR)
415538fd1498Szrj ? TREE_OPERAND (elt, 1)
415638fd1498Szrj : (REFERENCE_CLASS_P (elt)
415738fd1498Szrj || UNARY_CLASS_P (elt)
415838fd1498Szrj || BINARY_CLASS_P (elt)
415938fd1498Szrj || VL_EXP_CLASS_P (elt)
416038fd1498Szrj || EXPRESSION_CLASS_P (elt))
416138fd1498Szrj ? TREE_OPERAND (elt, 0) : 0))
416238fd1498Szrj if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
416338fd1498Szrj return elt;
416438fd1498Szrj
416538fd1498Szrj for (elt = obj; elt != 0;
416638fd1498Szrj elt = ((TREE_CODE (elt) == COMPOUND_EXPR
416738fd1498Szrj || TREE_CODE (elt) == COND_EXPR)
416838fd1498Szrj ? TREE_OPERAND (elt, 1)
416938fd1498Szrj : (REFERENCE_CLASS_P (elt)
417038fd1498Szrj || UNARY_CLASS_P (elt)
417138fd1498Szrj || BINARY_CLASS_P (elt)
417238fd1498Szrj || VL_EXP_CLASS_P (elt)
417338fd1498Szrj || EXPRESSION_CLASS_P (elt))
417438fd1498Szrj ? TREE_OPERAND (elt, 0) : 0))
417538fd1498Szrj if (POINTER_TYPE_P (TREE_TYPE (elt))
417638fd1498Szrj && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
417738fd1498Szrj == need_type))
417838fd1498Szrj return fold_build1 (INDIRECT_REF, need_type, elt);
417938fd1498Szrj
418038fd1498Szrj /* If we didn't find it, return the original PLACEHOLDER_EXPR. If it
418138fd1498Szrj survives until RTL generation, there will be an error. */
418238fd1498Szrj return exp;
418338fd1498Szrj }
418438fd1498Szrj
418538fd1498Szrj /* TREE_LIST is special because we need to look at TREE_VALUE
418638fd1498Szrj and TREE_CHAIN, not TREE_OPERANDS. */
418738fd1498Szrj else if (code == TREE_LIST)
418838fd1498Szrj {
418938fd1498Szrj op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_CHAIN (exp), obj);
419038fd1498Szrj op1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_VALUE (exp), obj);
419138fd1498Szrj if (op0 == TREE_CHAIN (exp) && op1 == TREE_VALUE (exp))
419238fd1498Szrj return exp;
419338fd1498Szrj
419438fd1498Szrj return tree_cons (TREE_PURPOSE (exp), op1, op0);
419538fd1498Szrj }
419638fd1498Szrj else
419738fd1498Szrj switch (TREE_CODE_CLASS (code))
419838fd1498Szrj {
419938fd1498Szrj case tcc_constant:
420038fd1498Szrj case tcc_declaration:
420138fd1498Szrj return exp;
420238fd1498Szrj
420338fd1498Szrj case tcc_exceptional:
420438fd1498Szrj case tcc_unary:
420538fd1498Szrj case tcc_binary:
420638fd1498Szrj case tcc_comparison:
420738fd1498Szrj case tcc_expression:
420838fd1498Szrj case tcc_reference:
420938fd1498Szrj case tcc_statement:
421038fd1498Szrj switch (TREE_CODE_LENGTH (code))
421138fd1498Szrj {
421238fd1498Szrj case 0:
421338fd1498Szrj return exp;
421438fd1498Szrj
421538fd1498Szrj case 1:
421638fd1498Szrj op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
421738fd1498Szrj if (op0 == TREE_OPERAND (exp, 0))
421838fd1498Szrj return exp;
421938fd1498Szrj
422038fd1498Szrj new_tree = fold_build1 (code, TREE_TYPE (exp), op0);
422138fd1498Szrj break;
422238fd1498Szrj
422338fd1498Szrj case 2:
422438fd1498Szrj op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
422538fd1498Szrj op1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 1), obj);
422638fd1498Szrj
422738fd1498Szrj if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
422838fd1498Szrj return exp;
422938fd1498Szrj
423038fd1498Szrj new_tree = fold_build2 (code, TREE_TYPE (exp), op0, op1);
423138fd1498Szrj break;
423238fd1498Szrj
423338fd1498Szrj case 3:
423438fd1498Szrj op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
423538fd1498Szrj op1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 1), obj);
423638fd1498Szrj op2 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 2), obj);
423738fd1498Szrj
423838fd1498Szrj if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
423938fd1498Szrj && op2 == TREE_OPERAND (exp, 2))
424038fd1498Szrj return exp;
424138fd1498Szrj
424238fd1498Szrj new_tree = fold_build3 (code, TREE_TYPE (exp), op0, op1, op2);
424338fd1498Szrj break;
424438fd1498Szrj
424538fd1498Szrj case 4:
424638fd1498Szrj op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
424738fd1498Szrj op1 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 1), obj);
424838fd1498Szrj op2 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 2), obj);
424938fd1498Szrj op3 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 3), obj);
425038fd1498Szrj
425138fd1498Szrj if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
425238fd1498Szrj && op2 == TREE_OPERAND (exp, 2)
425338fd1498Szrj && op3 == TREE_OPERAND (exp, 3))
425438fd1498Szrj return exp;
425538fd1498Szrj
425638fd1498Szrj new_tree
425738fd1498Szrj = fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3));
425838fd1498Szrj break;
425938fd1498Szrj
426038fd1498Szrj default:
426138fd1498Szrj gcc_unreachable ();
426238fd1498Szrj }
426338fd1498Szrj break;
426438fd1498Szrj
426538fd1498Szrj case tcc_vl_exp:
426638fd1498Szrj {
426738fd1498Szrj int i;
426838fd1498Szrj
426938fd1498Szrj new_tree = NULL_TREE;
427038fd1498Szrj
427138fd1498Szrj for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++)
427238fd1498Szrj {
427338fd1498Szrj tree op = TREE_OPERAND (exp, i);
427438fd1498Szrj tree new_op = SUBSTITUTE_PLACEHOLDER_IN_EXPR (op, obj);
427538fd1498Szrj if (new_op != op)
427638fd1498Szrj {
427738fd1498Szrj if (!new_tree)
427838fd1498Szrj new_tree = copy_node (exp);
427938fd1498Szrj TREE_OPERAND (new_tree, i) = new_op;
428038fd1498Szrj }
428138fd1498Szrj }
428238fd1498Szrj
428338fd1498Szrj if (new_tree)
428438fd1498Szrj {
428538fd1498Szrj new_tree = fold (new_tree);
428638fd1498Szrj if (TREE_CODE (new_tree) == CALL_EXPR)
428738fd1498Szrj process_call_operands (new_tree);
428838fd1498Szrj }
428938fd1498Szrj else
429038fd1498Szrj return exp;
429138fd1498Szrj }
429238fd1498Szrj break;
429338fd1498Szrj
429438fd1498Szrj default:
429538fd1498Szrj gcc_unreachable ();
429638fd1498Szrj }
429738fd1498Szrj
429838fd1498Szrj TREE_READONLY (new_tree) |= TREE_READONLY (exp);
429938fd1498Szrj
430038fd1498Szrj if (code == INDIRECT_REF || code == ARRAY_REF || code == ARRAY_RANGE_REF)
430138fd1498Szrj TREE_THIS_NOTRAP (new_tree) |= TREE_THIS_NOTRAP (exp);
430238fd1498Szrj
430338fd1498Szrj return new_tree;
430438fd1498Szrj }
430538fd1498Szrj
430638fd1498Szrj
430738fd1498Szrj /* Subroutine of stabilize_reference; this is called for subtrees of
430838fd1498Szrj references. Any expression with side-effects must be put in a SAVE_EXPR
430938fd1498Szrj to ensure that it is only evaluated once.
431038fd1498Szrj
431138fd1498Szrj We don't put SAVE_EXPR nodes around everything, because assigning very
431238fd1498Szrj simple expressions to temporaries causes us to miss good opportunities
431338fd1498Szrj for optimizations. Among other things, the opportunity to fold in the
431438fd1498Szrj addition of a constant into an addressing mode often gets lost, e.g.
431538fd1498Szrj "y[i+1] += x;". In general, we take the approach that we should not make
431638fd1498Szrj an assignment unless we are forced into it - i.e., that any non-side effect
431738fd1498Szrj operator should be allowed, and that cse should take care of coalescing
431838fd1498Szrj multiple utterances of the same expression should that prove fruitful. */
431938fd1498Szrj
432038fd1498Szrj static tree
stabilize_reference_1(tree e)432138fd1498Szrj stabilize_reference_1 (tree e)
432238fd1498Szrj {
432338fd1498Szrj tree result;
432438fd1498Szrj enum tree_code code = TREE_CODE (e);
432538fd1498Szrj
432638fd1498Szrj /* We cannot ignore const expressions because it might be a reference
432738fd1498Szrj to a const array but whose index contains side-effects. But we can
432838fd1498Szrj ignore things that are actual constant or that already have been
432938fd1498Szrj handled by this function. */
433038fd1498Szrj
433138fd1498Szrj if (tree_invariant_p (e))
433238fd1498Szrj return e;
433338fd1498Szrj
433438fd1498Szrj switch (TREE_CODE_CLASS (code))
433538fd1498Szrj {
433638fd1498Szrj case tcc_exceptional:
433738fd1498Szrj /* Always wrap STATEMENT_LIST into SAVE_EXPR, even if it doesn't
433838fd1498Szrj have side-effects. */
433938fd1498Szrj if (code == STATEMENT_LIST)
434038fd1498Szrj return save_expr (e);
434138fd1498Szrj /* FALLTHRU */
434238fd1498Szrj case tcc_type:
434338fd1498Szrj case tcc_declaration:
434438fd1498Szrj case tcc_comparison:
434538fd1498Szrj case tcc_statement:
434638fd1498Szrj case tcc_expression:
434738fd1498Szrj case tcc_reference:
434838fd1498Szrj case tcc_vl_exp:
434938fd1498Szrj /* If the expression has side-effects, then encase it in a SAVE_EXPR
435038fd1498Szrj so that it will only be evaluated once. */
435138fd1498Szrj /* The reference (r) and comparison (<) classes could be handled as
435238fd1498Szrj below, but it is generally faster to only evaluate them once. */
435338fd1498Szrj if (TREE_SIDE_EFFECTS (e))
435438fd1498Szrj return save_expr (e);
435538fd1498Szrj return e;
435638fd1498Szrj
435738fd1498Szrj case tcc_constant:
435838fd1498Szrj /* Constants need no processing. In fact, we should never reach
435938fd1498Szrj here. */
436038fd1498Szrj return e;
436138fd1498Szrj
436238fd1498Szrj case tcc_binary:
436338fd1498Szrj /* Division is slow and tends to be compiled with jumps,
436438fd1498Szrj especially the division by powers of 2 that is often
436538fd1498Szrj found inside of an array reference. So do it just once. */
436638fd1498Szrj if (code == TRUNC_DIV_EXPR || code == TRUNC_MOD_EXPR
436738fd1498Szrj || code == FLOOR_DIV_EXPR || code == FLOOR_MOD_EXPR
436838fd1498Szrj || code == CEIL_DIV_EXPR || code == CEIL_MOD_EXPR
436938fd1498Szrj || code == ROUND_DIV_EXPR || code == ROUND_MOD_EXPR)
437038fd1498Szrj return save_expr (e);
437138fd1498Szrj /* Recursively stabilize each operand. */
437238fd1498Szrj result = build_nt (code, stabilize_reference_1 (TREE_OPERAND (e, 0)),
437338fd1498Szrj stabilize_reference_1 (TREE_OPERAND (e, 1)));
437438fd1498Szrj break;
437538fd1498Szrj
437638fd1498Szrj case tcc_unary:
437738fd1498Szrj /* Recursively stabilize each operand. */
437838fd1498Szrj result = build_nt (code, stabilize_reference_1 (TREE_OPERAND (e, 0)));
437938fd1498Szrj break;
438038fd1498Szrj
438138fd1498Szrj default:
438238fd1498Szrj gcc_unreachable ();
438338fd1498Szrj }
438438fd1498Szrj
438538fd1498Szrj TREE_TYPE (result) = TREE_TYPE (e);
438638fd1498Szrj TREE_READONLY (result) = TREE_READONLY (e);
438738fd1498Szrj TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e);
438838fd1498Szrj TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);
438938fd1498Szrj
439038fd1498Szrj return result;
439138fd1498Szrj }
439238fd1498Szrj
439338fd1498Szrj /* Stabilize a reference so that we can use it any number of times
439438fd1498Szrj without causing its operands to be evaluated more than once.
439538fd1498Szrj Returns the stabilized reference. This works by means of save_expr,
439638fd1498Szrj so see the caveats in the comments about save_expr.
439738fd1498Szrj
439838fd1498Szrj Also allows conversion expressions whose operands are references.
439938fd1498Szrj Any other kind of expression is returned unchanged. */
440038fd1498Szrj
440138fd1498Szrj tree
stabilize_reference(tree ref)440238fd1498Szrj stabilize_reference (tree ref)
440338fd1498Szrj {
440438fd1498Szrj tree result;
440538fd1498Szrj enum tree_code code = TREE_CODE (ref);
440638fd1498Szrj
440738fd1498Szrj switch (code)
440838fd1498Szrj {
440938fd1498Szrj case VAR_DECL:
441038fd1498Szrj case PARM_DECL:
441138fd1498Szrj case RESULT_DECL:
441238fd1498Szrj /* No action is needed in this case. */
441338fd1498Szrj return ref;
441438fd1498Szrj
441538fd1498Szrj CASE_CONVERT:
441638fd1498Szrj case FLOAT_EXPR:
441738fd1498Szrj case FIX_TRUNC_EXPR:
441838fd1498Szrj result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
441938fd1498Szrj break;
442038fd1498Szrj
442138fd1498Szrj case INDIRECT_REF:
442238fd1498Szrj result = build_nt (INDIRECT_REF,
442338fd1498Szrj stabilize_reference_1 (TREE_OPERAND (ref, 0)));
442438fd1498Szrj break;
442538fd1498Szrj
442638fd1498Szrj case COMPONENT_REF:
442738fd1498Szrj result = build_nt (COMPONENT_REF,
442838fd1498Szrj stabilize_reference (TREE_OPERAND (ref, 0)),
442938fd1498Szrj TREE_OPERAND (ref, 1), NULL_TREE);
443038fd1498Szrj break;
443138fd1498Szrj
443238fd1498Szrj case BIT_FIELD_REF:
443338fd1498Szrj result = build_nt (BIT_FIELD_REF,
443438fd1498Szrj stabilize_reference (TREE_OPERAND (ref, 0)),
443538fd1498Szrj TREE_OPERAND (ref, 1), TREE_OPERAND (ref, 2));
443638fd1498Szrj REF_REVERSE_STORAGE_ORDER (result) = REF_REVERSE_STORAGE_ORDER (ref);
443738fd1498Szrj break;
443838fd1498Szrj
443938fd1498Szrj case ARRAY_REF:
444038fd1498Szrj result = build_nt (ARRAY_REF,
444138fd1498Szrj stabilize_reference (TREE_OPERAND (ref, 0)),
444238fd1498Szrj stabilize_reference_1 (TREE_OPERAND (ref, 1)),
444338fd1498Szrj TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3));
444438fd1498Szrj break;
444538fd1498Szrj
444638fd1498Szrj case ARRAY_RANGE_REF:
444738fd1498Szrj result = build_nt (ARRAY_RANGE_REF,
444838fd1498Szrj stabilize_reference (TREE_OPERAND (ref, 0)),
444938fd1498Szrj stabilize_reference_1 (TREE_OPERAND (ref, 1)),
445038fd1498Szrj TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3));
445138fd1498Szrj break;
445238fd1498Szrj
445338fd1498Szrj case COMPOUND_EXPR:
445438fd1498Szrj /* We cannot wrap the first expression in a SAVE_EXPR, as then
445538fd1498Szrj it wouldn't be ignored. This matters when dealing with
445638fd1498Szrj volatiles. */
445738fd1498Szrj return stabilize_reference_1 (ref);
445838fd1498Szrj
445938fd1498Szrj /* If arg isn't a kind of lvalue we recognize, make no change.
446038fd1498Szrj Caller should recognize the error for an invalid lvalue. */
446138fd1498Szrj default:
446238fd1498Szrj return ref;
446338fd1498Szrj
446438fd1498Szrj case ERROR_MARK:
446538fd1498Szrj return error_mark_node;
446638fd1498Szrj }
446738fd1498Szrj
446838fd1498Szrj TREE_TYPE (result) = TREE_TYPE (ref);
446938fd1498Szrj TREE_READONLY (result) = TREE_READONLY (ref);
447038fd1498Szrj TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
447138fd1498Szrj TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
447238fd1498Szrj
447338fd1498Szrj return result;
447438fd1498Szrj }
447538fd1498Szrj
447638fd1498Szrj /* Low-level constructors for expressions. */
447738fd1498Szrj
447838fd1498Szrj /* A helper function for build1 and constant folders. Set TREE_CONSTANT,
447938fd1498Szrj and TREE_SIDE_EFFECTS for an ADDR_EXPR. */
448038fd1498Szrj
448138fd1498Szrj void
recompute_tree_invariant_for_addr_expr(tree t)448238fd1498Szrj recompute_tree_invariant_for_addr_expr (tree t)
448338fd1498Szrj {
448438fd1498Szrj tree node;
448538fd1498Szrj bool tc = true, se = false;
448638fd1498Szrj
448738fd1498Szrj gcc_assert (TREE_CODE (t) == ADDR_EXPR);
448838fd1498Szrj
448938fd1498Szrj /* We started out assuming this address is both invariant and constant, but
449038fd1498Szrj does not have side effects. Now go down any handled components and see if
449138fd1498Szrj any of them involve offsets that are either non-constant or non-invariant.
449238fd1498Szrj Also check for side-effects.
449338fd1498Szrj
449438fd1498Szrj ??? Note that this code makes no attempt to deal with the case where
449538fd1498Szrj taking the address of something causes a copy due to misalignment. */
449638fd1498Szrj
449738fd1498Szrj #define UPDATE_FLAGS(NODE) \
449838fd1498Szrj do { tree _node = (NODE); \
449938fd1498Szrj if (_node && !TREE_CONSTANT (_node)) tc = false; \
450038fd1498Szrj if (_node && TREE_SIDE_EFFECTS (_node)) se = true; } while (0)
450138fd1498Szrj
450238fd1498Szrj for (node = TREE_OPERAND (t, 0); handled_component_p (node);
450338fd1498Szrj node = TREE_OPERAND (node, 0))
450438fd1498Szrj {
450538fd1498Szrj /* If the first operand doesn't have an ARRAY_TYPE, this is a bogus
450638fd1498Szrj array reference (probably made temporarily by the G++ front end),
450738fd1498Szrj so ignore all the operands. */
450838fd1498Szrj if ((TREE_CODE (node) == ARRAY_REF
450938fd1498Szrj || TREE_CODE (node) == ARRAY_RANGE_REF)
451038fd1498Szrj && TREE_CODE (TREE_TYPE (TREE_OPERAND (node, 0))) == ARRAY_TYPE)
451138fd1498Szrj {
451238fd1498Szrj UPDATE_FLAGS (TREE_OPERAND (node, 1));
451338fd1498Szrj if (TREE_OPERAND (node, 2))
451438fd1498Szrj UPDATE_FLAGS (TREE_OPERAND (node, 2));
451538fd1498Szrj if (TREE_OPERAND (node, 3))
451638fd1498Szrj UPDATE_FLAGS (TREE_OPERAND (node, 3));
451738fd1498Szrj }
451838fd1498Szrj /* Likewise, just because this is a COMPONENT_REF doesn't mean we have a
451938fd1498Szrj FIELD_DECL, apparently. The G++ front end can put something else
452038fd1498Szrj there, at least temporarily. */
452138fd1498Szrj else if (TREE_CODE (node) == COMPONENT_REF
452238fd1498Szrj && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL)
452338fd1498Szrj {
452438fd1498Szrj if (TREE_OPERAND (node, 2))
452538fd1498Szrj UPDATE_FLAGS (TREE_OPERAND (node, 2));
452638fd1498Szrj }
452738fd1498Szrj }
452838fd1498Szrj
452938fd1498Szrj node = lang_hooks.expr_to_decl (node, &tc, &se);
453038fd1498Szrj
453138fd1498Szrj /* Now see what's inside. If it's an INDIRECT_REF, copy our properties from
453238fd1498Szrj the address, since &(*a)->b is a form of addition. If it's a constant, the
453338fd1498Szrj address is constant too. If it's a decl, its address is constant if the
453438fd1498Szrj decl is static. Everything else is not constant and, furthermore,
453538fd1498Szrj taking the address of a volatile variable is not volatile. */
453638fd1498Szrj if (TREE_CODE (node) == INDIRECT_REF
453738fd1498Szrj || TREE_CODE (node) == MEM_REF)
453838fd1498Szrj UPDATE_FLAGS (TREE_OPERAND (node, 0));
453938fd1498Szrj else if (CONSTANT_CLASS_P (node))
454038fd1498Szrj ;
454138fd1498Szrj else if (DECL_P (node))
454238fd1498Szrj tc &= (staticp (node) != NULL_TREE);
454338fd1498Szrj else
454438fd1498Szrj {
454538fd1498Szrj tc = false;
454638fd1498Szrj se |= TREE_SIDE_EFFECTS (node);
454738fd1498Szrj }
454838fd1498Szrj
454938fd1498Szrj
455038fd1498Szrj TREE_CONSTANT (t) = tc;
455138fd1498Szrj TREE_SIDE_EFFECTS (t) = se;
455238fd1498Szrj #undef UPDATE_FLAGS
455338fd1498Szrj }
455438fd1498Szrj
455538fd1498Szrj /* Build an expression of code CODE, data type TYPE, and operands as
455638fd1498Szrj specified. Expressions and reference nodes can be created this way.
455738fd1498Szrj Constants, decls, types and misc nodes cannot be.
455838fd1498Szrj
455938fd1498Szrj We define 5 non-variadic functions, from 0 to 4 arguments. This is
456038fd1498Szrj enough for all extant tree codes. */
456138fd1498Szrj
456238fd1498Szrj tree
build0(enum tree_code code,tree tt MEM_STAT_DECL)456338fd1498Szrj build0 (enum tree_code code, tree tt MEM_STAT_DECL)
456438fd1498Szrj {
456538fd1498Szrj tree t;
456638fd1498Szrj
456738fd1498Szrj gcc_assert (TREE_CODE_LENGTH (code) == 0);
456838fd1498Szrj
456938fd1498Szrj t = make_node (code PASS_MEM_STAT);
457038fd1498Szrj TREE_TYPE (t) = tt;
457138fd1498Szrj
457238fd1498Szrj return t;
457338fd1498Szrj }
457438fd1498Szrj
457538fd1498Szrj tree
build1(enum tree_code code,tree type,tree node MEM_STAT_DECL)457638fd1498Szrj build1 (enum tree_code code, tree type, tree node MEM_STAT_DECL)
457738fd1498Szrj {
457838fd1498Szrj int length = sizeof (struct tree_exp);
457938fd1498Szrj tree t;
458038fd1498Szrj
458138fd1498Szrj record_node_allocation_statistics (code, length);
458238fd1498Szrj
458338fd1498Szrj gcc_assert (TREE_CODE_LENGTH (code) == 1);
458438fd1498Szrj
458538fd1498Szrj t = ggc_alloc_tree_node_stat (length PASS_MEM_STAT);
458638fd1498Szrj
458738fd1498Szrj memset (t, 0, sizeof (struct tree_common));
458838fd1498Szrj
458938fd1498Szrj TREE_SET_CODE (t, code);
459038fd1498Szrj
459138fd1498Szrj TREE_TYPE (t) = type;
459238fd1498Szrj SET_EXPR_LOCATION (t, UNKNOWN_LOCATION);
459338fd1498Szrj TREE_OPERAND (t, 0) = node;
459438fd1498Szrj if (node && !TYPE_P (node))
459538fd1498Szrj {
459638fd1498Szrj TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (node);
459738fd1498Szrj TREE_READONLY (t) = TREE_READONLY (node);
459838fd1498Szrj }
459938fd1498Szrj
460038fd1498Szrj if (TREE_CODE_CLASS (code) == tcc_statement)
460138fd1498Szrj {
460238fd1498Szrj if (code != DEBUG_BEGIN_STMT)
460338fd1498Szrj TREE_SIDE_EFFECTS (t) = 1;
460438fd1498Szrj }
460538fd1498Szrj else switch (code)
460638fd1498Szrj {
460738fd1498Szrj case VA_ARG_EXPR:
460838fd1498Szrj /* All of these have side-effects, no matter what their
460938fd1498Szrj operands are. */
461038fd1498Szrj TREE_SIDE_EFFECTS (t) = 1;
461138fd1498Szrj TREE_READONLY (t) = 0;
461238fd1498Szrj break;
461338fd1498Szrj
461438fd1498Szrj case INDIRECT_REF:
461538fd1498Szrj /* Whether a dereference is readonly has nothing to do with whether
461638fd1498Szrj its operand is readonly. */
461738fd1498Szrj TREE_READONLY (t) = 0;
461838fd1498Szrj break;
461938fd1498Szrj
462038fd1498Szrj case ADDR_EXPR:
462138fd1498Szrj if (node)
462238fd1498Szrj recompute_tree_invariant_for_addr_expr (t);
462338fd1498Szrj break;
462438fd1498Szrj
462538fd1498Szrj default:
462638fd1498Szrj if ((TREE_CODE_CLASS (code) == tcc_unary || code == VIEW_CONVERT_EXPR)
462738fd1498Szrj && node && !TYPE_P (node)
462838fd1498Szrj && TREE_CONSTANT (node))
462938fd1498Szrj TREE_CONSTANT (t) = 1;
463038fd1498Szrj if (TREE_CODE_CLASS (code) == tcc_reference
463138fd1498Szrj && node && TREE_THIS_VOLATILE (node))
463238fd1498Szrj TREE_THIS_VOLATILE (t) = 1;
463338fd1498Szrj break;
463438fd1498Szrj }
463538fd1498Szrj
463638fd1498Szrj return t;
463738fd1498Szrj }
463838fd1498Szrj
463938fd1498Szrj #define PROCESS_ARG(N) \
464038fd1498Szrj do { \
464138fd1498Szrj TREE_OPERAND (t, N) = arg##N; \
464238fd1498Szrj if (arg##N &&!TYPE_P (arg##N)) \
464338fd1498Szrj { \
464438fd1498Szrj if (TREE_SIDE_EFFECTS (arg##N)) \
464538fd1498Szrj side_effects = 1; \
464638fd1498Szrj if (!TREE_READONLY (arg##N) \
464738fd1498Szrj && !CONSTANT_CLASS_P (arg##N)) \
464838fd1498Szrj (void) (read_only = 0); \
464938fd1498Szrj if (!TREE_CONSTANT (arg##N)) \
465038fd1498Szrj (void) (constant = 0); \
465138fd1498Szrj } \
465238fd1498Szrj } while (0)
465338fd1498Szrj
465438fd1498Szrj tree
build2(enum tree_code code,tree tt,tree arg0,tree arg1 MEM_STAT_DECL)465538fd1498Szrj build2 (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
465638fd1498Szrj {
465738fd1498Szrj bool constant, read_only, side_effects, div_by_zero;
465838fd1498Szrj tree t;
465938fd1498Szrj
466038fd1498Szrj gcc_assert (TREE_CODE_LENGTH (code) == 2);
466138fd1498Szrj
466238fd1498Szrj if ((code == MINUS_EXPR || code == PLUS_EXPR || code == MULT_EXPR)
466338fd1498Szrj && arg0 && arg1 && tt && POINTER_TYPE_P (tt)
466438fd1498Szrj /* When sizetype precision doesn't match that of pointers
466538fd1498Szrj we need to be able to build explicit extensions or truncations
466638fd1498Szrj of the offset argument. */
466738fd1498Szrj && TYPE_PRECISION (sizetype) == TYPE_PRECISION (tt))
466838fd1498Szrj gcc_assert (TREE_CODE (arg0) == INTEGER_CST
466938fd1498Szrj && TREE_CODE (arg1) == INTEGER_CST);
467038fd1498Szrj
467138fd1498Szrj if (code == POINTER_PLUS_EXPR && arg0 && arg1 && tt)
467238fd1498Szrj gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0))
467338fd1498Szrj && ptrofftype_p (TREE_TYPE (arg1)));
467438fd1498Szrj
467538fd1498Szrj t = make_node (code PASS_MEM_STAT);
467638fd1498Szrj TREE_TYPE (t) = tt;
467738fd1498Szrj
467838fd1498Szrj /* Below, we automatically set TREE_SIDE_EFFECTS and TREE_READONLY for the
467938fd1498Szrj result based on those same flags for the arguments. But if the
468038fd1498Szrj arguments aren't really even `tree' expressions, we shouldn't be trying
468138fd1498Szrj to do this. */
468238fd1498Szrj
468338fd1498Szrj /* Expressions without side effects may be constant if their
468438fd1498Szrj arguments are as well. */
468538fd1498Szrj constant = (TREE_CODE_CLASS (code) == tcc_comparison
468638fd1498Szrj || TREE_CODE_CLASS (code) == tcc_binary);
468738fd1498Szrj read_only = 1;
468838fd1498Szrj side_effects = TREE_SIDE_EFFECTS (t);
468938fd1498Szrj
469038fd1498Szrj switch (code)
469138fd1498Szrj {
469238fd1498Szrj case TRUNC_DIV_EXPR:
469338fd1498Szrj case CEIL_DIV_EXPR:
469438fd1498Szrj case FLOOR_DIV_EXPR:
469538fd1498Szrj case ROUND_DIV_EXPR:
469638fd1498Szrj case EXACT_DIV_EXPR:
469738fd1498Szrj case CEIL_MOD_EXPR:
469838fd1498Szrj case FLOOR_MOD_EXPR:
469938fd1498Szrj case ROUND_MOD_EXPR:
470038fd1498Szrj case TRUNC_MOD_EXPR:
470138fd1498Szrj div_by_zero = integer_zerop (arg1);
470238fd1498Szrj break;
470338fd1498Szrj default:
470438fd1498Szrj div_by_zero = false;
470538fd1498Szrj }
470638fd1498Szrj
470738fd1498Szrj PROCESS_ARG (0);
470838fd1498Szrj PROCESS_ARG (1);
470938fd1498Szrj
471038fd1498Szrj TREE_SIDE_EFFECTS (t) = side_effects;
471138fd1498Szrj if (code == MEM_REF)
471238fd1498Szrj {
471338fd1498Szrj if (arg0 && TREE_CODE (arg0) == ADDR_EXPR)
471438fd1498Szrj {
471538fd1498Szrj tree o = TREE_OPERAND (arg0, 0);
471638fd1498Szrj TREE_READONLY (t) = TREE_READONLY (o);
471738fd1498Szrj TREE_THIS_VOLATILE (t) = TREE_THIS_VOLATILE (o);
471838fd1498Szrj }
471938fd1498Szrj }
472038fd1498Szrj else
472138fd1498Szrj {
472238fd1498Szrj TREE_READONLY (t) = read_only;
472338fd1498Szrj /* Don't mark X / 0 as constant. */
472438fd1498Szrj TREE_CONSTANT (t) = constant && !div_by_zero;
472538fd1498Szrj TREE_THIS_VOLATILE (t)
472638fd1498Szrj = (TREE_CODE_CLASS (code) == tcc_reference
472738fd1498Szrj && arg0 && TREE_THIS_VOLATILE (arg0));
472838fd1498Szrj }
472938fd1498Szrj
473038fd1498Szrj return t;
473138fd1498Szrj }
473238fd1498Szrj
473338fd1498Szrj
473438fd1498Szrj tree
build3(enum tree_code code,tree tt,tree arg0,tree arg1,tree arg2 MEM_STAT_DECL)473538fd1498Szrj build3 (enum tree_code code, tree tt, tree arg0, tree arg1,
473638fd1498Szrj tree arg2 MEM_STAT_DECL)
473738fd1498Szrj {
473838fd1498Szrj bool constant, read_only, side_effects;
473938fd1498Szrj tree t;
474038fd1498Szrj
474138fd1498Szrj gcc_assert (TREE_CODE_LENGTH (code) == 3);
474238fd1498Szrj gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
474338fd1498Szrj
474438fd1498Szrj t = make_node (code PASS_MEM_STAT);
474538fd1498Szrj TREE_TYPE (t) = tt;
474638fd1498Szrj
474738fd1498Szrj read_only = 1;
474838fd1498Szrj
474938fd1498Szrj /* As a special exception, if COND_EXPR has NULL branches, we
475038fd1498Szrj assume that it is a gimple statement and always consider
475138fd1498Szrj it to have side effects. */
475238fd1498Szrj if (code == COND_EXPR
475338fd1498Szrj && tt == void_type_node
475438fd1498Szrj && arg1 == NULL_TREE
475538fd1498Szrj && arg2 == NULL_TREE)
475638fd1498Szrj side_effects = true;
475738fd1498Szrj else
475838fd1498Szrj side_effects = TREE_SIDE_EFFECTS (t);
475938fd1498Szrj
476038fd1498Szrj PROCESS_ARG (0);
476138fd1498Szrj PROCESS_ARG (1);
476238fd1498Szrj PROCESS_ARG (2);
476338fd1498Szrj
476438fd1498Szrj if (code == COND_EXPR)
476538fd1498Szrj TREE_READONLY (t) = read_only;
476638fd1498Szrj
476738fd1498Szrj TREE_SIDE_EFFECTS (t) = side_effects;
476838fd1498Szrj TREE_THIS_VOLATILE (t)
476938fd1498Szrj = (TREE_CODE_CLASS (code) == tcc_reference
477038fd1498Szrj && arg0 && TREE_THIS_VOLATILE (arg0));
477138fd1498Szrj
477238fd1498Szrj return t;
477338fd1498Szrj }
477438fd1498Szrj
477538fd1498Szrj tree
build4(enum tree_code code,tree tt,tree arg0,tree arg1,tree arg2,tree arg3 MEM_STAT_DECL)477638fd1498Szrj build4 (enum tree_code code, tree tt, tree arg0, tree arg1,
477738fd1498Szrj tree arg2, tree arg3 MEM_STAT_DECL)
477838fd1498Szrj {
477938fd1498Szrj bool constant, read_only, side_effects;
478038fd1498Szrj tree t;
478138fd1498Szrj
478238fd1498Szrj gcc_assert (TREE_CODE_LENGTH (code) == 4);
478338fd1498Szrj
478438fd1498Szrj t = make_node (code PASS_MEM_STAT);
478538fd1498Szrj TREE_TYPE (t) = tt;
478638fd1498Szrj
478738fd1498Szrj side_effects = TREE_SIDE_EFFECTS (t);
478838fd1498Szrj
478938fd1498Szrj PROCESS_ARG (0);
479038fd1498Szrj PROCESS_ARG (1);
479138fd1498Szrj PROCESS_ARG (2);
479238fd1498Szrj PROCESS_ARG (3);
479338fd1498Szrj
479438fd1498Szrj TREE_SIDE_EFFECTS (t) = side_effects;
479538fd1498Szrj TREE_THIS_VOLATILE (t)
479638fd1498Szrj = (TREE_CODE_CLASS (code) == tcc_reference
479738fd1498Szrj && arg0 && TREE_THIS_VOLATILE (arg0));
479838fd1498Szrj
479938fd1498Szrj return t;
480038fd1498Szrj }
480138fd1498Szrj
480238fd1498Szrj tree
build5(enum tree_code code,tree tt,tree arg0,tree arg1,tree arg2,tree arg3,tree arg4 MEM_STAT_DECL)480338fd1498Szrj build5 (enum tree_code code, tree tt, tree arg0, tree arg1,
480438fd1498Szrj tree arg2, tree arg3, tree arg4 MEM_STAT_DECL)
480538fd1498Szrj {
480638fd1498Szrj bool constant, read_only, side_effects;
480738fd1498Szrj tree t;
480838fd1498Szrj
480938fd1498Szrj gcc_assert (TREE_CODE_LENGTH (code) == 5);
481038fd1498Szrj
481138fd1498Szrj t = make_node (code PASS_MEM_STAT);
481238fd1498Szrj TREE_TYPE (t) = tt;
481338fd1498Szrj
481438fd1498Szrj side_effects = TREE_SIDE_EFFECTS (t);
481538fd1498Szrj
481638fd1498Szrj PROCESS_ARG (0);
481738fd1498Szrj PROCESS_ARG (1);
481838fd1498Szrj PROCESS_ARG (2);
481938fd1498Szrj PROCESS_ARG (3);
482038fd1498Szrj PROCESS_ARG (4);
482138fd1498Szrj
482238fd1498Szrj TREE_SIDE_EFFECTS (t) = side_effects;
482338fd1498Szrj if (code == TARGET_MEM_REF)
482438fd1498Szrj {
482538fd1498Szrj if (arg0 && TREE_CODE (arg0) == ADDR_EXPR)
482638fd1498Szrj {
482738fd1498Szrj tree o = TREE_OPERAND (arg0, 0);
482838fd1498Szrj TREE_READONLY (t) = TREE_READONLY (o);
482938fd1498Szrj TREE_THIS_VOLATILE (t) = TREE_THIS_VOLATILE (o);
483038fd1498Szrj }
483138fd1498Szrj }
483238fd1498Szrj else
483338fd1498Szrj TREE_THIS_VOLATILE (t)
483438fd1498Szrj = (TREE_CODE_CLASS (code) == tcc_reference
483538fd1498Szrj && arg0 && TREE_THIS_VOLATILE (arg0));
483638fd1498Szrj
483738fd1498Szrj return t;
483838fd1498Szrj }
483938fd1498Szrj
484038fd1498Szrj /* Build a simple MEM_REF tree with the sematics of a plain INDIRECT_REF
484138fd1498Szrj on the pointer PTR. */
484238fd1498Szrj
484338fd1498Szrj tree
build_simple_mem_ref_loc(location_t loc,tree ptr)484438fd1498Szrj build_simple_mem_ref_loc (location_t loc, tree ptr)
484538fd1498Szrj {
484638fd1498Szrj poly_int64 offset = 0;
484738fd1498Szrj tree ptype = TREE_TYPE (ptr);
484838fd1498Szrj tree tem;
484938fd1498Szrj /* For convenience allow addresses that collapse to a simple base
485038fd1498Szrj and offset. */
485138fd1498Szrj if (TREE_CODE (ptr) == ADDR_EXPR
485238fd1498Szrj && (handled_component_p (TREE_OPERAND (ptr, 0))
485338fd1498Szrj || TREE_CODE (TREE_OPERAND (ptr, 0)) == MEM_REF))
485438fd1498Szrj {
485538fd1498Szrj ptr = get_addr_base_and_unit_offset (TREE_OPERAND (ptr, 0), &offset);
485638fd1498Szrj gcc_assert (ptr);
485738fd1498Szrj if (TREE_CODE (ptr) == MEM_REF)
485838fd1498Szrj {
485938fd1498Szrj offset += mem_ref_offset (ptr).force_shwi ();
486038fd1498Szrj ptr = TREE_OPERAND (ptr, 0);
486138fd1498Szrj }
486238fd1498Szrj else
486338fd1498Szrj ptr = build_fold_addr_expr (ptr);
486438fd1498Szrj gcc_assert (is_gimple_reg (ptr) || is_gimple_min_invariant (ptr));
486538fd1498Szrj }
486638fd1498Szrj tem = build2 (MEM_REF, TREE_TYPE (ptype),
486738fd1498Szrj ptr, build_int_cst (ptype, offset));
486838fd1498Szrj SET_EXPR_LOCATION (tem, loc);
486938fd1498Szrj return tem;
487038fd1498Szrj }
487138fd1498Szrj
487238fd1498Szrj /* Return the constant offset of a MEM_REF or TARGET_MEM_REF tree T. */
487338fd1498Szrj
487438fd1498Szrj poly_offset_int
mem_ref_offset(const_tree t)487538fd1498Szrj mem_ref_offset (const_tree t)
487638fd1498Szrj {
487738fd1498Szrj return poly_offset_int::from (wi::to_poly_wide (TREE_OPERAND (t, 1)),
487838fd1498Szrj SIGNED);
487938fd1498Szrj }
488038fd1498Szrj
488138fd1498Szrj /* Return an invariant ADDR_EXPR of type TYPE taking the address of BASE
488238fd1498Szrj offsetted by OFFSET units. */
488338fd1498Szrj
488438fd1498Szrj tree
build_invariant_address(tree type,tree base,poly_int64 offset)488538fd1498Szrj build_invariant_address (tree type, tree base, poly_int64 offset)
488638fd1498Szrj {
488738fd1498Szrj tree ref = fold_build2 (MEM_REF, TREE_TYPE (type),
488838fd1498Szrj build_fold_addr_expr (base),
488938fd1498Szrj build_int_cst (ptr_type_node, offset));
489038fd1498Szrj tree addr = build1 (ADDR_EXPR, type, ref);
489138fd1498Szrj recompute_tree_invariant_for_addr_expr (addr);
489238fd1498Szrj return addr;
489338fd1498Szrj }
489438fd1498Szrj
489538fd1498Szrj /* Similar except don't specify the TREE_TYPE
489638fd1498Szrj and leave the TREE_SIDE_EFFECTS as 0.
489738fd1498Szrj It is permissible for arguments to be null,
489838fd1498Szrj or even garbage if their values do not matter. */
489938fd1498Szrj
490038fd1498Szrj tree
build_nt(enum tree_code code,...)490138fd1498Szrj build_nt (enum tree_code code, ...)
490238fd1498Szrj {
490338fd1498Szrj tree t;
490438fd1498Szrj int length;
490538fd1498Szrj int i;
490638fd1498Szrj va_list p;
490738fd1498Szrj
490838fd1498Szrj gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
490938fd1498Szrj
491038fd1498Szrj va_start (p, code);
491138fd1498Szrj
491238fd1498Szrj t = make_node (code);
491338fd1498Szrj length = TREE_CODE_LENGTH (code);
491438fd1498Szrj
491538fd1498Szrj for (i = 0; i < length; i++)
491638fd1498Szrj TREE_OPERAND (t, i) = va_arg (p, tree);
491738fd1498Szrj
491838fd1498Szrj va_end (p);
491938fd1498Szrj return t;
492038fd1498Szrj }
492138fd1498Szrj
492238fd1498Szrj /* Similar to build_nt, but for creating a CALL_EXPR object with a
492338fd1498Szrj tree vec. */
492438fd1498Szrj
492538fd1498Szrj tree
build_nt_call_vec(tree fn,vec<tree,va_gc> * args)492638fd1498Szrj build_nt_call_vec (tree fn, vec<tree, va_gc> *args)
492738fd1498Szrj {
492838fd1498Szrj tree ret, t;
492938fd1498Szrj unsigned int ix;
493038fd1498Szrj
493138fd1498Szrj ret = build_vl_exp (CALL_EXPR, vec_safe_length (args) + 3);
493238fd1498Szrj CALL_EXPR_FN (ret) = fn;
493338fd1498Szrj CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE;
493438fd1498Szrj FOR_EACH_VEC_SAFE_ELT (args, ix, t)
493538fd1498Szrj CALL_EXPR_ARG (ret, ix) = t;
493638fd1498Szrj return ret;
493738fd1498Szrj }
493838fd1498Szrj
493938fd1498Szrj /* Create a DECL_... node of code CODE, name NAME and data type TYPE.
494038fd1498Szrj We do NOT enter this node in any sort of symbol table.
494138fd1498Szrj
494238fd1498Szrj LOC is the location of the decl.
494338fd1498Szrj
494438fd1498Szrj layout_decl is used to set up the decl's storage layout.
494538fd1498Szrj Other slots are initialized to 0 or null pointers. */
494638fd1498Szrj
494738fd1498Szrj tree
build_decl(location_t loc,enum tree_code code,tree name,tree type MEM_STAT_DECL)494838fd1498Szrj build_decl (location_t loc, enum tree_code code, tree name,
494938fd1498Szrj tree type MEM_STAT_DECL)
495038fd1498Szrj {
495138fd1498Szrj tree t;
495238fd1498Szrj
495338fd1498Szrj t = make_node (code PASS_MEM_STAT);
495438fd1498Szrj DECL_SOURCE_LOCATION (t) = loc;
495538fd1498Szrj
495638fd1498Szrj /* if (type == error_mark_node)
495738fd1498Szrj type = integer_type_node; */
495838fd1498Szrj /* That is not done, deliberately, so that having error_mark_node
495938fd1498Szrj as the type can suppress useless errors in the use of this variable. */
496038fd1498Szrj
496138fd1498Szrj DECL_NAME (t) = name;
496238fd1498Szrj TREE_TYPE (t) = type;
496338fd1498Szrj
496438fd1498Szrj if (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL)
496538fd1498Szrj layout_decl (t, 0);
496638fd1498Szrj
496738fd1498Szrj return t;
496838fd1498Szrj }
496938fd1498Szrj
497038fd1498Szrj /* Builds and returns function declaration with NAME and TYPE. */
497138fd1498Szrj
497238fd1498Szrj tree
build_fn_decl(const char * name,tree type)497338fd1498Szrj build_fn_decl (const char *name, tree type)
497438fd1498Szrj {
497538fd1498Szrj tree id = get_identifier (name);
497638fd1498Szrj tree decl = build_decl (input_location, FUNCTION_DECL, id, type);
497738fd1498Szrj
497838fd1498Szrj DECL_EXTERNAL (decl) = 1;
497938fd1498Szrj TREE_PUBLIC (decl) = 1;
498038fd1498Szrj DECL_ARTIFICIAL (decl) = 1;
498138fd1498Szrj TREE_NOTHROW (decl) = 1;
498238fd1498Szrj
498338fd1498Szrj return decl;
498438fd1498Szrj }
498538fd1498Szrj
498638fd1498Szrj vec<tree, va_gc> *all_translation_units;
498738fd1498Szrj
498838fd1498Szrj /* Builds a new translation-unit decl with name NAME, queues it in the
498938fd1498Szrj global list of translation-unit decls and returns it. */
499038fd1498Szrj
499138fd1498Szrj tree
build_translation_unit_decl(tree name)499238fd1498Szrj build_translation_unit_decl (tree name)
499338fd1498Szrj {
499438fd1498Szrj tree tu = build_decl (UNKNOWN_LOCATION, TRANSLATION_UNIT_DECL,
499538fd1498Szrj name, NULL_TREE);
499638fd1498Szrj TRANSLATION_UNIT_LANGUAGE (tu) = lang_hooks.name;
499738fd1498Szrj vec_safe_push (all_translation_units, tu);
499838fd1498Szrj return tu;
499938fd1498Szrj }
500038fd1498Szrj
500138fd1498Szrj
500238fd1498Szrj /* BLOCK nodes are used to represent the structure of binding contours
500338fd1498Szrj and declarations, once those contours have been exited and their contents
500438fd1498Szrj compiled. This information is used for outputting debugging info. */
500538fd1498Szrj
500638fd1498Szrj tree
build_block(tree vars,tree subblocks,tree supercontext,tree chain)500738fd1498Szrj build_block (tree vars, tree subblocks, tree supercontext, tree chain)
500838fd1498Szrj {
500938fd1498Szrj tree block = make_node (BLOCK);
501038fd1498Szrj
501138fd1498Szrj BLOCK_VARS (block) = vars;
501238fd1498Szrj BLOCK_SUBBLOCKS (block) = subblocks;
501338fd1498Szrj BLOCK_SUPERCONTEXT (block) = supercontext;
501438fd1498Szrj BLOCK_CHAIN (block) = chain;
501538fd1498Szrj return block;
501638fd1498Szrj }
501738fd1498Szrj
501838fd1498Szrj
501938fd1498Szrj /* Like SET_EXPR_LOCATION, but make sure the tree can have a location.
502038fd1498Szrj
502138fd1498Szrj LOC is the location to use in tree T. */
502238fd1498Szrj
502338fd1498Szrj void
protected_set_expr_location(tree t,location_t loc)502438fd1498Szrj protected_set_expr_location (tree t, location_t loc)
502538fd1498Szrj {
502638fd1498Szrj if (CAN_HAVE_LOCATION_P (t))
502738fd1498Szrj SET_EXPR_LOCATION (t, loc);
502838fd1498Szrj }
502938fd1498Szrj
503038fd1498Szrj /* Reset the expression *EXPR_P, a size or position.
503138fd1498Szrj
503238fd1498Szrj ??? We could reset all non-constant sizes or positions. But it's cheap
503338fd1498Szrj enough to not do so and refrain from adding workarounds to dwarf2out.c.
503438fd1498Szrj
503538fd1498Szrj We need to reset self-referential sizes or positions because they cannot
503638fd1498Szrj be gimplified and thus can contain a CALL_EXPR after the gimplification
503738fd1498Szrj is finished, which will run afoul of LTO streaming. And they need to be
503838fd1498Szrj reset to something essentially dummy but not constant, so as to preserve
503938fd1498Szrj the properties of the object they are attached to. */
504038fd1498Szrj
504138fd1498Szrj static inline void
free_lang_data_in_one_sizepos(tree * expr_p)504238fd1498Szrj free_lang_data_in_one_sizepos (tree *expr_p)
504338fd1498Szrj {
504438fd1498Szrj tree expr = *expr_p;
504538fd1498Szrj if (CONTAINS_PLACEHOLDER_P (expr))
504638fd1498Szrj *expr_p = build0 (PLACEHOLDER_EXPR, TREE_TYPE (expr));
504738fd1498Szrj }
504838fd1498Szrj
504938fd1498Szrj
505038fd1498Szrj /* Reset all the fields in a binfo node BINFO. We only keep
505138fd1498Szrj BINFO_VTABLE, which is used by gimple_fold_obj_type_ref. */
505238fd1498Szrj
505338fd1498Szrj static void
free_lang_data_in_binfo(tree binfo)505438fd1498Szrj free_lang_data_in_binfo (tree binfo)
505538fd1498Szrj {
505638fd1498Szrj unsigned i;
505738fd1498Szrj tree t;
505838fd1498Szrj
505938fd1498Szrj gcc_assert (TREE_CODE (binfo) == TREE_BINFO);
506038fd1498Szrj
506138fd1498Szrj BINFO_VIRTUALS (binfo) = NULL_TREE;
506238fd1498Szrj BINFO_BASE_ACCESSES (binfo) = NULL;
506338fd1498Szrj BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
506438fd1498Szrj BINFO_SUBVTT_INDEX (binfo) = NULL_TREE;
506538fd1498Szrj
506638fd1498Szrj FOR_EACH_VEC_ELT (*BINFO_BASE_BINFOS (binfo), i, t)
506738fd1498Szrj free_lang_data_in_binfo (t);
506838fd1498Szrj }
506938fd1498Szrj
507038fd1498Szrj
507138fd1498Szrj /* Reset all language specific information still present in TYPE. */
507238fd1498Szrj
507338fd1498Szrj static void
free_lang_data_in_type(tree type)507438fd1498Szrj free_lang_data_in_type (tree type)
507538fd1498Szrj {
507638fd1498Szrj gcc_assert (TYPE_P (type));
507738fd1498Szrj
507838fd1498Szrj /* Give the FE a chance to remove its own data first. */
507938fd1498Szrj lang_hooks.free_lang_data (type);
508038fd1498Szrj
508138fd1498Szrj TREE_LANG_FLAG_0 (type) = 0;
508238fd1498Szrj TREE_LANG_FLAG_1 (type) = 0;
508338fd1498Szrj TREE_LANG_FLAG_2 (type) = 0;
508438fd1498Szrj TREE_LANG_FLAG_3 (type) = 0;
508538fd1498Szrj TREE_LANG_FLAG_4 (type) = 0;
508638fd1498Szrj TREE_LANG_FLAG_5 (type) = 0;
508738fd1498Szrj TREE_LANG_FLAG_6 (type) = 0;
508838fd1498Szrj
508938fd1498Szrj if (TREE_CODE (type) == FUNCTION_TYPE)
509038fd1498Szrj {
509138fd1498Szrj /* Remove the const and volatile qualifiers from arguments. The
509238fd1498Szrj C++ front end removes them, but the C front end does not,
509338fd1498Szrj leading to false ODR violation errors when merging two
509438fd1498Szrj instances of the same function signature compiled by
509538fd1498Szrj different front ends. */
509638fd1498Szrj for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
509738fd1498Szrj {
509838fd1498Szrj tree arg_type = TREE_VALUE (p);
509938fd1498Szrj
510038fd1498Szrj if (TYPE_READONLY (arg_type) || TYPE_VOLATILE (arg_type))
510138fd1498Szrj {
510238fd1498Szrj int quals = TYPE_QUALS (arg_type)
510338fd1498Szrj & ~TYPE_QUAL_CONST
510438fd1498Szrj & ~TYPE_QUAL_VOLATILE;
510538fd1498Szrj TREE_VALUE (p) = build_qualified_type (arg_type, quals);
510638fd1498Szrj free_lang_data_in_type (TREE_VALUE (p));
510738fd1498Szrj }
510838fd1498Szrj /* C++ FE uses TREE_PURPOSE to store initial values. */
510938fd1498Szrj TREE_PURPOSE (p) = NULL;
511038fd1498Szrj }
511138fd1498Szrj }
511238fd1498Szrj else if (TREE_CODE (type) == METHOD_TYPE)
511338fd1498Szrj for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
511438fd1498Szrj /* C++ FE uses TREE_PURPOSE to store initial values. */
511538fd1498Szrj TREE_PURPOSE (p) = NULL;
511638fd1498Szrj else if (RECORD_OR_UNION_TYPE_P (type))
511738fd1498Szrj {
511838fd1498Szrj /* Remove members that are not FIELD_DECLs from the field list
511938fd1498Szrj of an aggregate. These occur in C++. */
512038fd1498Szrj for (tree *prev = &TYPE_FIELDS (type), member; (member = *prev);)
512138fd1498Szrj if (TREE_CODE (member) == FIELD_DECL)
512238fd1498Szrj prev = &DECL_CHAIN (member);
512338fd1498Szrj else
512438fd1498Szrj *prev = DECL_CHAIN (member);
512538fd1498Szrj
512638fd1498Szrj /* FIXME: C FE uses TYPE_VFIELD to record C_TYPE_INCOMPLETE_VARS
512738fd1498Szrj and danagle the pointer from time to time. */
512838fd1498Szrj if (TYPE_VFIELD (type) && TREE_CODE (TYPE_VFIELD (type)) != FIELD_DECL)
512938fd1498Szrj TYPE_VFIELD (type) = NULL_TREE;
513038fd1498Szrj
513138fd1498Szrj if (TYPE_BINFO (type))
513238fd1498Szrj {
513338fd1498Szrj free_lang_data_in_binfo (TYPE_BINFO (type));
513438fd1498Szrj /* We need to preserve link to bases and virtual table for all
513538fd1498Szrj polymorphic types to make devirtualization machinery working. */
513638fd1498Szrj if (!BINFO_VTABLE (TYPE_BINFO (type))
513738fd1498Szrj || !flag_devirtualize)
513838fd1498Szrj TYPE_BINFO (type) = NULL;
513938fd1498Szrj }
514038fd1498Szrj }
514138fd1498Szrj else if (INTEGRAL_TYPE_P (type)
514238fd1498Szrj || SCALAR_FLOAT_TYPE_P (type)
514338fd1498Szrj || FIXED_POINT_TYPE_P (type))
514438fd1498Szrj {
514538fd1498Szrj free_lang_data_in_one_sizepos (&TYPE_MIN_VALUE (type));
514638fd1498Szrj free_lang_data_in_one_sizepos (&TYPE_MAX_VALUE (type));
514738fd1498Szrj }
514838fd1498Szrj
514938fd1498Szrj TYPE_LANG_SLOT_1 (type) = NULL_TREE;
515038fd1498Szrj
515138fd1498Szrj free_lang_data_in_one_sizepos (&TYPE_SIZE (type));
515238fd1498Szrj free_lang_data_in_one_sizepos (&TYPE_SIZE_UNIT (type));
515338fd1498Szrj
515438fd1498Szrj if (TYPE_CONTEXT (type)
515538fd1498Szrj && TREE_CODE (TYPE_CONTEXT (type)) == BLOCK)
515638fd1498Szrj {
515738fd1498Szrj tree ctx = TYPE_CONTEXT (type);
515838fd1498Szrj do
515938fd1498Szrj {
516038fd1498Szrj ctx = BLOCK_SUPERCONTEXT (ctx);
516138fd1498Szrj }
516238fd1498Szrj while (ctx && TREE_CODE (ctx) == BLOCK);
516338fd1498Szrj TYPE_CONTEXT (type) = ctx;
516438fd1498Szrj }
516538fd1498Szrj
516638fd1498Szrj /* Drop TYPE_DECLs in TYPE_NAME in favor of the identifier in the
516738fd1498Szrj TYPE_DECL if the type doesn't have linkage. */
516838fd1498Szrj if (! type_with_linkage_p (type))
516938fd1498Szrj TYPE_NAME (type) = TYPE_IDENTIFIER (type);
517038fd1498Szrj }
517138fd1498Szrj
517238fd1498Szrj
517338fd1498Szrj /* Return true if DECL may need an assembler name to be set. */
517438fd1498Szrj
517538fd1498Szrj static inline bool
need_assembler_name_p(tree decl)517638fd1498Szrj need_assembler_name_p (tree decl)
517738fd1498Szrj {
517838fd1498Szrj /* We use DECL_ASSEMBLER_NAME to hold mangled type names for One Definition
517938fd1498Szrj Rule merging. This makes type_odr_p to return true on those types during
518038fd1498Szrj LTO and by comparing the mangled name, we can say what types are intended
518138fd1498Szrj to be equivalent across compilation unit.
518238fd1498Szrj
518338fd1498Szrj We do not store names of type_in_anonymous_namespace_p.
518438fd1498Szrj
518538fd1498Szrj Record, union and enumeration type have linkage that allows use
518638fd1498Szrj to check type_in_anonymous_namespace_p. We do not mangle compound types
518738fd1498Szrj that always can be compared structurally.
518838fd1498Szrj
518938fd1498Szrj Similarly for builtin types, we compare properties of their main variant.
519038fd1498Szrj A special case are integer types where mangling do make differences
519138fd1498Szrj between char/signed char/unsigned char etc. Storing name for these makes
519238fd1498Szrj e.g. -fno-signed-char/-fsigned-char mismatches to be handled well.
519338fd1498Szrj See cp/mangle.c:write_builtin_type for details. */
519438fd1498Szrj
519538fd1498Szrj if (flag_lto_odr_type_mering
519638fd1498Szrj && TREE_CODE (decl) == TYPE_DECL
519738fd1498Szrj && DECL_NAME (decl)
519838fd1498Szrj && decl == TYPE_NAME (TREE_TYPE (decl))
519938fd1498Szrj && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TREE_TYPE (decl)
520038fd1498Szrj && !TYPE_ARTIFICIAL (TREE_TYPE (decl))
520138fd1498Szrj && (type_with_linkage_p (TREE_TYPE (decl))
520238fd1498Szrj || TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE)
520338fd1498Szrj && !variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
520438fd1498Szrj return !DECL_ASSEMBLER_NAME_SET_P (decl);
520538fd1498Szrj /* Only FUNCTION_DECLs and VAR_DECLs are considered. */
520638fd1498Szrj if (!VAR_OR_FUNCTION_DECL_P (decl))
520738fd1498Szrj return false;
520838fd1498Szrj
520938fd1498Szrj /* If DECL already has its assembler name set, it does not need a
521038fd1498Szrj new one. */
521138fd1498Szrj if (!HAS_DECL_ASSEMBLER_NAME_P (decl)
521238fd1498Szrj || DECL_ASSEMBLER_NAME_SET_P (decl))
521338fd1498Szrj return false;
521438fd1498Szrj
521538fd1498Szrj /* Abstract decls do not need an assembler name. */
521638fd1498Szrj if (DECL_ABSTRACT_P (decl))
521738fd1498Szrj return false;
521838fd1498Szrj
521938fd1498Szrj /* For VAR_DECLs, only static, public and external symbols need an
522038fd1498Szrj assembler name. */
522138fd1498Szrj if (VAR_P (decl)
522238fd1498Szrj && !TREE_STATIC (decl)
522338fd1498Szrj && !TREE_PUBLIC (decl)
522438fd1498Szrj && !DECL_EXTERNAL (decl))
522538fd1498Szrj return false;
522638fd1498Szrj
522738fd1498Szrj if (TREE_CODE (decl) == FUNCTION_DECL)
522838fd1498Szrj {
522938fd1498Szrj /* Do not set assembler name on builtins. Allow RTL expansion to
523038fd1498Szrj decide whether to expand inline or via a regular call. */
523138fd1498Szrj if (DECL_BUILT_IN (decl)
523238fd1498Szrj && DECL_BUILT_IN_CLASS (decl) != BUILT_IN_FRONTEND)
523338fd1498Szrj return false;
523438fd1498Szrj
523538fd1498Szrj /* Functions represented in the callgraph need an assembler name. */
523638fd1498Szrj if (cgraph_node::get (decl) != NULL)
523738fd1498Szrj return true;
523838fd1498Szrj
523938fd1498Szrj /* Unused and not public functions don't need an assembler name. */
524038fd1498Szrj if (!TREE_USED (decl) && !TREE_PUBLIC (decl))
524138fd1498Szrj return false;
524238fd1498Szrj }
524338fd1498Szrj
524438fd1498Szrj return true;
524538fd1498Szrj }
524638fd1498Szrj
524738fd1498Szrj
524838fd1498Szrj /* Reset all language specific information still present in symbol
524938fd1498Szrj DECL. */
525038fd1498Szrj
525138fd1498Szrj static void
free_lang_data_in_decl(tree decl)525238fd1498Szrj free_lang_data_in_decl (tree decl)
525338fd1498Szrj {
525438fd1498Szrj gcc_assert (DECL_P (decl));
525538fd1498Szrj
525638fd1498Szrj /* Give the FE a chance to remove its own data first. */
525738fd1498Szrj lang_hooks.free_lang_data (decl);
525838fd1498Szrj
525938fd1498Szrj TREE_LANG_FLAG_0 (decl) = 0;
526038fd1498Szrj TREE_LANG_FLAG_1 (decl) = 0;
526138fd1498Szrj TREE_LANG_FLAG_2 (decl) = 0;
526238fd1498Szrj TREE_LANG_FLAG_3 (decl) = 0;
526338fd1498Szrj TREE_LANG_FLAG_4 (decl) = 0;
526438fd1498Szrj TREE_LANG_FLAG_5 (decl) = 0;
526538fd1498Szrj TREE_LANG_FLAG_6 (decl) = 0;
526638fd1498Szrj
526738fd1498Szrj free_lang_data_in_one_sizepos (&DECL_SIZE (decl));
526838fd1498Szrj free_lang_data_in_one_sizepos (&DECL_SIZE_UNIT (decl));
526938fd1498Szrj if (TREE_CODE (decl) == FIELD_DECL)
527038fd1498Szrj {
527138fd1498Szrj free_lang_data_in_one_sizepos (&DECL_FIELD_OFFSET (decl));
527238fd1498Szrj if (TREE_CODE (DECL_CONTEXT (decl)) == QUAL_UNION_TYPE)
527338fd1498Szrj DECL_QUALIFIER (decl) = NULL_TREE;
527438fd1498Szrj }
527538fd1498Szrj
527638fd1498Szrj if (TREE_CODE (decl) == FUNCTION_DECL)
527738fd1498Szrj {
527838fd1498Szrj struct cgraph_node *node;
527938fd1498Szrj if (!(node = cgraph_node::get (decl))
528038fd1498Szrj || (!node->definition && !node->clones))
528138fd1498Szrj {
528238fd1498Szrj if (node)
528338fd1498Szrj node->release_body ();
528438fd1498Szrj else
528538fd1498Szrj {
528638fd1498Szrj release_function_body (decl);
528738fd1498Szrj DECL_ARGUMENTS (decl) = NULL;
528838fd1498Szrj DECL_RESULT (decl) = NULL;
528938fd1498Szrj DECL_INITIAL (decl) = error_mark_node;
529038fd1498Szrj }
529138fd1498Szrj }
529238fd1498Szrj if (gimple_has_body_p (decl) || (node && node->thunk.thunk_p))
529338fd1498Szrj {
529438fd1498Szrj tree t;
529538fd1498Szrj
529638fd1498Szrj /* If DECL has a gimple body, then the context for its
529738fd1498Szrj arguments must be DECL. Otherwise, it doesn't really
529838fd1498Szrj matter, as we will not be emitting any code for DECL. In
529938fd1498Szrj general, there may be other instances of DECL created by
530038fd1498Szrj the front end and since PARM_DECLs are generally shared,
530138fd1498Szrj their DECL_CONTEXT changes as the replicas of DECL are
530238fd1498Szrj created. The only time where DECL_CONTEXT is important
530338fd1498Szrj is for the FUNCTION_DECLs that have a gimple body (since
530438fd1498Szrj the PARM_DECL will be used in the function's body). */
530538fd1498Szrj for (t = DECL_ARGUMENTS (decl); t; t = TREE_CHAIN (t))
530638fd1498Szrj DECL_CONTEXT (t) = decl;
530738fd1498Szrj if (!DECL_FUNCTION_SPECIFIC_TARGET (decl))
530838fd1498Szrj DECL_FUNCTION_SPECIFIC_TARGET (decl)
530938fd1498Szrj = target_option_default_node;
531038fd1498Szrj if (!DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl))
531138fd1498Szrj DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl)
531238fd1498Szrj = optimization_default_node;
531338fd1498Szrj }
531438fd1498Szrj
531538fd1498Szrj /* DECL_SAVED_TREE holds the GENERIC representation for DECL.
531638fd1498Szrj At this point, it is not needed anymore. */
531738fd1498Szrj DECL_SAVED_TREE (decl) = NULL_TREE;
531838fd1498Szrj
531938fd1498Szrj /* Clear the abstract origin if it refers to a method.
532038fd1498Szrj Otherwise dwarf2out.c will ICE as we splice functions out of
532138fd1498Szrj TYPE_FIELDS and thus the origin will not be output
532238fd1498Szrj correctly. */
532338fd1498Szrj if (DECL_ABSTRACT_ORIGIN (decl)
532438fd1498Szrj && DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl))
532538fd1498Szrj && RECORD_OR_UNION_TYPE_P
532638fd1498Szrj (DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl))))
532738fd1498Szrj DECL_ABSTRACT_ORIGIN (decl) = NULL_TREE;
532838fd1498Szrj
532938fd1498Szrj /* Sometimes the C++ frontend doesn't manage to transform a temporary
533038fd1498Szrj DECL_VINDEX referring to itself into a vtable slot number as it
533138fd1498Szrj should. Happens with functions that are copied and then forgotten
533238fd1498Szrj about. Just clear it, it won't matter anymore. */
533338fd1498Szrj if (DECL_VINDEX (decl) && !tree_fits_shwi_p (DECL_VINDEX (decl)))
533438fd1498Szrj DECL_VINDEX (decl) = NULL_TREE;
533538fd1498Szrj }
533638fd1498Szrj else if (VAR_P (decl))
533738fd1498Szrj {
533838fd1498Szrj if ((DECL_EXTERNAL (decl)
533938fd1498Szrj && (!TREE_STATIC (decl) || !TREE_READONLY (decl)))
534038fd1498Szrj || (decl_function_context (decl) && !TREE_STATIC (decl)))
534138fd1498Szrj DECL_INITIAL (decl) = NULL_TREE;
534238fd1498Szrj }
534338fd1498Szrj else if (TREE_CODE (decl) == TYPE_DECL)
534438fd1498Szrj {
534538fd1498Szrj DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
534638fd1498Szrj DECL_VISIBILITY_SPECIFIED (decl) = 0;
534738fd1498Szrj DECL_INITIAL (decl) = NULL_TREE;
534838fd1498Szrj }
534938fd1498Szrj else if (TREE_CODE (decl) == FIELD_DECL)
535038fd1498Szrj DECL_INITIAL (decl) = NULL_TREE;
535138fd1498Szrj else if (TREE_CODE (decl) == TRANSLATION_UNIT_DECL
535238fd1498Szrj && DECL_INITIAL (decl)
535338fd1498Szrj && TREE_CODE (DECL_INITIAL (decl)) == BLOCK)
535438fd1498Szrj {
535538fd1498Szrj /* Strip builtins from the translation-unit BLOCK. We still have targets
535638fd1498Szrj without builtin_decl_explicit support and also builtins are shared
535738fd1498Szrj nodes and thus we can't use TREE_CHAIN in multiple lists. */
535838fd1498Szrj tree *nextp = &BLOCK_VARS (DECL_INITIAL (decl));
535938fd1498Szrj while (*nextp)
536038fd1498Szrj {
536138fd1498Szrj tree var = *nextp;
536238fd1498Szrj if (TREE_CODE (var) == FUNCTION_DECL
536338fd1498Szrj && DECL_BUILT_IN (var))
536438fd1498Szrj *nextp = TREE_CHAIN (var);
536538fd1498Szrj else
536638fd1498Szrj nextp = &TREE_CHAIN (var);
536738fd1498Szrj }
536838fd1498Szrj }
536938fd1498Szrj }
537038fd1498Szrj
537138fd1498Szrj
537238fd1498Szrj /* Data used when collecting DECLs and TYPEs for language data removal. */
537338fd1498Szrj
537438fd1498Szrj struct free_lang_data_d
537538fd1498Szrj {
free_lang_data_dfree_lang_data_d537638fd1498Szrj free_lang_data_d () : decls (100), types (100) {}
537738fd1498Szrj
537838fd1498Szrj /* Worklist to avoid excessive recursion. */
537938fd1498Szrj auto_vec<tree> worklist;
538038fd1498Szrj
538138fd1498Szrj /* Set of traversed objects. Used to avoid duplicate visits. */
538238fd1498Szrj hash_set<tree> pset;
538338fd1498Szrj
538438fd1498Szrj /* Array of symbols to process with free_lang_data_in_decl. */
538538fd1498Szrj auto_vec<tree> decls;
538638fd1498Szrj
538738fd1498Szrj /* Array of types to process with free_lang_data_in_type. */
538838fd1498Szrj auto_vec<tree> types;
538938fd1498Szrj };
539038fd1498Szrj
539138fd1498Szrj
539238fd1498Szrj /* Add type or decl T to one of the list of tree nodes that need their
539338fd1498Szrj language data removed. The lists are held inside FLD. */
539438fd1498Szrj
539538fd1498Szrj static void
add_tree_to_fld_list(tree t,struct free_lang_data_d * fld)539638fd1498Szrj add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
539738fd1498Szrj {
539838fd1498Szrj if (DECL_P (t))
539938fd1498Szrj fld->decls.safe_push (t);
540038fd1498Szrj else if (TYPE_P (t))
540138fd1498Szrj fld->types.safe_push (t);
540238fd1498Szrj else
540338fd1498Szrj gcc_unreachable ();
540438fd1498Szrj }
540538fd1498Szrj
540638fd1498Szrj /* Push tree node T into FLD->WORKLIST. */
540738fd1498Szrj
540838fd1498Szrj static inline void
fld_worklist_push(tree t,struct free_lang_data_d * fld)540938fd1498Szrj fld_worklist_push (tree t, struct free_lang_data_d *fld)
541038fd1498Szrj {
541138fd1498Szrj if (t && !is_lang_specific (t) && !fld->pset.contains (t))
541238fd1498Szrj fld->worklist.safe_push ((t));
541338fd1498Szrj }
541438fd1498Szrj
541538fd1498Szrj
541638fd1498Szrj /* Operand callback helper for free_lang_data_in_node. *TP is the
541738fd1498Szrj subtree operand being considered. */
541838fd1498Szrj
541938fd1498Szrj static tree
find_decls_types_r(tree * tp,int * ws,void * data)542038fd1498Szrj find_decls_types_r (tree *tp, int *ws, void *data)
542138fd1498Szrj {
542238fd1498Szrj tree t = *tp;
542338fd1498Szrj struct free_lang_data_d *fld = (struct free_lang_data_d *) data;
542438fd1498Szrj
542538fd1498Szrj if (TREE_CODE (t) == TREE_LIST)
542638fd1498Szrj return NULL_TREE;
542738fd1498Szrj
542838fd1498Szrj /* Language specific nodes will be removed, so there is no need
542938fd1498Szrj to gather anything under them. */
543038fd1498Szrj if (is_lang_specific (t))
543138fd1498Szrj {
543238fd1498Szrj *ws = 0;
543338fd1498Szrj return NULL_TREE;
543438fd1498Szrj }
543538fd1498Szrj
543638fd1498Szrj if (DECL_P (t))
543738fd1498Szrj {
543838fd1498Szrj /* Note that walk_tree does not traverse every possible field in
543938fd1498Szrj decls, so we have to do our own traversals here. */
544038fd1498Szrj add_tree_to_fld_list (t, fld);
544138fd1498Szrj
544238fd1498Szrj fld_worklist_push (DECL_NAME (t), fld);
544338fd1498Szrj fld_worklist_push (DECL_CONTEXT (t), fld);
544438fd1498Szrj fld_worklist_push (DECL_SIZE (t), fld);
544538fd1498Szrj fld_worklist_push (DECL_SIZE_UNIT (t), fld);
544638fd1498Szrj
544738fd1498Szrj /* We are going to remove everything under DECL_INITIAL for
544838fd1498Szrj TYPE_DECLs. No point walking them. */
544938fd1498Szrj if (TREE_CODE (t) != TYPE_DECL)
545038fd1498Szrj fld_worklist_push (DECL_INITIAL (t), fld);
545138fd1498Szrj
545238fd1498Szrj fld_worklist_push (DECL_ATTRIBUTES (t), fld);
545338fd1498Szrj fld_worklist_push (DECL_ABSTRACT_ORIGIN (t), fld);
545438fd1498Szrj
545538fd1498Szrj if (TREE_CODE (t) == FUNCTION_DECL)
545638fd1498Szrj {
545738fd1498Szrj fld_worklist_push (DECL_ARGUMENTS (t), fld);
545838fd1498Szrj fld_worklist_push (DECL_RESULT (t), fld);
545938fd1498Szrj }
546038fd1498Szrj else if (TREE_CODE (t) == TYPE_DECL)
546138fd1498Szrj {
546238fd1498Szrj fld_worklist_push (DECL_ORIGINAL_TYPE (t), fld);
546338fd1498Szrj }
546438fd1498Szrj else if (TREE_CODE (t) == FIELD_DECL)
546538fd1498Szrj {
546638fd1498Szrj fld_worklist_push (DECL_FIELD_OFFSET (t), fld);
546738fd1498Szrj fld_worklist_push (DECL_BIT_FIELD_TYPE (t), fld);
546838fd1498Szrj fld_worklist_push (DECL_FIELD_BIT_OFFSET (t), fld);
546938fd1498Szrj fld_worklist_push (DECL_FCONTEXT (t), fld);
547038fd1498Szrj }
547138fd1498Szrj
547238fd1498Szrj if ((VAR_P (t) || TREE_CODE (t) == PARM_DECL)
547338fd1498Szrj && DECL_HAS_VALUE_EXPR_P (t))
547438fd1498Szrj fld_worklist_push (DECL_VALUE_EXPR (t), fld);
547538fd1498Szrj
547638fd1498Szrj if (TREE_CODE (t) != FIELD_DECL
547738fd1498Szrj && TREE_CODE (t) != TYPE_DECL)
547838fd1498Szrj fld_worklist_push (TREE_CHAIN (t), fld);
547938fd1498Szrj *ws = 0;
548038fd1498Szrj }
548138fd1498Szrj else if (TYPE_P (t))
548238fd1498Szrj {
548338fd1498Szrj /* Note that walk_tree does not traverse every possible field in
548438fd1498Szrj types, so we have to do our own traversals here. */
548538fd1498Szrj add_tree_to_fld_list (t, fld);
548638fd1498Szrj
548738fd1498Szrj if (!RECORD_OR_UNION_TYPE_P (t))
548838fd1498Szrj fld_worklist_push (TYPE_CACHED_VALUES (t), fld);
548938fd1498Szrj fld_worklist_push (TYPE_SIZE (t), fld);
549038fd1498Szrj fld_worklist_push (TYPE_SIZE_UNIT (t), fld);
549138fd1498Szrj fld_worklist_push (TYPE_ATTRIBUTES (t), fld);
549238fd1498Szrj fld_worklist_push (TYPE_POINTER_TO (t), fld);
549338fd1498Szrj fld_worklist_push (TYPE_REFERENCE_TO (t), fld);
549438fd1498Szrj fld_worklist_push (TYPE_NAME (t), fld);
549538fd1498Szrj /* Do not walk TYPE_NEXT_PTR_TO or TYPE_NEXT_REF_TO. We do not stream
549638fd1498Szrj them and thus do not and want not to reach unused pointer types
549738fd1498Szrj this way. */
549838fd1498Szrj if (!POINTER_TYPE_P (t))
549938fd1498Szrj fld_worklist_push (TYPE_MIN_VALUE_RAW (t), fld);
550038fd1498Szrj /* TYPE_MAX_VALUE_RAW is TYPE_BINFO for record types. */
550138fd1498Szrj if (!RECORD_OR_UNION_TYPE_P (t))
550238fd1498Szrj fld_worklist_push (TYPE_MAX_VALUE_RAW (t), fld);
550338fd1498Szrj fld_worklist_push (TYPE_MAIN_VARIANT (t), fld);
550438fd1498Szrj /* Do not walk TYPE_NEXT_VARIANT. We do not stream it and thus
550538fd1498Szrj do not and want not to reach unused variants this way. */
550638fd1498Szrj if (TYPE_CONTEXT (t))
550738fd1498Szrj {
550838fd1498Szrj tree ctx = TYPE_CONTEXT (t);
550938fd1498Szrj /* We adjust BLOCK TYPE_CONTEXTs to the innermost non-BLOCK one.
551038fd1498Szrj So push that instead. */
551138fd1498Szrj while (ctx && TREE_CODE (ctx) == BLOCK)
551238fd1498Szrj ctx = BLOCK_SUPERCONTEXT (ctx);
551338fd1498Szrj fld_worklist_push (ctx, fld);
551438fd1498Szrj }
551538fd1498Szrj /* Do not walk TYPE_CANONICAL. We do not stream it and thus do not
551638fd1498Szrj and want not to reach unused types this way. */
551738fd1498Szrj
551838fd1498Szrj if (RECORD_OR_UNION_TYPE_P (t) && TYPE_BINFO (t))
551938fd1498Szrj {
552038fd1498Szrj unsigned i;
552138fd1498Szrj tree tem;
552238fd1498Szrj FOR_EACH_VEC_ELT (*BINFO_BASE_BINFOS (TYPE_BINFO (t)), i, tem)
552338fd1498Szrj fld_worklist_push (TREE_TYPE (tem), fld);
552438fd1498Szrj fld_worklist_push (BINFO_TYPE (TYPE_BINFO (t)), fld);
552538fd1498Szrj fld_worklist_push (BINFO_VTABLE (TYPE_BINFO (t)), fld);
552638fd1498Szrj }
552738fd1498Szrj if (RECORD_OR_UNION_TYPE_P (t))
552838fd1498Szrj {
552938fd1498Szrj tree tem;
553038fd1498Szrj /* Push all TYPE_FIELDS - there can be interleaving interesting
553138fd1498Szrj and non-interesting things. */
553238fd1498Szrj tem = TYPE_FIELDS (t);
553338fd1498Szrj while (tem)
553438fd1498Szrj {
553538fd1498Szrj if (TREE_CODE (tem) == FIELD_DECL
553638fd1498Szrj || (TREE_CODE (tem) == TYPE_DECL
553738fd1498Szrj && !DECL_IGNORED_P (tem)
553838fd1498Szrj && debug_info_level > DINFO_LEVEL_TERSE
553938fd1498Szrj && !is_redundant_typedef (tem)))
554038fd1498Szrj fld_worklist_push (tem, fld);
554138fd1498Szrj tem = TREE_CHAIN (tem);
554238fd1498Szrj }
554338fd1498Szrj }
554438fd1498Szrj if (FUNC_OR_METHOD_TYPE_P (t))
554538fd1498Szrj fld_worklist_push (TYPE_METHOD_BASETYPE (t), fld);
554638fd1498Szrj
554738fd1498Szrj fld_worklist_push (TYPE_STUB_DECL (t), fld);
554838fd1498Szrj *ws = 0;
554938fd1498Szrj }
555038fd1498Szrj else if (TREE_CODE (t) == BLOCK)
555138fd1498Szrj {
555238fd1498Szrj tree tem;
555338fd1498Szrj for (tem = BLOCK_VARS (t); tem; tem = TREE_CHAIN (tem))
555438fd1498Szrj fld_worklist_push (tem, fld);
555538fd1498Szrj for (tem = BLOCK_SUBBLOCKS (t); tem; tem = BLOCK_CHAIN (tem))
555638fd1498Szrj fld_worklist_push (tem, fld);
555738fd1498Szrj fld_worklist_push (BLOCK_ABSTRACT_ORIGIN (t), fld);
555838fd1498Szrj }
555938fd1498Szrj
556038fd1498Szrj if (TREE_CODE (t) != IDENTIFIER_NODE
556138fd1498Szrj && CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPED))
556238fd1498Szrj fld_worklist_push (TREE_TYPE (t), fld);
556338fd1498Szrj
556438fd1498Szrj return NULL_TREE;
556538fd1498Szrj }
556638fd1498Szrj
556738fd1498Szrj
556838fd1498Szrj /* Find decls and types in T. */
556938fd1498Szrj
557038fd1498Szrj static void
find_decls_types(tree t,struct free_lang_data_d * fld)557138fd1498Szrj find_decls_types (tree t, struct free_lang_data_d *fld)
557238fd1498Szrj {
557338fd1498Szrj while (1)
557438fd1498Szrj {
557538fd1498Szrj if (!fld->pset.contains (t))
557638fd1498Szrj walk_tree (&t, find_decls_types_r, fld, &fld->pset);
557738fd1498Szrj if (fld->worklist.is_empty ())
557838fd1498Szrj break;
557938fd1498Szrj t = fld->worklist.pop ();
558038fd1498Szrj }
558138fd1498Szrj }
558238fd1498Szrj
558338fd1498Szrj /* Translate all the types in LIST with the corresponding runtime
558438fd1498Szrj types. */
558538fd1498Szrj
558638fd1498Szrj static tree
get_eh_types_for_runtime(tree list)558738fd1498Szrj get_eh_types_for_runtime (tree list)
558838fd1498Szrj {
558938fd1498Szrj tree head, prev;
559038fd1498Szrj
559138fd1498Szrj if (list == NULL_TREE)
559238fd1498Szrj return NULL_TREE;
559338fd1498Szrj
559438fd1498Szrj head = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list)));
559538fd1498Szrj prev = head;
559638fd1498Szrj list = TREE_CHAIN (list);
559738fd1498Szrj while (list)
559838fd1498Szrj {
559938fd1498Szrj tree n = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list)));
560038fd1498Szrj TREE_CHAIN (prev) = n;
560138fd1498Szrj prev = TREE_CHAIN (prev);
560238fd1498Szrj list = TREE_CHAIN (list);
560338fd1498Szrj }
560438fd1498Szrj
560538fd1498Szrj return head;
560638fd1498Szrj }
560738fd1498Szrj
560838fd1498Szrj
560938fd1498Szrj /* Find decls and types referenced in EH region R and store them in
561038fd1498Szrj FLD->DECLS and FLD->TYPES. */
561138fd1498Szrj
561238fd1498Szrj static void
find_decls_types_in_eh_region(eh_region r,struct free_lang_data_d * fld)561338fd1498Szrj find_decls_types_in_eh_region (eh_region r, struct free_lang_data_d *fld)
561438fd1498Szrj {
561538fd1498Szrj switch (r->type)
561638fd1498Szrj {
561738fd1498Szrj case ERT_CLEANUP:
561838fd1498Szrj break;
561938fd1498Szrj
562038fd1498Szrj case ERT_TRY:
562138fd1498Szrj {
562238fd1498Szrj eh_catch c;
562338fd1498Szrj
562438fd1498Szrj /* The types referenced in each catch must first be changed to the
562538fd1498Szrj EH types used at runtime. This removes references to FE types
562638fd1498Szrj in the region. */
562738fd1498Szrj for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
562838fd1498Szrj {
562938fd1498Szrj c->type_list = get_eh_types_for_runtime (c->type_list);
563038fd1498Szrj walk_tree (&c->type_list, find_decls_types_r, fld, &fld->pset);
563138fd1498Szrj }
563238fd1498Szrj }
563338fd1498Szrj break;
563438fd1498Szrj
563538fd1498Szrj case ERT_ALLOWED_EXCEPTIONS:
563638fd1498Szrj r->u.allowed.type_list
563738fd1498Szrj = get_eh_types_for_runtime (r->u.allowed.type_list);
563838fd1498Szrj walk_tree (&r->u.allowed.type_list, find_decls_types_r, fld, &fld->pset);
563938fd1498Szrj break;
564038fd1498Szrj
564138fd1498Szrj case ERT_MUST_NOT_THROW:
564238fd1498Szrj walk_tree (&r->u.must_not_throw.failure_decl,
564338fd1498Szrj find_decls_types_r, fld, &fld->pset);
564438fd1498Szrj break;
564538fd1498Szrj }
564638fd1498Szrj }
564738fd1498Szrj
564838fd1498Szrj
564938fd1498Szrj /* Find decls and types referenced in cgraph node N and store them in
565038fd1498Szrj FLD->DECLS and FLD->TYPES. Unlike pass_referenced_vars, this will
565138fd1498Szrj look for *every* kind of DECL and TYPE node reachable from N,
565238fd1498Szrj including those embedded inside types and decls (i.e,, TYPE_DECLs,
565338fd1498Szrj NAMESPACE_DECLs, etc). */
565438fd1498Szrj
565538fd1498Szrj static void
find_decls_types_in_node(struct cgraph_node * n,struct free_lang_data_d * fld)565638fd1498Szrj find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
565738fd1498Szrj {
565838fd1498Szrj basic_block bb;
565938fd1498Szrj struct function *fn;
566038fd1498Szrj unsigned ix;
566138fd1498Szrj tree t;
566238fd1498Szrj
566338fd1498Szrj find_decls_types (n->decl, fld);
566438fd1498Szrj
566538fd1498Szrj if (!gimple_has_body_p (n->decl))
566638fd1498Szrj return;
566738fd1498Szrj
566838fd1498Szrj gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
566938fd1498Szrj
567038fd1498Szrj fn = DECL_STRUCT_FUNCTION (n->decl);
567138fd1498Szrj
567238fd1498Szrj /* Traverse locals. */
567338fd1498Szrj FOR_EACH_LOCAL_DECL (fn, ix, t)
567438fd1498Szrj find_decls_types (t, fld);
567538fd1498Szrj
567638fd1498Szrj /* Traverse EH regions in FN. */
567738fd1498Szrj {
567838fd1498Szrj eh_region r;
567938fd1498Szrj FOR_ALL_EH_REGION_FN (r, fn)
568038fd1498Szrj find_decls_types_in_eh_region (r, fld);
568138fd1498Szrj }
568238fd1498Szrj
568338fd1498Szrj /* Traverse every statement in FN. */
568438fd1498Szrj FOR_EACH_BB_FN (bb, fn)
568538fd1498Szrj {
568638fd1498Szrj gphi_iterator psi;
568738fd1498Szrj gimple_stmt_iterator si;
568838fd1498Szrj unsigned i;
568938fd1498Szrj
569038fd1498Szrj for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
569138fd1498Szrj {
569238fd1498Szrj gphi *phi = psi.phi ();
569338fd1498Szrj
569438fd1498Szrj for (i = 0; i < gimple_phi_num_args (phi); i++)
569538fd1498Szrj {
569638fd1498Szrj tree *arg_p = gimple_phi_arg_def_ptr (phi, i);
569738fd1498Szrj find_decls_types (*arg_p, fld);
569838fd1498Szrj }
569938fd1498Szrj }
570038fd1498Szrj
570138fd1498Szrj for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
570238fd1498Szrj {
570338fd1498Szrj gimple *stmt = gsi_stmt (si);
570438fd1498Szrj
570538fd1498Szrj if (is_gimple_call (stmt))
570638fd1498Szrj find_decls_types (gimple_call_fntype (stmt), fld);
570738fd1498Szrj
570838fd1498Szrj for (i = 0; i < gimple_num_ops (stmt); i++)
570938fd1498Szrj {
571038fd1498Szrj tree arg = gimple_op (stmt, i);
571138fd1498Szrj find_decls_types (arg, fld);
571238fd1498Szrj }
571338fd1498Szrj }
571438fd1498Szrj }
571538fd1498Szrj }
571638fd1498Szrj
571738fd1498Szrj
571838fd1498Szrj /* Find decls and types referenced in varpool node N and store them in
571938fd1498Szrj FLD->DECLS and FLD->TYPES. Unlike pass_referenced_vars, this will
572038fd1498Szrj look for *every* kind of DECL and TYPE node reachable from N,
572138fd1498Szrj including those embedded inside types and decls (i.e,, TYPE_DECLs,
572238fd1498Szrj NAMESPACE_DECLs, etc). */
572338fd1498Szrj
572438fd1498Szrj static void
find_decls_types_in_var(varpool_node * v,struct free_lang_data_d * fld)572538fd1498Szrj find_decls_types_in_var (varpool_node *v, struct free_lang_data_d *fld)
572638fd1498Szrj {
572738fd1498Szrj find_decls_types (v->decl, fld);
572838fd1498Szrj }
572938fd1498Szrj
573038fd1498Szrj /* If T needs an assembler name, have one created for it. */
573138fd1498Szrj
573238fd1498Szrj void
assign_assembler_name_if_needed(tree t)573338fd1498Szrj assign_assembler_name_if_needed (tree t)
573438fd1498Szrj {
573538fd1498Szrj if (need_assembler_name_p (t))
573638fd1498Szrj {
573738fd1498Szrj /* When setting DECL_ASSEMBLER_NAME, the C++ mangler may emit
573838fd1498Szrj diagnostics that use input_location to show locus
573938fd1498Szrj information. The problem here is that, at this point,
574038fd1498Szrj input_location is generally anchored to the end of the file
574138fd1498Szrj (since the parser is long gone), so we don't have a good
574238fd1498Szrj position to pin it to.
574338fd1498Szrj
574438fd1498Szrj To alleviate this problem, this uses the location of T's
574538fd1498Szrj declaration. Examples of this are
574638fd1498Szrj testsuite/g++.dg/template/cond2.C and
574738fd1498Szrj testsuite/g++.dg/template/pr35240.C. */
574838fd1498Szrj location_t saved_location = input_location;
574938fd1498Szrj input_location = DECL_SOURCE_LOCATION (t);
575038fd1498Szrj
575138fd1498Szrj decl_assembler_name (t);
575238fd1498Szrj
575338fd1498Szrj input_location = saved_location;
575438fd1498Szrj }
575538fd1498Szrj }
575638fd1498Szrj
575738fd1498Szrj
575838fd1498Szrj /* Free language specific information for every operand and expression
575938fd1498Szrj in every node of the call graph. This process operates in three stages:
576038fd1498Szrj
576138fd1498Szrj 1- Every callgraph node and varpool node is traversed looking for
576238fd1498Szrj decls and types embedded in them. This is a more exhaustive
576338fd1498Szrj search than that done by find_referenced_vars, because it will
576438fd1498Szrj also collect individual fields, decls embedded in types, etc.
576538fd1498Szrj
576638fd1498Szrj 2- All the decls found are sent to free_lang_data_in_decl.
576738fd1498Szrj
576838fd1498Szrj 3- All the types found are sent to free_lang_data_in_type.
576938fd1498Szrj
577038fd1498Szrj The ordering between decls and types is important because
577138fd1498Szrj free_lang_data_in_decl sets assembler names, which includes
577238fd1498Szrj mangling. So types cannot be freed up until assembler names have
577338fd1498Szrj been set up. */
577438fd1498Szrj
577538fd1498Szrj static void
free_lang_data_in_cgraph(void)577638fd1498Szrj free_lang_data_in_cgraph (void)
577738fd1498Szrj {
577838fd1498Szrj struct cgraph_node *n;
577938fd1498Szrj varpool_node *v;
578038fd1498Szrj struct free_lang_data_d fld;
578138fd1498Szrj tree t;
578238fd1498Szrj unsigned i;
578338fd1498Szrj alias_pair *p;
578438fd1498Szrj
578538fd1498Szrj /* Find decls and types in the body of every function in the callgraph. */
578638fd1498Szrj FOR_EACH_FUNCTION (n)
578738fd1498Szrj find_decls_types_in_node (n, &fld);
578838fd1498Szrj
578938fd1498Szrj FOR_EACH_VEC_SAFE_ELT (alias_pairs, i, p)
579038fd1498Szrj find_decls_types (p->decl, &fld);
579138fd1498Szrj
579238fd1498Szrj /* Find decls and types in every varpool symbol. */
579338fd1498Szrj FOR_EACH_VARIABLE (v)
579438fd1498Szrj find_decls_types_in_var (v, &fld);
579538fd1498Szrj
579638fd1498Szrj /* Set the assembler name on every decl found. We need to do this
579738fd1498Szrj now because free_lang_data_in_decl will invalidate data needed
579838fd1498Szrj for mangling. This breaks mangling on interdependent decls. */
579938fd1498Szrj FOR_EACH_VEC_ELT (fld.decls, i, t)
580038fd1498Szrj assign_assembler_name_if_needed (t);
580138fd1498Szrj
580238fd1498Szrj /* Traverse every decl found freeing its language data. */
580338fd1498Szrj FOR_EACH_VEC_ELT (fld.decls, i, t)
580438fd1498Szrj free_lang_data_in_decl (t);
580538fd1498Szrj
580638fd1498Szrj /* Traverse every type found freeing its language data. */
580738fd1498Szrj FOR_EACH_VEC_ELT (fld.types, i, t)
580838fd1498Szrj free_lang_data_in_type (t);
580938fd1498Szrj if (flag_checking)
581038fd1498Szrj {
581138fd1498Szrj FOR_EACH_VEC_ELT (fld.types, i, t)
581238fd1498Szrj verify_type (t);
581338fd1498Szrj }
581438fd1498Szrj }
581538fd1498Szrj
581638fd1498Szrj
581738fd1498Szrj /* Free resources that are used by FE but are not needed once they are done. */
581838fd1498Szrj
581938fd1498Szrj static unsigned
free_lang_data(void)582038fd1498Szrj free_lang_data (void)
582138fd1498Szrj {
582238fd1498Szrj unsigned i;
582338fd1498Szrj
582438fd1498Szrj /* If we are the LTO frontend we have freed lang-specific data already. */
582538fd1498Szrj if (in_lto_p
582638fd1498Szrj || (!flag_generate_lto && !flag_generate_offload))
5827*58e805e6Szrj {
5828*58e805e6Szrj /* Rebuild type inheritance graph even when not doing LTO to get
5829*58e805e6Szrj consistent profile data. */
5830*58e805e6Szrj rebuild_type_inheritance_graph ();
583138fd1498Szrj return 0;
5832*58e805e6Szrj }
583338fd1498Szrj
583438fd1498Szrj /* Provide a dummy TRANSLATION_UNIT_DECL if the FE failed to provide one. */
583538fd1498Szrj if (vec_safe_is_empty (all_translation_units))
583638fd1498Szrj build_translation_unit_decl (NULL_TREE);
583738fd1498Szrj
583838fd1498Szrj /* Allocate and assign alias sets to the standard integer types
583938fd1498Szrj while the slots are still in the way the frontends generated them. */
584038fd1498Szrj for (i = 0; i < itk_none; ++i)
584138fd1498Szrj if (integer_types[i])
584238fd1498Szrj TYPE_ALIAS_SET (integer_types[i]) = get_alias_set (integer_types[i]);
584338fd1498Szrj
584438fd1498Szrj /* Traverse the IL resetting language specific information for
584538fd1498Szrj operands, expressions, etc. */
584638fd1498Szrj free_lang_data_in_cgraph ();
584738fd1498Szrj
584838fd1498Szrj /* Create gimple variants for common types. */
584938fd1498Szrj for (unsigned i = 0;
585038fd1498Szrj i < sizeof (builtin_structptr_types) / sizeof (builtin_structptr_type);
585138fd1498Szrj ++i)
585238fd1498Szrj builtin_structptr_types[i].node = builtin_structptr_types[i].base;
585338fd1498Szrj
585438fd1498Szrj /* Reset some langhooks. Do not reset types_compatible_p, it may
585538fd1498Szrj still be used indirectly via the get_alias_set langhook. */
585638fd1498Szrj lang_hooks.dwarf_name = lhd_dwarf_name;
585738fd1498Szrj lang_hooks.decl_printable_name = gimple_decl_printable_name;
585838fd1498Szrj lang_hooks.gimplify_expr = lhd_gimplify_expr;
585938fd1498Szrj
586038fd1498Szrj /* We do not want the default decl_assembler_name implementation,
586138fd1498Szrj rather if we have fixed everything we want a wrapper around it
586238fd1498Szrj asserting that all non-local symbols already got their assembler
586338fd1498Szrj name and only produce assembler names for local symbols. Or rather
586438fd1498Szrj make sure we never call decl_assembler_name on local symbols and
586538fd1498Szrj devise a separate, middle-end private scheme for it. */
586638fd1498Szrj
586738fd1498Szrj /* Reset diagnostic machinery. */
586838fd1498Szrj tree_diagnostics_defaults (global_dc);
586938fd1498Szrj
587038fd1498Szrj rebuild_type_inheritance_graph ();
587138fd1498Szrj
587238fd1498Szrj return 0;
587338fd1498Szrj }
587438fd1498Szrj
587538fd1498Szrj
587638fd1498Szrj namespace {
587738fd1498Szrj
587838fd1498Szrj const pass_data pass_data_ipa_free_lang_data =
587938fd1498Szrj {
588038fd1498Szrj SIMPLE_IPA_PASS, /* type */
588138fd1498Szrj "*free_lang_data", /* name */
588238fd1498Szrj OPTGROUP_NONE, /* optinfo_flags */
588338fd1498Szrj TV_IPA_FREE_LANG_DATA, /* tv_id */
588438fd1498Szrj 0, /* properties_required */
588538fd1498Szrj 0, /* properties_provided */
588638fd1498Szrj 0, /* properties_destroyed */
588738fd1498Szrj 0, /* todo_flags_start */
588838fd1498Szrj 0, /* todo_flags_finish */
588938fd1498Szrj };
589038fd1498Szrj
589138fd1498Szrj class pass_ipa_free_lang_data : public simple_ipa_opt_pass
589238fd1498Szrj {
589338fd1498Szrj public:
pass_ipa_free_lang_data(gcc::context * ctxt)589438fd1498Szrj pass_ipa_free_lang_data (gcc::context *ctxt)
589538fd1498Szrj : simple_ipa_opt_pass (pass_data_ipa_free_lang_data, ctxt)
589638fd1498Szrj {}
589738fd1498Szrj
589838fd1498Szrj /* opt_pass methods: */
execute(function *)589938fd1498Szrj virtual unsigned int execute (function *) { return free_lang_data (); }
590038fd1498Szrj
590138fd1498Szrj }; // class pass_ipa_free_lang_data
590238fd1498Szrj
590338fd1498Szrj } // anon namespace
590438fd1498Szrj
590538fd1498Szrj simple_ipa_opt_pass *
make_pass_ipa_free_lang_data(gcc::context * ctxt)590638fd1498Szrj make_pass_ipa_free_lang_data (gcc::context *ctxt)
590738fd1498Szrj {
590838fd1498Szrj return new pass_ipa_free_lang_data (ctxt);
590938fd1498Szrj }
591038fd1498Szrj
591138fd1498Szrj /* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask
591238fd1498Szrj of the various TYPE_QUAL values. */
591338fd1498Szrj
591438fd1498Szrj static void
set_type_quals(tree type,int type_quals)591538fd1498Szrj set_type_quals (tree type, int type_quals)
591638fd1498Szrj {
591738fd1498Szrj TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;
591838fd1498Szrj TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
591938fd1498Szrj TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
592038fd1498Szrj TYPE_ATOMIC (type) = (type_quals & TYPE_QUAL_ATOMIC) != 0;
592138fd1498Szrj TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
592238fd1498Szrj }
592338fd1498Szrj
592438fd1498Szrj /* Returns true iff CAND and BASE have equivalent language-specific
592538fd1498Szrj qualifiers. */
592638fd1498Szrj
592738fd1498Szrj bool
check_lang_type(const_tree cand,const_tree base)592838fd1498Szrj check_lang_type (const_tree cand, const_tree base)
592938fd1498Szrj {
593038fd1498Szrj if (lang_hooks.types.type_hash_eq == NULL)
593138fd1498Szrj return true;
593238fd1498Szrj /* type_hash_eq currently only applies to these types. */
593338fd1498Szrj if (TREE_CODE (cand) != FUNCTION_TYPE
593438fd1498Szrj && TREE_CODE (cand) != METHOD_TYPE)
593538fd1498Szrj return true;
593638fd1498Szrj return lang_hooks.types.type_hash_eq (cand, base);
593738fd1498Szrj }
593838fd1498Szrj
593938fd1498Szrj /* Returns true iff unqualified CAND and BASE are equivalent. */
594038fd1498Szrj
594138fd1498Szrj bool
check_base_type(const_tree cand,const_tree base)594238fd1498Szrj check_base_type (const_tree cand, const_tree base)
594338fd1498Szrj {
594438fd1498Szrj return (TYPE_NAME (cand) == TYPE_NAME (base)
594538fd1498Szrj /* Apparently this is needed for Objective-C. */
594638fd1498Szrj && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
594738fd1498Szrj /* Check alignment. */
594838fd1498Szrj && TYPE_ALIGN (cand) == TYPE_ALIGN (base)
594938fd1498Szrj && attribute_list_equal (TYPE_ATTRIBUTES (cand),
595038fd1498Szrj TYPE_ATTRIBUTES (base)));
595138fd1498Szrj }
595238fd1498Szrj
595338fd1498Szrj /* Returns true iff CAND is equivalent to BASE with TYPE_QUALS. */
595438fd1498Szrj
595538fd1498Szrj bool
check_qualified_type(const_tree cand,const_tree base,int type_quals)595638fd1498Szrj check_qualified_type (const_tree cand, const_tree base, int type_quals)
595738fd1498Szrj {
595838fd1498Szrj return (TYPE_QUALS (cand) == type_quals
595938fd1498Szrj && check_base_type (cand, base)
596038fd1498Szrj && check_lang_type (cand, base));
596138fd1498Szrj }
596238fd1498Szrj
596338fd1498Szrj /* Returns true iff CAND is equivalent to BASE with ALIGN. */
596438fd1498Szrj
596538fd1498Szrj static bool
check_aligned_type(const_tree cand,const_tree base,unsigned int align)596638fd1498Szrj check_aligned_type (const_tree cand, const_tree base, unsigned int align)
596738fd1498Szrj {
596838fd1498Szrj return (TYPE_QUALS (cand) == TYPE_QUALS (base)
596938fd1498Szrj && TYPE_NAME (cand) == TYPE_NAME (base)
597038fd1498Szrj /* Apparently this is needed for Objective-C. */
597138fd1498Szrj && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
597238fd1498Szrj /* Check alignment. */
597338fd1498Szrj && TYPE_ALIGN (cand) == align
597438fd1498Szrj && attribute_list_equal (TYPE_ATTRIBUTES (cand),
597538fd1498Szrj TYPE_ATTRIBUTES (base))
597638fd1498Szrj && check_lang_type (cand, base));
597738fd1498Szrj }
597838fd1498Szrj
597938fd1498Szrj /* This function checks to see if TYPE matches the size one of the built-in
598038fd1498Szrj atomic types, and returns that core atomic type. */
598138fd1498Szrj
598238fd1498Szrj static tree
find_atomic_core_type(tree type)598338fd1498Szrj find_atomic_core_type (tree type)
598438fd1498Szrj {
598538fd1498Szrj tree base_atomic_type;
598638fd1498Szrj
598738fd1498Szrj /* Only handle complete types. */
598838fd1498Szrj if (!tree_fits_uhwi_p (TYPE_SIZE (type)))
598938fd1498Szrj return NULL_TREE;
599038fd1498Szrj
599138fd1498Szrj switch (tree_to_uhwi (TYPE_SIZE (type)))
599238fd1498Szrj {
599338fd1498Szrj case 8:
599438fd1498Szrj base_atomic_type = atomicQI_type_node;
599538fd1498Szrj break;
599638fd1498Szrj
599738fd1498Szrj case 16:
599838fd1498Szrj base_atomic_type = atomicHI_type_node;
599938fd1498Szrj break;
600038fd1498Szrj
600138fd1498Szrj case 32:
600238fd1498Szrj base_atomic_type = atomicSI_type_node;
600338fd1498Szrj break;
600438fd1498Szrj
600538fd1498Szrj case 64:
600638fd1498Szrj base_atomic_type = atomicDI_type_node;
600738fd1498Szrj break;
600838fd1498Szrj
600938fd1498Szrj case 128:
601038fd1498Szrj base_atomic_type = atomicTI_type_node;
601138fd1498Szrj break;
601238fd1498Szrj
601338fd1498Szrj default:
601438fd1498Szrj base_atomic_type = NULL_TREE;
601538fd1498Szrj }
601638fd1498Szrj
601738fd1498Szrj return base_atomic_type;
601838fd1498Szrj }
601938fd1498Szrj
602038fd1498Szrj /* Return a version of the TYPE, qualified as indicated by the
602138fd1498Szrj TYPE_QUALS, if one exists. If no qualified version exists yet,
602238fd1498Szrj return NULL_TREE. */
602338fd1498Szrj
602438fd1498Szrj tree
get_qualified_type(tree type,int type_quals)602538fd1498Szrj get_qualified_type (tree type, int type_quals)
602638fd1498Szrj {
602738fd1498Szrj tree t;
602838fd1498Szrj
602938fd1498Szrj if (TYPE_QUALS (type) == type_quals)
603038fd1498Szrj return type;
603138fd1498Szrj
603238fd1498Szrj /* Search the chain of variants to see if there is already one there just
603338fd1498Szrj like the one we need to have. If so, use that existing one. We must
603438fd1498Szrj preserve the TYPE_NAME, since there is code that depends on this. */
603538fd1498Szrj for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
603638fd1498Szrj if (check_qualified_type (t, type, type_quals))
603738fd1498Szrj return t;
603838fd1498Szrj
603938fd1498Szrj return NULL_TREE;
604038fd1498Szrj }
604138fd1498Szrj
604238fd1498Szrj /* Like get_qualified_type, but creates the type if it does not
604338fd1498Szrj exist. This function never returns NULL_TREE. */
604438fd1498Szrj
604538fd1498Szrj tree
build_qualified_type(tree type,int type_quals MEM_STAT_DECL)604638fd1498Szrj build_qualified_type (tree type, int type_quals MEM_STAT_DECL)
604738fd1498Szrj {
604838fd1498Szrj tree t;
604938fd1498Szrj
605038fd1498Szrj /* See if we already have the appropriate qualified variant. */
605138fd1498Szrj t = get_qualified_type (type, type_quals);
605238fd1498Szrj
605338fd1498Szrj /* If not, build it. */
605438fd1498Szrj if (!t)
605538fd1498Szrj {
605638fd1498Szrj t = build_variant_type_copy (type PASS_MEM_STAT);
605738fd1498Szrj set_type_quals (t, type_quals);
605838fd1498Szrj
605938fd1498Szrj if (((type_quals & TYPE_QUAL_ATOMIC) == TYPE_QUAL_ATOMIC))
606038fd1498Szrj {
606138fd1498Szrj /* See if this object can map to a basic atomic type. */
606238fd1498Szrj tree atomic_type = find_atomic_core_type (type);
606338fd1498Szrj if (atomic_type)
606438fd1498Szrj {
606538fd1498Szrj /* Ensure the alignment of this type is compatible with
606638fd1498Szrj the required alignment of the atomic type. */
606738fd1498Szrj if (TYPE_ALIGN (atomic_type) > TYPE_ALIGN (t))
606838fd1498Szrj SET_TYPE_ALIGN (t, TYPE_ALIGN (atomic_type));
606938fd1498Szrj }
607038fd1498Szrj }
607138fd1498Szrj
607238fd1498Szrj if (TYPE_STRUCTURAL_EQUALITY_P (type))
607338fd1498Szrj /* Propagate structural equality. */
607438fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (t);
607538fd1498Szrj else if (TYPE_CANONICAL (type) != type)
607638fd1498Szrj /* Build the underlying canonical type, since it is different
607738fd1498Szrj from TYPE. */
607838fd1498Szrj {
607938fd1498Szrj tree c = build_qualified_type (TYPE_CANONICAL (type), type_quals);
608038fd1498Szrj TYPE_CANONICAL (t) = TYPE_CANONICAL (c);
608138fd1498Szrj }
608238fd1498Szrj else
608338fd1498Szrj /* T is its own canonical type. */
608438fd1498Szrj TYPE_CANONICAL (t) = t;
608538fd1498Szrj
608638fd1498Szrj }
608738fd1498Szrj
608838fd1498Szrj return t;
608938fd1498Szrj }
609038fd1498Szrj
609138fd1498Szrj /* Create a variant of type T with alignment ALIGN. */
609238fd1498Szrj
609338fd1498Szrj tree
build_aligned_type(tree type,unsigned int align)609438fd1498Szrj build_aligned_type (tree type, unsigned int align)
609538fd1498Szrj {
609638fd1498Szrj tree t;
609738fd1498Szrj
609838fd1498Szrj if (TYPE_PACKED (type)
609938fd1498Szrj || TYPE_ALIGN (type) == align)
610038fd1498Szrj return type;
610138fd1498Szrj
610238fd1498Szrj for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
610338fd1498Szrj if (check_aligned_type (t, type, align))
610438fd1498Szrj return t;
610538fd1498Szrj
610638fd1498Szrj t = build_variant_type_copy (type);
610738fd1498Szrj SET_TYPE_ALIGN (t, align);
610838fd1498Szrj TYPE_USER_ALIGN (t) = 1;
610938fd1498Szrj
611038fd1498Szrj return t;
611138fd1498Szrj }
611238fd1498Szrj
611338fd1498Szrj /* Create a new distinct copy of TYPE. The new type is made its own
611438fd1498Szrj MAIN_VARIANT. If TYPE requires structural equality checks, the
611538fd1498Szrj resulting type requires structural equality checks; otherwise, its
611638fd1498Szrj TYPE_CANONICAL points to itself. */
611738fd1498Szrj
611838fd1498Szrj tree
build_distinct_type_copy(tree type MEM_STAT_DECL)611938fd1498Szrj build_distinct_type_copy (tree type MEM_STAT_DECL)
612038fd1498Szrj {
612138fd1498Szrj tree t = copy_node (type PASS_MEM_STAT);
612238fd1498Szrj
612338fd1498Szrj TYPE_POINTER_TO (t) = 0;
612438fd1498Szrj TYPE_REFERENCE_TO (t) = 0;
612538fd1498Szrj
612638fd1498Szrj /* Set the canonical type either to a new equivalence class, or
612738fd1498Szrj propagate the need for structural equality checks. */
612838fd1498Szrj if (TYPE_STRUCTURAL_EQUALITY_P (type))
612938fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (t);
613038fd1498Szrj else
613138fd1498Szrj TYPE_CANONICAL (t) = t;
613238fd1498Szrj
613338fd1498Szrj /* Make it its own variant. */
613438fd1498Szrj TYPE_MAIN_VARIANT (t) = t;
613538fd1498Szrj TYPE_NEXT_VARIANT (t) = 0;
613638fd1498Szrj
613738fd1498Szrj /* Note that it is now possible for TYPE_MIN_VALUE to be a value
613838fd1498Szrj whose TREE_TYPE is not t. This can also happen in the Ada
613938fd1498Szrj frontend when using subtypes. */
614038fd1498Szrj
614138fd1498Szrj return t;
614238fd1498Szrj }
614338fd1498Szrj
614438fd1498Szrj /* Create a new variant of TYPE, equivalent but distinct. This is so
614538fd1498Szrj the caller can modify it. TYPE_CANONICAL for the return type will
614638fd1498Szrj be equivalent to TYPE_CANONICAL of TYPE, indicating that the types
614738fd1498Szrj are considered equal by the language itself (or that both types
614838fd1498Szrj require structural equality checks). */
614938fd1498Szrj
615038fd1498Szrj tree
build_variant_type_copy(tree type MEM_STAT_DECL)615138fd1498Szrj build_variant_type_copy (tree type MEM_STAT_DECL)
615238fd1498Szrj {
615338fd1498Szrj tree t, m = TYPE_MAIN_VARIANT (type);
615438fd1498Szrj
615538fd1498Szrj t = build_distinct_type_copy (type PASS_MEM_STAT);
615638fd1498Szrj
615738fd1498Szrj /* Since we're building a variant, assume that it is a non-semantic
615838fd1498Szrj variant. This also propagates TYPE_STRUCTURAL_EQUALITY_P. */
615938fd1498Szrj TYPE_CANONICAL (t) = TYPE_CANONICAL (type);
616038fd1498Szrj /* Type variants have no alias set defined. */
616138fd1498Szrj TYPE_ALIAS_SET (t) = -1;
616238fd1498Szrj
616338fd1498Szrj /* Add the new type to the chain of variants of TYPE. */
616438fd1498Szrj TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
616538fd1498Szrj TYPE_NEXT_VARIANT (m) = t;
616638fd1498Szrj TYPE_MAIN_VARIANT (t) = m;
616738fd1498Szrj
616838fd1498Szrj return t;
616938fd1498Szrj }
617038fd1498Szrj
617138fd1498Szrj /* Return true if the from tree in both tree maps are equal. */
617238fd1498Szrj
617338fd1498Szrj int
tree_map_base_eq(const void * va,const void * vb)617438fd1498Szrj tree_map_base_eq (const void *va, const void *vb)
617538fd1498Szrj {
617638fd1498Szrj const struct tree_map_base *const a = (const struct tree_map_base *) va,
617738fd1498Szrj *const b = (const struct tree_map_base *) vb;
617838fd1498Szrj return (a->from == b->from);
617938fd1498Szrj }
618038fd1498Szrj
618138fd1498Szrj /* Hash a from tree in a tree_base_map. */
618238fd1498Szrj
618338fd1498Szrj unsigned int
tree_map_base_hash(const void * item)618438fd1498Szrj tree_map_base_hash (const void *item)
618538fd1498Szrj {
618638fd1498Szrj return htab_hash_pointer (((const struct tree_map_base *)item)->from);
618738fd1498Szrj }
618838fd1498Szrj
618938fd1498Szrj /* Return true if this tree map structure is marked for garbage collection
619038fd1498Szrj purposes. We simply return true if the from tree is marked, so that this
619138fd1498Szrj structure goes away when the from tree goes away. */
619238fd1498Szrj
619338fd1498Szrj int
tree_map_base_marked_p(const void * p)619438fd1498Szrj tree_map_base_marked_p (const void *p)
619538fd1498Szrj {
619638fd1498Szrj return ggc_marked_p (((const struct tree_map_base *) p)->from);
619738fd1498Szrj }
619838fd1498Szrj
619938fd1498Szrj /* Hash a from tree in a tree_map. */
620038fd1498Szrj
620138fd1498Szrj unsigned int
tree_map_hash(const void * item)620238fd1498Szrj tree_map_hash (const void *item)
620338fd1498Szrj {
620438fd1498Szrj return (((const struct tree_map *) item)->hash);
620538fd1498Szrj }
620638fd1498Szrj
620738fd1498Szrj /* Hash a from tree in a tree_decl_map. */
620838fd1498Szrj
620938fd1498Szrj unsigned int
tree_decl_map_hash(const void * item)621038fd1498Szrj tree_decl_map_hash (const void *item)
621138fd1498Szrj {
621238fd1498Szrj return DECL_UID (((const struct tree_decl_map *) item)->base.from);
621338fd1498Szrj }
621438fd1498Szrj
621538fd1498Szrj /* Return the initialization priority for DECL. */
621638fd1498Szrj
621738fd1498Szrj priority_type
decl_init_priority_lookup(tree decl)621838fd1498Szrj decl_init_priority_lookup (tree decl)
621938fd1498Szrj {
622038fd1498Szrj symtab_node *snode = symtab_node::get (decl);
622138fd1498Szrj
622238fd1498Szrj if (!snode)
622338fd1498Szrj return DEFAULT_INIT_PRIORITY;
622438fd1498Szrj return
622538fd1498Szrj snode->get_init_priority ();
622638fd1498Szrj }
622738fd1498Szrj
622838fd1498Szrj /* Return the finalization priority for DECL. */
622938fd1498Szrj
623038fd1498Szrj priority_type
decl_fini_priority_lookup(tree decl)623138fd1498Szrj decl_fini_priority_lookup (tree decl)
623238fd1498Szrj {
623338fd1498Szrj cgraph_node *node = cgraph_node::get (decl);
623438fd1498Szrj
623538fd1498Szrj if (!node)
623638fd1498Szrj return DEFAULT_INIT_PRIORITY;
623738fd1498Szrj return
623838fd1498Szrj node->get_fini_priority ();
623938fd1498Szrj }
624038fd1498Szrj
624138fd1498Szrj /* Set the initialization priority for DECL to PRIORITY. */
624238fd1498Szrj
624338fd1498Szrj void
decl_init_priority_insert(tree decl,priority_type priority)624438fd1498Szrj decl_init_priority_insert (tree decl, priority_type priority)
624538fd1498Szrj {
624638fd1498Szrj struct symtab_node *snode;
624738fd1498Szrj
624838fd1498Szrj if (priority == DEFAULT_INIT_PRIORITY)
624938fd1498Szrj {
625038fd1498Szrj snode = symtab_node::get (decl);
625138fd1498Szrj if (!snode)
625238fd1498Szrj return;
625338fd1498Szrj }
625438fd1498Szrj else if (VAR_P (decl))
625538fd1498Szrj snode = varpool_node::get_create (decl);
625638fd1498Szrj else
625738fd1498Szrj snode = cgraph_node::get_create (decl);
625838fd1498Szrj snode->set_init_priority (priority);
625938fd1498Szrj }
626038fd1498Szrj
626138fd1498Szrj /* Set the finalization priority for DECL to PRIORITY. */
626238fd1498Szrj
626338fd1498Szrj void
decl_fini_priority_insert(tree decl,priority_type priority)626438fd1498Szrj decl_fini_priority_insert (tree decl, priority_type priority)
626538fd1498Szrj {
626638fd1498Szrj struct cgraph_node *node;
626738fd1498Szrj
626838fd1498Szrj if (priority == DEFAULT_INIT_PRIORITY)
626938fd1498Szrj {
627038fd1498Szrj node = cgraph_node::get (decl);
627138fd1498Szrj if (!node)
627238fd1498Szrj return;
627338fd1498Szrj }
627438fd1498Szrj else
627538fd1498Szrj node = cgraph_node::get_create (decl);
627638fd1498Szrj node->set_fini_priority (priority);
627738fd1498Szrj }
627838fd1498Szrj
627938fd1498Szrj /* Print out the statistics for the DECL_DEBUG_EXPR hash table. */
628038fd1498Szrj
628138fd1498Szrj static void
print_debug_expr_statistics(void)628238fd1498Szrj print_debug_expr_statistics (void)
628338fd1498Szrj {
628438fd1498Szrj fprintf (stderr, "DECL_DEBUG_EXPR hash: size %ld, %ld elements, %f collisions\n",
628538fd1498Szrj (long) debug_expr_for_decl->size (),
628638fd1498Szrj (long) debug_expr_for_decl->elements (),
628738fd1498Szrj debug_expr_for_decl->collisions ());
628838fd1498Szrj }
628938fd1498Szrj
629038fd1498Szrj /* Print out the statistics for the DECL_VALUE_EXPR hash table. */
629138fd1498Szrj
629238fd1498Szrj static void
print_value_expr_statistics(void)629338fd1498Szrj print_value_expr_statistics (void)
629438fd1498Szrj {
629538fd1498Szrj fprintf (stderr, "DECL_VALUE_EXPR hash: size %ld, %ld elements, %f collisions\n",
629638fd1498Szrj (long) value_expr_for_decl->size (),
629738fd1498Szrj (long) value_expr_for_decl->elements (),
629838fd1498Szrj value_expr_for_decl->collisions ());
629938fd1498Szrj }
630038fd1498Szrj
630138fd1498Szrj /* Lookup a debug expression for FROM, and return it if we find one. */
630238fd1498Szrj
630338fd1498Szrj tree
decl_debug_expr_lookup(tree from)630438fd1498Szrj decl_debug_expr_lookup (tree from)
630538fd1498Szrj {
630638fd1498Szrj struct tree_decl_map *h, in;
630738fd1498Szrj in.base.from = from;
630838fd1498Szrj
630938fd1498Szrj h = debug_expr_for_decl->find_with_hash (&in, DECL_UID (from));
631038fd1498Szrj if (h)
631138fd1498Szrj return h->to;
631238fd1498Szrj return NULL_TREE;
631338fd1498Szrj }
631438fd1498Szrj
631538fd1498Szrj /* Insert a mapping FROM->TO in the debug expression hashtable. */
631638fd1498Szrj
631738fd1498Szrj void
decl_debug_expr_insert(tree from,tree to)631838fd1498Szrj decl_debug_expr_insert (tree from, tree to)
631938fd1498Szrj {
632038fd1498Szrj struct tree_decl_map *h;
632138fd1498Szrj
632238fd1498Szrj h = ggc_alloc<tree_decl_map> ();
632338fd1498Szrj h->base.from = from;
632438fd1498Szrj h->to = to;
632538fd1498Szrj *debug_expr_for_decl->find_slot_with_hash (h, DECL_UID (from), INSERT) = h;
632638fd1498Szrj }
632738fd1498Szrj
632838fd1498Szrj /* Lookup a value expression for FROM, and return it if we find one. */
632938fd1498Szrj
633038fd1498Szrj tree
decl_value_expr_lookup(tree from)633138fd1498Szrj decl_value_expr_lookup (tree from)
633238fd1498Szrj {
633338fd1498Szrj struct tree_decl_map *h, in;
633438fd1498Szrj in.base.from = from;
633538fd1498Szrj
633638fd1498Szrj h = value_expr_for_decl->find_with_hash (&in, DECL_UID (from));
633738fd1498Szrj if (h)
633838fd1498Szrj return h->to;
633938fd1498Szrj return NULL_TREE;
634038fd1498Szrj }
634138fd1498Szrj
634238fd1498Szrj /* Insert a mapping FROM->TO in the value expression hashtable. */
634338fd1498Szrj
634438fd1498Szrj void
decl_value_expr_insert(tree from,tree to)634538fd1498Szrj decl_value_expr_insert (tree from, tree to)
634638fd1498Szrj {
634738fd1498Szrj struct tree_decl_map *h;
634838fd1498Szrj
634938fd1498Szrj h = ggc_alloc<tree_decl_map> ();
635038fd1498Szrj h->base.from = from;
635138fd1498Szrj h->to = to;
635238fd1498Szrj *value_expr_for_decl->find_slot_with_hash (h, DECL_UID (from), INSERT) = h;
635338fd1498Szrj }
635438fd1498Szrj
635538fd1498Szrj /* Lookup a vector of debug arguments for FROM, and return it if we
635638fd1498Szrj find one. */
635738fd1498Szrj
635838fd1498Szrj vec<tree, va_gc> **
decl_debug_args_lookup(tree from)635938fd1498Szrj decl_debug_args_lookup (tree from)
636038fd1498Szrj {
636138fd1498Szrj struct tree_vec_map *h, in;
636238fd1498Szrj
636338fd1498Szrj if (!DECL_HAS_DEBUG_ARGS_P (from))
636438fd1498Szrj return NULL;
636538fd1498Szrj gcc_checking_assert (debug_args_for_decl != NULL);
636638fd1498Szrj in.base.from = from;
636738fd1498Szrj h = debug_args_for_decl->find_with_hash (&in, DECL_UID (from));
636838fd1498Szrj if (h)
636938fd1498Szrj return &h->to;
637038fd1498Szrj return NULL;
637138fd1498Szrj }
637238fd1498Szrj
637338fd1498Szrj /* Insert a mapping FROM->empty vector of debug arguments in the value
637438fd1498Szrj expression hashtable. */
637538fd1498Szrj
637638fd1498Szrj vec<tree, va_gc> **
decl_debug_args_insert(tree from)637738fd1498Szrj decl_debug_args_insert (tree from)
637838fd1498Szrj {
637938fd1498Szrj struct tree_vec_map *h;
638038fd1498Szrj tree_vec_map **loc;
638138fd1498Szrj
638238fd1498Szrj if (DECL_HAS_DEBUG_ARGS_P (from))
638338fd1498Szrj return decl_debug_args_lookup (from);
638438fd1498Szrj if (debug_args_for_decl == NULL)
638538fd1498Szrj debug_args_for_decl = hash_table<tree_vec_map_cache_hasher>::create_ggc (64);
638638fd1498Szrj h = ggc_alloc<tree_vec_map> ();
638738fd1498Szrj h->base.from = from;
638838fd1498Szrj h->to = NULL;
638938fd1498Szrj loc = debug_args_for_decl->find_slot_with_hash (h, DECL_UID (from), INSERT);
639038fd1498Szrj *loc = h;
639138fd1498Szrj DECL_HAS_DEBUG_ARGS_P (from) = 1;
639238fd1498Szrj return &h->to;
639338fd1498Szrj }
639438fd1498Szrj
639538fd1498Szrj /* Hashing of types so that we don't make duplicates.
639638fd1498Szrj The entry point is `type_hash_canon'. */
639738fd1498Szrj
639838fd1498Szrj /* Generate the default hash code for TYPE. This is designed for
639938fd1498Szrj speed, rather than maximum entropy. */
640038fd1498Szrj
640138fd1498Szrj hashval_t
type_hash_canon_hash(tree type)640238fd1498Szrj type_hash_canon_hash (tree type)
640338fd1498Szrj {
640438fd1498Szrj inchash::hash hstate;
640538fd1498Szrj
640638fd1498Szrj hstate.add_int (TREE_CODE (type));
640738fd1498Szrj
640838fd1498Szrj if (TREE_TYPE (type))
640938fd1498Szrj hstate.add_object (TYPE_HASH (TREE_TYPE (type)));
641038fd1498Szrj
641138fd1498Szrj for (tree t = TYPE_ATTRIBUTES (type); t; t = TREE_CHAIN (t))
641238fd1498Szrj /* Just the identifier is adequate to distinguish. */
641338fd1498Szrj hstate.add_object (IDENTIFIER_HASH_VALUE (get_attribute_name (t)));
641438fd1498Szrj
641538fd1498Szrj switch (TREE_CODE (type))
641638fd1498Szrj {
641738fd1498Szrj case METHOD_TYPE:
641838fd1498Szrj hstate.add_object (TYPE_HASH (TYPE_METHOD_BASETYPE (type)));
641938fd1498Szrj /* FALLTHROUGH. */
642038fd1498Szrj case FUNCTION_TYPE:
642138fd1498Szrj for (tree t = TYPE_ARG_TYPES (type); t; t = TREE_CHAIN (t))
642238fd1498Szrj if (TREE_VALUE (t) != error_mark_node)
642338fd1498Szrj hstate.add_object (TYPE_HASH (TREE_VALUE (t)));
642438fd1498Szrj break;
642538fd1498Szrj
642638fd1498Szrj case OFFSET_TYPE:
642738fd1498Szrj hstate.add_object (TYPE_HASH (TYPE_OFFSET_BASETYPE (type)));
642838fd1498Szrj break;
642938fd1498Szrj
643038fd1498Szrj case ARRAY_TYPE:
643138fd1498Szrj {
643238fd1498Szrj if (TYPE_DOMAIN (type))
643338fd1498Szrj hstate.add_object (TYPE_HASH (TYPE_DOMAIN (type)));
643438fd1498Szrj if (!AGGREGATE_TYPE_P (TREE_TYPE (type)))
643538fd1498Szrj {
643638fd1498Szrj unsigned typeless = TYPE_TYPELESS_STORAGE (type);
643738fd1498Szrj hstate.add_object (typeless);
643838fd1498Szrj }
643938fd1498Szrj }
644038fd1498Szrj break;
644138fd1498Szrj
644238fd1498Szrj case INTEGER_TYPE:
644338fd1498Szrj {
644438fd1498Szrj tree t = TYPE_MAX_VALUE (type);
644538fd1498Szrj if (!t)
644638fd1498Szrj t = TYPE_MIN_VALUE (type);
644738fd1498Szrj for (int i = 0; i < TREE_INT_CST_NUNITS (t); i++)
644838fd1498Szrj hstate.add_object (TREE_INT_CST_ELT (t, i));
644938fd1498Szrj break;
645038fd1498Szrj }
645138fd1498Szrj
645238fd1498Szrj case REAL_TYPE:
645338fd1498Szrj case FIXED_POINT_TYPE:
645438fd1498Szrj {
645538fd1498Szrj unsigned prec = TYPE_PRECISION (type);
645638fd1498Szrj hstate.add_object (prec);
645738fd1498Szrj break;
645838fd1498Szrj }
645938fd1498Szrj
646038fd1498Szrj case VECTOR_TYPE:
646138fd1498Szrj hstate.add_poly_int (TYPE_VECTOR_SUBPARTS (type));
646238fd1498Szrj break;
646338fd1498Szrj
646438fd1498Szrj default:
646538fd1498Szrj break;
646638fd1498Szrj }
646738fd1498Szrj
646838fd1498Szrj return hstate.end ();
646938fd1498Szrj }
647038fd1498Szrj
647138fd1498Szrj /* These are the Hashtable callback functions. */
647238fd1498Szrj
647338fd1498Szrj /* Returns true iff the types are equivalent. */
647438fd1498Szrj
647538fd1498Szrj bool
equal(type_hash * a,type_hash * b)647638fd1498Szrj type_cache_hasher::equal (type_hash *a, type_hash *b)
647738fd1498Szrj {
647838fd1498Szrj /* First test the things that are the same for all types. */
647938fd1498Szrj if (a->hash != b->hash
648038fd1498Szrj || TREE_CODE (a->type) != TREE_CODE (b->type)
648138fd1498Szrj || TREE_TYPE (a->type) != TREE_TYPE (b->type)
648238fd1498Szrj || !attribute_list_equal (TYPE_ATTRIBUTES (a->type),
648338fd1498Szrj TYPE_ATTRIBUTES (b->type))
648438fd1498Szrj || (TREE_CODE (a->type) != COMPLEX_TYPE
648538fd1498Szrj && TYPE_NAME (a->type) != TYPE_NAME (b->type)))
648638fd1498Szrj return 0;
648738fd1498Szrj
648838fd1498Szrj /* Be careful about comparing arrays before and after the element type
648938fd1498Szrj has been completed; don't compare TYPE_ALIGN unless both types are
649038fd1498Szrj complete. */
649138fd1498Szrj if (COMPLETE_TYPE_P (a->type) && COMPLETE_TYPE_P (b->type)
649238fd1498Szrj && (TYPE_ALIGN (a->type) != TYPE_ALIGN (b->type)
649338fd1498Szrj || TYPE_MODE (a->type) != TYPE_MODE (b->type)))
649438fd1498Szrj return 0;
649538fd1498Szrj
649638fd1498Szrj switch (TREE_CODE (a->type))
649738fd1498Szrj {
649838fd1498Szrj case VOID_TYPE:
649938fd1498Szrj case COMPLEX_TYPE:
650038fd1498Szrj case POINTER_TYPE:
650138fd1498Szrj case REFERENCE_TYPE:
650238fd1498Szrj case NULLPTR_TYPE:
650338fd1498Szrj return 1;
650438fd1498Szrj
650538fd1498Szrj case VECTOR_TYPE:
650638fd1498Szrj return known_eq (TYPE_VECTOR_SUBPARTS (a->type),
650738fd1498Szrj TYPE_VECTOR_SUBPARTS (b->type));
650838fd1498Szrj
650938fd1498Szrj case ENUMERAL_TYPE:
651038fd1498Szrj if (TYPE_VALUES (a->type) != TYPE_VALUES (b->type)
651138fd1498Szrj && !(TYPE_VALUES (a->type)
651238fd1498Szrj && TREE_CODE (TYPE_VALUES (a->type)) == TREE_LIST
651338fd1498Szrj && TYPE_VALUES (b->type)
651438fd1498Szrj && TREE_CODE (TYPE_VALUES (b->type)) == TREE_LIST
651538fd1498Szrj && type_list_equal (TYPE_VALUES (a->type),
651638fd1498Szrj TYPE_VALUES (b->type))))
651738fd1498Szrj return 0;
651838fd1498Szrj
651938fd1498Szrj /* fall through */
652038fd1498Szrj
652138fd1498Szrj case INTEGER_TYPE:
652238fd1498Szrj case REAL_TYPE:
652338fd1498Szrj case BOOLEAN_TYPE:
652438fd1498Szrj if (TYPE_PRECISION (a->type) != TYPE_PRECISION (b->type))
652538fd1498Szrj return false;
652638fd1498Szrj return ((TYPE_MAX_VALUE (a->type) == TYPE_MAX_VALUE (b->type)
652738fd1498Szrj || tree_int_cst_equal (TYPE_MAX_VALUE (a->type),
652838fd1498Szrj TYPE_MAX_VALUE (b->type)))
652938fd1498Szrj && (TYPE_MIN_VALUE (a->type) == TYPE_MIN_VALUE (b->type)
653038fd1498Szrj || tree_int_cst_equal (TYPE_MIN_VALUE (a->type),
653138fd1498Szrj TYPE_MIN_VALUE (b->type))));
653238fd1498Szrj
653338fd1498Szrj case FIXED_POINT_TYPE:
653438fd1498Szrj return TYPE_SATURATING (a->type) == TYPE_SATURATING (b->type);
653538fd1498Szrj
653638fd1498Szrj case OFFSET_TYPE:
653738fd1498Szrj return TYPE_OFFSET_BASETYPE (a->type) == TYPE_OFFSET_BASETYPE (b->type);
653838fd1498Szrj
653938fd1498Szrj case METHOD_TYPE:
654038fd1498Szrj if (TYPE_METHOD_BASETYPE (a->type) == TYPE_METHOD_BASETYPE (b->type)
654138fd1498Szrj && (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type)
654238fd1498Szrj || (TYPE_ARG_TYPES (a->type)
654338fd1498Szrj && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST
654438fd1498Szrj && TYPE_ARG_TYPES (b->type)
654538fd1498Szrj && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST
654638fd1498Szrj && type_list_equal (TYPE_ARG_TYPES (a->type),
654738fd1498Szrj TYPE_ARG_TYPES (b->type)))))
654838fd1498Szrj break;
654938fd1498Szrj return 0;
655038fd1498Szrj case ARRAY_TYPE:
655138fd1498Szrj /* Don't compare TYPE_TYPELESS_STORAGE flag on aggregates,
655238fd1498Szrj where the flag should be inherited from the element type
655338fd1498Szrj and can change after ARRAY_TYPEs are created; on non-aggregates
655438fd1498Szrj compare it and hash it, scalars will never have that flag set
655538fd1498Szrj and we need to differentiate between arrays created by different
655638fd1498Szrj front-ends or middle-end created arrays. */
655738fd1498Szrj return (TYPE_DOMAIN (a->type) == TYPE_DOMAIN (b->type)
655838fd1498Szrj && (AGGREGATE_TYPE_P (TREE_TYPE (a->type))
655938fd1498Szrj || (TYPE_TYPELESS_STORAGE (a->type)
656038fd1498Szrj == TYPE_TYPELESS_STORAGE (b->type))));
656138fd1498Szrj
656238fd1498Szrj case RECORD_TYPE:
656338fd1498Szrj case UNION_TYPE:
656438fd1498Szrj case QUAL_UNION_TYPE:
656538fd1498Szrj return (TYPE_FIELDS (a->type) == TYPE_FIELDS (b->type)
656638fd1498Szrj || (TYPE_FIELDS (a->type)
656738fd1498Szrj && TREE_CODE (TYPE_FIELDS (a->type)) == TREE_LIST
656838fd1498Szrj && TYPE_FIELDS (b->type)
656938fd1498Szrj && TREE_CODE (TYPE_FIELDS (b->type)) == TREE_LIST
657038fd1498Szrj && type_list_equal (TYPE_FIELDS (a->type),
657138fd1498Szrj TYPE_FIELDS (b->type))));
657238fd1498Szrj
657338fd1498Szrj case FUNCTION_TYPE:
657438fd1498Szrj if (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type)
657538fd1498Szrj || (TYPE_ARG_TYPES (a->type)
657638fd1498Szrj && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST
657738fd1498Szrj && TYPE_ARG_TYPES (b->type)
657838fd1498Szrj && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST
657938fd1498Szrj && type_list_equal (TYPE_ARG_TYPES (a->type),
658038fd1498Szrj TYPE_ARG_TYPES (b->type))))
658138fd1498Szrj break;
658238fd1498Szrj return 0;
658338fd1498Szrj
658438fd1498Szrj default:
658538fd1498Szrj return 0;
658638fd1498Szrj }
658738fd1498Szrj
658838fd1498Szrj if (lang_hooks.types.type_hash_eq != NULL)
658938fd1498Szrj return lang_hooks.types.type_hash_eq (a->type, b->type);
659038fd1498Szrj
659138fd1498Szrj return 1;
659238fd1498Szrj }
659338fd1498Szrj
659438fd1498Szrj /* Given TYPE, and HASHCODE its hash code, return the canonical
659538fd1498Szrj object for an identical type if one already exists.
659638fd1498Szrj Otherwise, return TYPE, and record it as the canonical object.
659738fd1498Szrj
659838fd1498Szrj To use this function, first create a type of the sort you want.
659938fd1498Szrj Then compute its hash code from the fields of the type that
660038fd1498Szrj make it different from other similar types.
660138fd1498Szrj Then call this function and use the value. */
660238fd1498Szrj
660338fd1498Szrj tree
type_hash_canon(unsigned int hashcode,tree type)660438fd1498Szrj type_hash_canon (unsigned int hashcode, tree type)
660538fd1498Szrj {
660638fd1498Szrj type_hash in;
660738fd1498Szrj type_hash **loc;
660838fd1498Szrj
660938fd1498Szrj /* The hash table only contains main variants, so ensure that's what we're
661038fd1498Szrj being passed. */
661138fd1498Szrj gcc_assert (TYPE_MAIN_VARIANT (type) == type);
661238fd1498Szrj
661338fd1498Szrj /* The TYPE_ALIGN field of a type is set by layout_type(), so we
661438fd1498Szrj must call that routine before comparing TYPE_ALIGNs. */
661538fd1498Szrj layout_type (type);
661638fd1498Szrj
661738fd1498Szrj in.hash = hashcode;
661838fd1498Szrj in.type = type;
661938fd1498Szrj
662038fd1498Szrj loc = type_hash_table->find_slot_with_hash (&in, hashcode, INSERT);
662138fd1498Szrj if (*loc)
662238fd1498Szrj {
662338fd1498Szrj tree t1 = ((type_hash *) *loc)->type;
6624*58e805e6Szrj gcc_assert (TYPE_MAIN_VARIANT (t1) == t1
6625*58e805e6Szrj && t1 != type);
662638fd1498Szrj if (TYPE_UID (type) + 1 == next_type_uid)
662738fd1498Szrj --next_type_uid;
662838fd1498Szrj /* Free also min/max values and the cache for integer
662938fd1498Szrj types. This can't be done in free_node, as LTO frees
663038fd1498Szrj those on its own. */
663138fd1498Szrj if (TREE_CODE (type) == INTEGER_TYPE)
663238fd1498Szrj {
663338fd1498Szrj if (TYPE_MIN_VALUE (type)
663438fd1498Szrj && TREE_TYPE (TYPE_MIN_VALUE (type)) == type)
663538fd1498Szrj {
663638fd1498Szrj /* Zero is always in TYPE_CACHED_VALUES. */
663738fd1498Szrj if (! TYPE_UNSIGNED (type))
663838fd1498Szrj int_cst_hash_table->remove_elt (TYPE_MIN_VALUE (type));
663938fd1498Szrj ggc_free (TYPE_MIN_VALUE (type));
664038fd1498Szrj }
664138fd1498Szrj if (TYPE_MAX_VALUE (type)
664238fd1498Szrj && TREE_TYPE (TYPE_MAX_VALUE (type)) == type)
664338fd1498Szrj {
664438fd1498Szrj int_cst_hash_table->remove_elt (TYPE_MAX_VALUE (type));
664538fd1498Szrj ggc_free (TYPE_MAX_VALUE (type));
664638fd1498Szrj }
664738fd1498Szrj if (TYPE_CACHED_VALUES_P (type))
664838fd1498Szrj ggc_free (TYPE_CACHED_VALUES (type));
664938fd1498Szrj }
665038fd1498Szrj free_node (type);
665138fd1498Szrj return t1;
665238fd1498Szrj }
665338fd1498Szrj else
665438fd1498Szrj {
665538fd1498Szrj struct type_hash *h;
665638fd1498Szrj
665738fd1498Szrj h = ggc_alloc<type_hash> ();
665838fd1498Szrj h->hash = hashcode;
665938fd1498Szrj h->type = type;
666038fd1498Szrj *loc = h;
666138fd1498Szrj
666238fd1498Szrj return type;
666338fd1498Szrj }
666438fd1498Szrj }
666538fd1498Szrj
666638fd1498Szrj static void
print_type_hash_statistics(void)666738fd1498Szrj print_type_hash_statistics (void)
666838fd1498Szrj {
666938fd1498Szrj fprintf (stderr, "Type hash: size %ld, %ld elements, %f collisions\n",
667038fd1498Szrj (long) type_hash_table->size (),
667138fd1498Szrj (long) type_hash_table->elements (),
667238fd1498Szrj type_hash_table->collisions ());
667338fd1498Szrj }
667438fd1498Szrj
667538fd1498Szrj /* Given two lists of types
667638fd1498Szrj (chains of TREE_LIST nodes with types in the TREE_VALUE slots)
667738fd1498Szrj return 1 if the lists contain the same types in the same order.
667838fd1498Szrj Also, the TREE_PURPOSEs must match. */
667938fd1498Szrj
668038fd1498Szrj int
type_list_equal(const_tree l1,const_tree l2)668138fd1498Szrj type_list_equal (const_tree l1, const_tree l2)
668238fd1498Szrj {
668338fd1498Szrj const_tree t1, t2;
668438fd1498Szrj
668538fd1498Szrj for (t1 = l1, t2 = l2; t1 && t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
668638fd1498Szrj if (TREE_VALUE (t1) != TREE_VALUE (t2)
668738fd1498Szrj || (TREE_PURPOSE (t1) != TREE_PURPOSE (t2)
668838fd1498Szrj && ! (1 == simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2))
668938fd1498Szrj && (TREE_TYPE (TREE_PURPOSE (t1))
669038fd1498Szrj == TREE_TYPE (TREE_PURPOSE (t2))))))
669138fd1498Szrj return 0;
669238fd1498Szrj
669338fd1498Szrj return t1 == t2;
669438fd1498Szrj }
669538fd1498Szrj
669638fd1498Szrj /* Returns the number of arguments to the FUNCTION_TYPE or METHOD_TYPE
669738fd1498Szrj given by TYPE. If the argument list accepts variable arguments,
669838fd1498Szrj then this function counts only the ordinary arguments. */
669938fd1498Szrj
670038fd1498Szrj int
type_num_arguments(const_tree type)670138fd1498Szrj type_num_arguments (const_tree type)
670238fd1498Szrj {
670338fd1498Szrj int i = 0;
670438fd1498Szrj tree t;
670538fd1498Szrj
670638fd1498Szrj for (t = TYPE_ARG_TYPES (type); t; t = TREE_CHAIN (t))
670738fd1498Szrj /* If the function does not take a variable number of arguments,
670838fd1498Szrj the last element in the list will have type `void'. */
670938fd1498Szrj if (VOID_TYPE_P (TREE_VALUE (t)))
671038fd1498Szrj break;
671138fd1498Szrj else
671238fd1498Szrj ++i;
671338fd1498Szrj
671438fd1498Szrj return i;
671538fd1498Szrj }
671638fd1498Szrj
671738fd1498Szrj /* Nonzero if integer constants T1 and T2
671838fd1498Szrj represent the same constant value. */
671938fd1498Szrj
672038fd1498Szrj int
tree_int_cst_equal(const_tree t1,const_tree t2)672138fd1498Szrj tree_int_cst_equal (const_tree t1, const_tree t2)
672238fd1498Szrj {
672338fd1498Szrj if (t1 == t2)
672438fd1498Szrj return 1;
672538fd1498Szrj
672638fd1498Szrj if (t1 == 0 || t2 == 0)
672738fd1498Szrj return 0;
672838fd1498Szrj
672938fd1498Szrj if (TREE_CODE (t1) == INTEGER_CST
673038fd1498Szrj && TREE_CODE (t2) == INTEGER_CST
673138fd1498Szrj && wi::to_widest (t1) == wi::to_widest (t2))
673238fd1498Szrj return 1;
673338fd1498Szrj
673438fd1498Szrj return 0;
673538fd1498Szrj }
673638fd1498Szrj
673738fd1498Szrj /* Return true if T is an INTEGER_CST whose numerical value (extended
673838fd1498Szrj according to TYPE_UNSIGNED) fits in a signed HOST_WIDE_INT. */
673938fd1498Szrj
674038fd1498Szrj bool
tree_fits_shwi_p(const_tree t)674138fd1498Szrj tree_fits_shwi_p (const_tree t)
674238fd1498Szrj {
674338fd1498Szrj return (t != NULL_TREE
674438fd1498Szrj && TREE_CODE (t) == INTEGER_CST
674538fd1498Szrj && wi::fits_shwi_p (wi::to_widest (t)));
674638fd1498Szrj }
674738fd1498Szrj
674838fd1498Szrj /* Return true if T is an INTEGER_CST or POLY_INT_CST whose numerical
674938fd1498Szrj value (extended according to TYPE_UNSIGNED) fits in a poly_int64. */
675038fd1498Szrj
675138fd1498Szrj bool
tree_fits_poly_int64_p(const_tree t)675238fd1498Szrj tree_fits_poly_int64_p (const_tree t)
675338fd1498Szrj {
675438fd1498Szrj if (t == NULL_TREE)
675538fd1498Szrj return false;
675638fd1498Szrj if (POLY_INT_CST_P (t))
675738fd1498Szrj {
675838fd1498Szrj for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; i++)
675938fd1498Szrj if (!wi::fits_shwi_p (wi::to_wide (POLY_INT_CST_COEFF (t, i))))
676038fd1498Szrj return false;
676138fd1498Szrj return true;
676238fd1498Szrj }
676338fd1498Szrj return (TREE_CODE (t) == INTEGER_CST
676438fd1498Szrj && wi::fits_shwi_p (wi::to_widest (t)));
676538fd1498Szrj }
676638fd1498Szrj
676738fd1498Szrj /* Return true if T is an INTEGER_CST whose numerical value (extended
676838fd1498Szrj according to TYPE_UNSIGNED) fits in an unsigned HOST_WIDE_INT. */
676938fd1498Szrj
677038fd1498Szrj bool
tree_fits_uhwi_p(const_tree t)677138fd1498Szrj tree_fits_uhwi_p (const_tree t)
677238fd1498Szrj {
677338fd1498Szrj return (t != NULL_TREE
677438fd1498Szrj && TREE_CODE (t) == INTEGER_CST
677538fd1498Szrj && wi::fits_uhwi_p (wi::to_widest (t)));
677638fd1498Szrj }
677738fd1498Szrj
677838fd1498Szrj /* Return true if T is an INTEGER_CST or POLY_INT_CST whose numerical
677938fd1498Szrj value (extended according to TYPE_UNSIGNED) fits in a poly_uint64. */
678038fd1498Szrj
678138fd1498Szrj bool
tree_fits_poly_uint64_p(const_tree t)678238fd1498Szrj tree_fits_poly_uint64_p (const_tree t)
678338fd1498Szrj {
678438fd1498Szrj if (t == NULL_TREE)
678538fd1498Szrj return false;
678638fd1498Szrj if (POLY_INT_CST_P (t))
678738fd1498Szrj {
678838fd1498Szrj for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; i++)
678938fd1498Szrj if (!wi::fits_uhwi_p (wi::to_widest (POLY_INT_CST_COEFF (t, i))))
679038fd1498Szrj return false;
679138fd1498Szrj return true;
679238fd1498Szrj }
679338fd1498Szrj return (TREE_CODE (t) == INTEGER_CST
679438fd1498Szrj && wi::fits_uhwi_p (wi::to_widest (t)));
679538fd1498Szrj }
679638fd1498Szrj
679738fd1498Szrj /* T is an INTEGER_CST whose numerical value (extended according to
679838fd1498Szrj TYPE_UNSIGNED) fits in a signed HOST_WIDE_INT. Return that
679938fd1498Szrj HOST_WIDE_INT. */
680038fd1498Szrj
680138fd1498Szrj HOST_WIDE_INT
tree_to_shwi(const_tree t)680238fd1498Szrj tree_to_shwi (const_tree t)
680338fd1498Szrj {
680438fd1498Szrj gcc_assert (tree_fits_shwi_p (t));
680538fd1498Szrj return TREE_INT_CST_LOW (t);
680638fd1498Szrj }
680738fd1498Szrj
680838fd1498Szrj /* T is an INTEGER_CST whose numerical value (extended according to
680938fd1498Szrj TYPE_UNSIGNED) fits in an unsigned HOST_WIDE_INT. Return that
681038fd1498Szrj HOST_WIDE_INT. */
681138fd1498Szrj
681238fd1498Szrj unsigned HOST_WIDE_INT
tree_to_uhwi(const_tree t)681338fd1498Szrj tree_to_uhwi (const_tree t)
681438fd1498Szrj {
681538fd1498Szrj gcc_assert (tree_fits_uhwi_p (t));
681638fd1498Szrj return TREE_INT_CST_LOW (t);
681738fd1498Szrj }
681838fd1498Szrj
681938fd1498Szrj /* Return the most significant (sign) bit of T. */
682038fd1498Szrj
682138fd1498Szrj int
tree_int_cst_sign_bit(const_tree t)682238fd1498Szrj tree_int_cst_sign_bit (const_tree t)
682338fd1498Szrj {
682438fd1498Szrj unsigned bitno = TYPE_PRECISION (TREE_TYPE (t)) - 1;
682538fd1498Szrj
682638fd1498Szrj return wi::extract_uhwi (wi::to_wide (t), bitno, 1);
682738fd1498Szrj }
682838fd1498Szrj
682938fd1498Szrj /* Return an indication of the sign of the integer constant T.
683038fd1498Szrj The return value is -1 if T < 0, 0 if T == 0, and 1 if T > 0.
683138fd1498Szrj Note that -1 will never be returned if T's type is unsigned. */
683238fd1498Szrj
683338fd1498Szrj int
tree_int_cst_sgn(const_tree t)683438fd1498Szrj tree_int_cst_sgn (const_tree t)
683538fd1498Szrj {
683638fd1498Szrj if (wi::to_wide (t) == 0)
683738fd1498Szrj return 0;
683838fd1498Szrj else if (TYPE_UNSIGNED (TREE_TYPE (t)))
683938fd1498Szrj return 1;
684038fd1498Szrj else if (wi::neg_p (wi::to_wide (t)))
684138fd1498Szrj return -1;
684238fd1498Szrj else
684338fd1498Szrj return 1;
684438fd1498Szrj }
684538fd1498Szrj
684638fd1498Szrj /* Return the minimum number of bits needed to represent VALUE in a
684738fd1498Szrj signed or unsigned type, UNSIGNEDP says which. */
684838fd1498Szrj
684938fd1498Szrj unsigned int
tree_int_cst_min_precision(tree value,signop sgn)685038fd1498Szrj tree_int_cst_min_precision (tree value, signop sgn)
685138fd1498Szrj {
685238fd1498Szrj /* If the value is negative, compute its negative minus 1. The latter
685338fd1498Szrj adjustment is because the absolute value of the largest negative value
685438fd1498Szrj is one larger than the largest positive value. This is equivalent to
685538fd1498Szrj a bit-wise negation, so use that operation instead. */
685638fd1498Szrj
685738fd1498Szrj if (tree_int_cst_sgn (value) < 0)
685838fd1498Szrj value = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (value), value);
685938fd1498Szrj
686038fd1498Szrj /* Return the number of bits needed, taking into account the fact
686138fd1498Szrj that we need one more bit for a signed than unsigned type.
686238fd1498Szrj If value is 0 or -1, the minimum precision is 1 no matter
686338fd1498Szrj whether unsignedp is true or false. */
686438fd1498Szrj
686538fd1498Szrj if (integer_zerop (value))
686638fd1498Szrj return 1;
686738fd1498Szrj else
686838fd1498Szrj return tree_floor_log2 (value) + 1 + (sgn == SIGNED ? 1 : 0) ;
686938fd1498Szrj }
687038fd1498Szrj
687138fd1498Szrj /* Return truthvalue of whether T1 is the same tree structure as T2.
687238fd1498Szrj Return 1 if they are the same.
687338fd1498Szrj Return 0 if they are understandably different.
687438fd1498Szrj Return -1 if either contains tree structure not understood by
687538fd1498Szrj this function. */
687638fd1498Szrj
687738fd1498Szrj int
simple_cst_equal(const_tree t1,const_tree t2)687838fd1498Szrj simple_cst_equal (const_tree t1, const_tree t2)
687938fd1498Szrj {
688038fd1498Szrj enum tree_code code1, code2;
688138fd1498Szrj int cmp;
688238fd1498Szrj int i;
688338fd1498Szrj
688438fd1498Szrj if (t1 == t2)
688538fd1498Szrj return 1;
688638fd1498Szrj if (t1 == 0 || t2 == 0)
688738fd1498Szrj return 0;
688838fd1498Szrj
688938fd1498Szrj code1 = TREE_CODE (t1);
689038fd1498Szrj code2 = TREE_CODE (t2);
689138fd1498Szrj
689238fd1498Szrj if (CONVERT_EXPR_CODE_P (code1) || code1 == NON_LVALUE_EXPR)
689338fd1498Szrj {
689438fd1498Szrj if (CONVERT_EXPR_CODE_P (code2)
689538fd1498Szrj || code2 == NON_LVALUE_EXPR)
689638fd1498Szrj return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
689738fd1498Szrj else
689838fd1498Szrj return simple_cst_equal (TREE_OPERAND (t1, 0), t2);
689938fd1498Szrj }
690038fd1498Szrj
690138fd1498Szrj else if (CONVERT_EXPR_CODE_P (code2)
690238fd1498Szrj || code2 == NON_LVALUE_EXPR)
690338fd1498Szrj return simple_cst_equal (t1, TREE_OPERAND (t2, 0));
690438fd1498Szrj
690538fd1498Szrj if (code1 != code2)
690638fd1498Szrj return 0;
690738fd1498Szrj
690838fd1498Szrj switch (code1)
690938fd1498Szrj {
691038fd1498Szrj case INTEGER_CST:
691138fd1498Szrj return wi::to_widest (t1) == wi::to_widest (t2);
691238fd1498Szrj
691338fd1498Szrj case REAL_CST:
691438fd1498Szrj return real_identical (&TREE_REAL_CST (t1), &TREE_REAL_CST (t2));
691538fd1498Szrj
691638fd1498Szrj case FIXED_CST:
691738fd1498Szrj return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1), TREE_FIXED_CST (t2));
691838fd1498Szrj
691938fd1498Szrj case STRING_CST:
692038fd1498Szrj return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
692138fd1498Szrj && ! memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
692238fd1498Szrj TREE_STRING_LENGTH (t1)));
692338fd1498Szrj
692438fd1498Szrj case CONSTRUCTOR:
692538fd1498Szrj {
692638fd1498Szrj unsigned HOST_WIDE_INT idx;
692738fd1498Szrj vec<constructor_elt, va_gc> *v1 = CONSTRUCTOR_ELTS (t1);
692838fd1498Szrj vec<constructor_elt, va_gc> *v2 = CONSTRUCTOR_ELTS (t2);
692938fd1498Szrj
693038fd1498Szrj if (vec_safe_length (v1) != vec_safe_length (v2))
693138fd1498Szrj return false;
693238fd1498Szrj
693338fd1498Szrj for (idx = 0; idx < vec_safe_length (v1); ++idx)
693438fd1498Szrj /* ??? Should we handle also fields here? */
693538fd1498Szrj if (!simple_cst_equal ((*v1)[idx].value, (*v2)[idx].value))
693638fd1498Szrj return false;
693738fd1498Szrj return true;
693838fd1498Szrj }
693938fd1498Szrj
694038fd1498Szrj case SAVE_EXPR:
694138fd1498Szrj return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
694238fd1498Szrj
694338fd1498Szrj case CALL_EXPR:
694438fd1498Szrj cmp = simple_cst_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2));
694538fd1498Szrj if (cmp <= 0)
694638fd1498Szrj return cmp;
694738fd1498Szrj if (call_expr_nargs (t1) != call_expr_nargs (t2))
694838fd1498Szrj return 0;
694938fd1498Szrj {
695038fd1498Szrj const_tree arg1, arg2;
695138fd1498Szrj const_call_expr_arg_iterator iter1, iter2;
695238fd1498Szrj for (arg1 = first_const_call_expr_arg (t1, &iter1),
695338fd1498Szrj arg2 = first_const_call_expr_arg (t2, &iter2);
695438fd1498Szrj arg1 && arg2;
695538fd1498Szrj arg1 = next_const_call_expr_arg (&iter1),
695638fd1498Szrj arg2 = next_const_call_expr_arg (&iter2))
695738fd1498Szrj {
695838fd1498Szrj cmp = simple_cst_equal (arg1, arg2);
695938fd1498Szrj if (cmp <= 0)
696038fd1498Szrj return cmp;
696138fd1498Szrj }
696238fd1498Szrj return arg1 == arg2;
696338fd1498Szrj }
696438fd1498Szrj
696538fd1498Szrj case TARGET_EXPR:
696638fd1498Szrj /* Special case: if either target is an unallocated VAR_DECL,
696738fd1498Szrj it means that it's going to be unified with whatever the
696838fd1498Szrj TARGET_EXPR is really supposed to initialize, so treat it
696938fd1498Szrj as being equivalent to anything. */
697038fd1498Szrj if ((TREE_CODE (TREE_OPERAND (t1, 0)) == VAR_DECL
697138fd1498Szrj && DECL_NAME (TREE_OPERAND (t1, 0)) == NULL_TREE
697238fd1498Szrj && !DECL_RTL_SET_P (TREE_OPERAND (t1, 0)))
697338fd1498Szrj || (TREE_CODE (TREE_OPERAND (t2, 0)) == VAR_DECL
697438fd1498Szrj && DECL_NAME (TREE_OPERAND (t2, 0)) == NULL_TREE
697538fd1498Szrj && !DECL_RTL_SET_P (TREE_OPERAND (t2, 0))))
697638fd1498Szrj cmp = 1;
697738fd1498Szrj else
697838fd1498Szrj cmp = simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
697938fd1498Szrj
698038fd1498Szrj if (cmp <= 0)
698138fd1498Szrj return cmp;
698238fd1498Szrj
698338fd1498Szrj return simple_cst_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
698438fd1498Szrj
698538fd1498Szrj case WITH_CLEANUP_EXPR:
698638fd1498Szrj cmp = simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
698738fd1498Szrj if (cmp <= 0)
698838fd1498Szrj return cmp;
698938fd1498Szrj
699038fd1498Szrj return simple_cst_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t1, 1));
699138fd1498Szrj
699238fd1498Szrj case COMPONENT_REF:
699338fd1498Szrj if (TREE_OPERAND (t1, 1) == TREE_OPERAND (t2, 1))
699438fd1498Szrj return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
699538fd1498Szrj
699638fd1498Szrj return 0;
699738fd1498Szrj
699838fd1498Szrj case VAR_DECL:
699938fd1498Szrj case PARM_DECL:
700038fd1498Szrj case CONST_DECL:
700138fd1498Szrj case FUNCTION_DECL:
700238fd1498Szrj return 0;
700338fd1498Szrj
700438fd1498Szrj default:
700538fd1498Szrj if (POLY_INT_CST_P (t1))
700638fd1498Szrj /* A false return means maybe_ne rather than known_ne. */
700738fd1498Szrj return known_eq (poly_widest_int::from (poly_int_cst_value (t1),
700838fd1498Szrj TYPE_SIGN (TREE_TYPE (t1))),
700938fd1498Szrj poly_widest_int::from (poly_int_cst_value (t2),
701038fd1498Szrj TYPE_SIGN (TREE_TYPE (t2))));
701138fd1498Szrj break;
701238fd1498Szrj }
701338fd1498Szrj
701438fd1498Szrj /* This general rule works for most tree codes. All exceptions should be
701538fd1498Szrj handled above. If this is a language-specific tree code, we can't
701638fd1498Szrj trust what might be in the operand, so say we don't know
701738fd1498Szrj the situation. */
701838fd1498Szrj if ((int) code1 >= (int) LAST_AND_UNUSED_TREE_CODE)
701938fd1498Szrj return -1;
702038fd1498Szrj
702138fd1498Szrj switch (TREE_CODE_CLASS (code1))
702238fd1498Szrj {
702338fd1498Szrj case tcc_unary:
702438fd1498Szrj case tcc_binary:
702538fd1498Szrj case tcc_comparison:
702638fd1498Szrj case tcc_expression:
702738fd1498Szrj case tcc_reference:
702838fd1498Szrj case tcc_statement:
702938fd1498Szrj cmp = 1;
703038fd1498Szrj for (i = 0; i < TREE_CODE_LENGTH (code1); i++)
703138fd1498Szrj {
703238fd1498Szrj cmp = simple_cst_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i));
703338fd1498Szrj if (cmp <= 0)
703438fd1498Szrj return cmp;
703538fd1498Szrj }
703638fd1498Szrj
703738fd1498Szrj return cmp;
703838fd1498Szrj
703938fd1498Szrj default:
704038fd1498Szrj return -1;
704138fd1498Szrj }
704238fd1498Szrj }
704338fd1498Szrj
704438fd1498Szrj /* Compare the value of T, an INTEGER_CST, with U, an unsigned integer value.
704538fd1498Szrj Return -1, 0, or 1 if the value of T is less than, equal to, or greater
704638fd1498Szrj than U, respectively. */
704738fd1498Szrj
704838fd1498Szrj int
compare_tree_int(const_tree t,unsigned HOST_WIDE_INT u)704938fd1498Szrj compare_tree_int (const_tree t, unsigned HOST_WIDE_INT u)
705038fd1498Szrj {
705138fd1498Szrj if (tree_int_cst_sgn (t) < 0)
705238fd1498Szrj return -1;
705338fd1498Szrj else if (!tree_fits_uhwi_p (t))
705438fd1498Szrj return 1;
705538fd1498Szrj else if (TREE_INT_CST_LOW (t) == u)
705638fd1498Szrj return 0;
705738fd1498Szrj else if (TREE_INT_CST_LOW (t) < u)
705838fd1498Szrj return -1;
705938fd1498Szrj else
706038fd1498Szrj return 1;
706138fd1498Szrj }
706238fd1498Szrj
706338fd1498Szrj /* Return true if SIZE represents a constant size that is in bounds of
706438fd1498Szrj what the middle-end and the backend accepts (covering not more than
706538fd1498Szrj half of the address-space). */
706638fd1498Szrj
706738fd1498Szrj bool
valid_constant_size_p(const_tree size)706838fd1498Szrj valid_constant_size_p (const_tree size)
706938fd1498Szrj {
707038fd1498Szrj if (POLY_INT_CST_P (size))
707138fd1498Szrj {
707238fd1498Szrj if (TREE_OVERFLOW (size))
707338fd1498Szrj return false;
707438fd1498Szrj for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
707538fd1498Szrj if (!valid_constant_size_p (POLY_INT_CST_COEFF (size, i)))
707638fd1498Szrj return false;
707738fd1498Szrj return true;
707838fd1498Szrj }
707938fd1498Szrj if (! tree_fits_uhwi_p (size)
708038fd1498Szrj || TREE_OVERFLOW (size)
708138fd1498Szrj || tree_int_cst_sign_bit (size) != 0)
708238fd1498Szrj return false;
708338fd1498Szrj return true;
708438fd1498Szrj }
708538fd1498Szrj
708638fd1498Szrj /* Return the precision of the type, or for a complex or vector type the
708738fd1498Szrj precision of the type of its elements. */
708838fd1498Szrj
708938fd1498Szrj unsigned int
element_precision(const_tree type)709038fd1498Szrj element_precision (const_tree type)
709138fd1498Szrj {
709238fd1498Szrj if (!TYPE_P (type))
709338fd1498Szrj type = TREE_TYPE (type);
709438fd1498Szrj enum tree_code code = TREE_CODE (type);
709538fd1498Szrj if (code == COMPLEX_TYPE || code == VECTOR_TYPE)
709638fd1498Szrj type = TREE_TYPE (type);
709738fd1498Szrj
709838fd1498Szrj return TYPE_PRECISION (type);
709938fd1498Szrj }
710038fd1498Szrj
710138fd1498Szrj /* Return true if CODE represents an associative tree code. Otherwise
710238fd1498Szrj return false. */
710338fd1498Szrj bool
associative_tree_code(enum tree_code code)710438fd1498Szrj associative_tree_code (enum tree_code code)
710538fd1498Szrj {
710638fd1498Szrj switch (code)
710738fd1498Szrj {
710838fd1498Szrj case BIT_IOR_EXPR:
710938fd1498Szrj case BIT_AND_EXPR:
711038fd1498Szrj case BIT_XOR_EXPR:
711138fd1498Szrj case PLUS_EXPR:
711238fd1498Szrj case MULT_EXPR:
711338fd1498Szrj case MIN_EXPR:
711438fd1498Szrj case MAX_EXPR:
711538fd1498Szrj return true;
711638fd1498Szrj
711738fd1498Szrj default:
711838fd1498Szrj break;
711938fd1498Szrj }
712038fd1498Szrj return false;
712138fd1498Szrj }
712238fd1498Szrj
712338fd1498Szrj /* Return true if CODE represents a commutative tree code. Otherwise
712438fd1498Szrj return false. */
712538fd1498Szrj bool
commutative_tree_code(enum tree_code code)712638fd1498Szrj commutative_tree_code (enum tree_code code)
712738fd1498Szrj {
712838fd1498Szrj switch (code)
712938fd1498Szrj {
713038fd1498Szrj case PLUS_EXPR:
713138fd1498Szrj case MULT_EXPR:
713238fd1498Szrj case MULT_HIGHPART_EXPR:
713338fd1498Szrj case MIN_EXPR:
713438fd1498Szrj case MAX_EXPR:
713538fd1498Szrj case BIT_IOR_EXPR:
713638fd1498Szrj case BIT_XOR_EXPR:
713738fd1498Szrj case BIT_AND_EXPR:
713838fd1498Szrj case NE_EXPR:
713938fd1498Szrj case EQ_EXPR:
714038fd1498Szrj case UNORDERED_EXPR:
714138fd1498Szrj case ORDERED_EXPR:
714238fd1498Szrj case UNEQ_EXPR:
714338fd1498Szrj case LTGT_EXPR:
714438fd1498Szrj case TRUTH_AND_EXPR:
714538fd1498Szrj case TRUTH_XOR_EXPR:
714638fd1498Szrj case TRUTH_OR_EXPR:
714738fd1498Szrj case WIDEN_MULT_EXPR:
714838fd1498Szrj case VEC_WIDEN_MULT_HI_EXPR:
714938fd1498Szrj case VEC_WIDEN_MULT_LO_EXPR:
715038fd1498Szrj case VEC_WIDEN_MULT_EVEN_EXPR:
715138fd1498Szrj case VEC_WIDEN_MULT_ODD_EXPR:
715238fd1498Szrj return true;
715338fd1498Szrj
715438fd1498Szrj default:
715538fd1498Szrj break;
715638fd1498Szrj }
715738fd1498Szrj return false;
715838fd1498Szrj }
715938fd1498Szrj
716038fd1498Szrj /* Return true if CODE represents a ternary tree code for which the
716138fd1498Szrj first two operands are commutative. Otherwise return false. */
716238fd1498Szrj bool
commutative_ternary_tree_code(enum tree_code code)716338fd1498Szrj commutative_ternary_tree_code (enum tree_code code)
716438fd1498Szrj {
716538fd1498Szrj switch (code)
716638fd1498Szrj {
716738fd1498Szrj case WIDEN_MULT_PLUS_EXPR:
716838fd1498Szrj case WIDEN_MULT_MINUS_EXPR:
716938fd1498Szrj case DOT_PROD_EXPR:
717038fd1498Szrj case FMA_EXPR:
717138fd1498Szrj return true;
717238fd1498Szrj
717338fd1498Szrj default:
717438fd1498Szrj break;
717538fd1498Szrj }
717638fd1498Szrj return false;
717738fd1498Szrj }
717838fd1498Szrj
717938fd1498Szrj /* Returns true if CODE can overflow. */
718038fd1498Szrj
718138fd1498Szrj bool
operation_can_overflow(enum tree_code code)718238fd1498Szrj operation_can_overflow (enum tree_code code)
718338fd1498Szrj {
718438fd1498Szrj switch (code)
718538fd1498Szrj {
718638fd1498Szrj case PLUS_EXPR:
718738fd1498Szrj case MINUS_EXPR:
718838fd1498Szrj case MULT_EXPR:
718938fd1498Szrj case LSHIFT_EXPR:
719038fd1498Szrj /* Can overflow in various ways. */
719138fd1498Szrj return true;
719238fd1498Szrj case TRUNC_DIV_EXPR:
719338fd1498Szrj case EXACT_DIV_EXPR:
719438fd1498Szrj case FLOOR_DIV_EXPR:
719538fd1498Szrj case CEIL_DIV_EXPR:
719638fd1498Szrj /* For INT_MIN / -1. */
719738fd1498Szrj return true;
719838fd1498Szrj case NEGATE_EXPR:
719938fd1498Szrj case ABS_EXPR:
720038fd1498Szrj /* For -INT_MIN. */
720138fd1498Szrj return true;
720238fd1498Szrj default:
720338fd1498Szrj /* These operators cannot overflow. */
720438fd1498Szrj return false;
720538fd1498Szrj }
720638fd1498Szrj }
720738fd1498Szrj
720838fd1498Szrj /* Returns true if CODE operating on operands of type TYPE doesn't overflow, or
720938fd1498Szrj ftrapv doesn't generate trapping insns for CODE. */
721038fd1498Szrj
721138fd1498Szrj bool
operation_no_trapping_overflow(tree type,enum tree_code code)721238fd1498Szrj operation_no_trapping_overflow (tree type, enum tree_code code)
721338fd1498Szrj {
721438fd1498Szrj gcc_checking_assert (ANY_INTEGRAL_TYPE_P (type));
721538fd1498Szrj
721638fd1498Szrj /* We don't generate instructions that trap on overflow for complex or vector
721738fd1498Szrj types. */
721838fd1498Szrj if (!INTEGRAL_TYPE_P (type))
721938fd1498Szrj return true;
722038fd1498Szrj
722138fd1498Szrj if (!TYPE_OVERFLOW_TRAPS (type))
722238fd1498Szrj return true;
722338fd1498Szrj
722438fd1498Szrj switch (code)
722538fd1498Szrj {
722638fd1498Szrj case PLUS_EXPR:
722738fd1498Szrj case MINUS_EXPR:
722838fd1498Szrj case MULT_EXPR:
722938fd1498Szrj case NEGATE_EXPR:
723038fd1498Szrj case ABS_EXPR:
723138fd1498Szrj /* These operators can overflow, and -ftrapv generates trapping code for
723238fd1498Szrj these. */
723338fd1498Szrj return false;
723438fd1498Szrj case TRUNC_DIV_EXPR:
723538fd1498Szrj case EXACT_DIV_EXPR:
723638fd1498Szrj case FLOOR_DIV_EXPR:
723738fd1498Szrj case CEIL_DIV_EXPR:
723838fd1498Szrj case LSHIFT_EXPR:
723938fd1498Szrj /* These operators can overflow, but -ftrapv does not generate trapping
724038fd1498Szrj code for these. */
724138fd1498Szrj return true;
724238fd1498Szrj default:
724338fd1498Szrj /* These operators cannot overflow. */
724438fd1498Szrj return true;
724538fd1498Szrj }
724638fd1498Szrj }
724738fd1498Szrj
724838fd1498Szrj namespace inchash
724938fd1498Szrj {
725038fd1498Szrj
725138fd1498Szrj /* Generate a hash value for an expression. This can be used iteratively
725238fd1498Szrj by passing a previous result as the HSTATE argument.
725338fd1498Szrj
725438fd1498Szrj This function is intended to produce the same hash for expressions which
725538fd1498Szrj would compare equal using operand_equal_p. */
725638fd1498Szrj void
add_expr(const_tree t,inchash::hash & hstate,unsigned int flags)725738fd1498Szrj add_expr (const_tree t, inchash::hash &hstate, unsigned int flags)
725838fd1498Szrj {
725938fd1498Szrj int i;
726038fd1498Szrj enum tree_code code;
726138fd1498Szrj enum tree_code_class tclass;
726238fd1498Szrj
726338fd1498Szrj if (t == NULL_TREE || t == error_mark_node)
726438fd1498Szrj {
726538fd1498Szrj hstate.merge_hash (0);
726638fd1498Szrj return;
726738fd1498Szrj }
726838fd1498Szrj
726938fd1498Szrj if (!(flags & OEP_ADDRESS_OF))
727038fd1498Szrj STRIP_NOPS (t);
727138fd1498Szrj
727238fd1498Szrj code = TREE_CODE (t);
727338fd1498Szrj
727438fd1498Szrj switch (code)
727538fd1498Szrj {
727638fd1498Szrj /* Alas, constants aren't shared, so we can't rely on pointer
727738fd1498Szrj identity. */
727838fd1498Szrj case VOID_CST:
727938fd1498Szrj hstate.merge_hash (0);
728038fd1498Szrj return;
728138fd1498Szrj case INTEGER_CST:
728238fd1498Szrj gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
728338fd1498Szrj for (i = 0; i < TREE_INT_CST_EXT_NUNITS (t); i++)
728438fd1498Szrj hstate.add_hwi (TREE_INT_CST_ELT (t, i));
728538fd1498Szrj return;
728638fd1498Szrj case REAL_CST:
728738fd1498Szrj {
728838fd1498Szrj unsigned int val2;
728938fd1498Szrj if (!HONOR_SIGNED_ZEROS (t) && real_zerop (t))
729038fd1498Szrj val2 = rvc_zero;
729138fd1498Szrj else
729238fd1498Szrj val2 = real_hash (TREE_REAL_CST_PTR (t));
729338fd1498Szrj hstate.merge_hash (val2);
729438fd1498Szrj return;
729538fd1498Szrj }
729638fd1498Szrj case FIXED_CST:
729738fd1498Szrj {
729838fd1498Szrj unsigned int val2 = fixed_hash (TREE_FIXED_CST_PTR (t));
729938fd1498Szrj hstate.merge_hash (val2);
730038fd1498Szrj return;
730138fd1498Szrj }
730238fd1498Szrj case STRING_CST:
730338fd1498Szrj hstate.add ((const void *) TREE_STRING_POINTER (t),
730438fd1498Szrj TREE_STRING_LENGTH (t));
730538fd1498Szrj return;
730638fd1498Szrj case COMPLEX_CST:
730738fd1498Szrj inchash::add_expr (TREE_REALPART (t), hstate, flags);
730838fd1498Szrj inchash::add_expr (TREE_IMAGPART (t), hstate, flags);
730938fd1498Szrj return;
731038fd1498Szrj case VECTOR_CST:
731138fd1498Szrj {
731238fd1498Szrj hstate.add_int (VECTOR_CST_NPATTERNS (t));
731338fd1498Szrj hstate.add_int (VECTOR_CST_NELTS_PER_PATTERN (t));
731438fd1498Szrj unsigned int count = vector_cst_encoded_nelts (t);
731538fd1498Szrj for (unsigned int i = 0; i < count; ++i)
731638fd1498Szrj inchash::add_expr (VECTOR_CST_ENCODED_ELT (t, i), hstate, flags);
731738fd1498Szrj return;
731838fd1498Szrj }
731938fd1498Szrj case SSA_NAME:
732038fd1498Szrj /* We can just compare by pointer. */
732138fd1498Szrj hstate.add_hwi (SSA_NAME_VERSION (t));
732238fd1498Szrj return;
732338fd1498Szrj case PLACEHOLDER_EXPR:
732438fd1498Szrj /* The node itself doesn't matter. */
732538fd1498Szrj return;
732638fd1498Szrj case BLOCK:
732738fd1498Szrj case OMP_CLAUSE:
732838fd1498Szrj /* Ignore. */
732938fd1498Szrj return;
733038fd1498Szrj case TREE_LIST:
733138fd1498Szrj /* A list of expressions, for a CALL_EXPR or as the elements of a
733238fd1498Szrj VECTOR_CST. */
733338fd1498Szrj for (; t; t = TREE_CHAIN (t))
733438fd1498Szrj inchash::add_expr (TREE_VALUE (t), hstate, flags);
733538fd1498Szrj return;
733638fd1498Szrj case CONSTRUCTOR:
733738fd1498Szrj {
733838fd1498Szrj unsigned HOST_WIDE_INT idx;
733938fd1498Szrj tree field, value;
734038fd1498Szrj flags &= ~OEP_ADDRESS_OF;
734138fd1498Szrj FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), idx, field, value)
734238fd1498Szrj {
734338fd1498Szrj inchash::add_expr (field, hstate, flags);
734438fd1498Szrj inchash::add_expr (value, hstate, flags);
734538fd1498Szrj }
734638fd1498Szrj return;
734738fd1498Szrj }
734838fd1498Szrj case STATEMENT_LIST:
734938fd1498Szrj {
735038fd1498Szrj tree_stmt_iterator i;
735138fd1498Szrj for (i = tsi_start (CONST_CAST_TREE (t));
735238fd1498Szrj !tsi_end_p (i); tsi_next (&i))
735338fd1498Szrj inchash::add_expr (tsi_stmt (i), hstate, flags);
735438fd1498Szrj return;
735538fd1498Szrj }
735638fd1498Szrj case TREE_VEC:
735738fd1498Szrj for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
735838fd1498Szrj inchash::add_expr (TREE_VEC_ELT (t, i), hstate, flags);
735938fd1498Szrj return;
7360*58e805e6Szrj case IDENTIFIER_NODE:
7361*58e805e6Szrj hstate.add_object (IDENTIFIER_HASH_VALUE (t));
7362*58e805e6Szrj return;
736338fd1498Szrj case FUNCTION_DECL:
736438fd1498Szrj /* When referring to a built-in FUNCTION_DECL, use the __builtin__ form.
736538fd1498Szrj Otherwise nodes that compare equal according to operand_equal_p might
736638fd1498Szrj get different hash codes. However, don't do this for machine specific
736738fd1498Szrj or front end builtins, since the function code is overloaded in those
736838fd1498Szrj cases. */
736938fd1498Szrj if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
737038fd1498Szrj && builtin_decl_explicit_p (DECL_FUNCTION_CODE (t)))
737138fd1498Szrj {
737238fd1498Szrj t = builtin_decl_explicit (DECL_FUNCTION_CODE (t));
737338fd1498Szrj code = TREE_CODE (t);
737438fd1498Szrj }
737538fd1498Szrj /* FALL THROUGH */
737638fd1498Szrj default:
737738fd1498Szrj if (POLY_INT_CST_P (t))
737838fd1498Szrj {
737938fd1498Szrj for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
738038fd1498Szrj hstate.add_wide_int (wi::to_wide (POLY_INT_CST_COEFF (t, i)));
738138fd1498Szrj return;
738238fd1498Szrj }
738338fd1498Szrj tclass = TREE_CODE_CLASS (code);
738438fd1498Szrj
738538fd1498Szrj if (tclass == tcc_declaration)
738638fd1498Szrj {
738738fd1498Szrj /* DECL's have a unique ID */
738838fd1498Szrj hstate.add_hwi (DECL_UID (t));
738938fd1498Szrj }
739038fd1498Szrj else if (tclass == tcc_comparison && !commutative_tree_code (code))
739138fd1498Szrj {
739238fd1498Szrj /* For comparisons that can be swapped, use the lower
739338fd1498Szrj tree code. */
739438fd1498Szrj enum tree_code ccode = swap_tree_comparison (code);
739538fd1498Szrj if (code < ccode)
739638fd1498Szrj ccode = code;
739738fd1498Szrj hstate.add_object (ccode);
739838fd1498Szrj inchash::add_expr (TREE_OPERAND (t, ccode != code), hstate, flags);
739938fd1498Szrj inchash::add_expr (TREE_OPERAND (t, ccode == code), hstate, flags);
740038fd1498Szrj }
740138fd1498Szrj else if (CONVERT_EXPR_CODE_P (code))
740238fd1498Szrj {
740338fd1498Szrj /* NOP_EXPR and CONVERT_EXPR are considered equal by
740438fd1498Szrj operand_equal_p. */
740538fd1498Szrj enum tree_code ccode = NOP_EXPR;
740638fd1498Szrj hstate.add_object (ccode);
740738fd1498Szrj
740838fd1498Szrj /* Don't hash the type, that can lead to having nodes which
740938fd1498Szrj compare equal according to operand_equal_p, but which
741038fd1498Szrj have different hash codes. Make sure to include signedness
741138fd1498Szrj in the hash computation. */
741238fd1498Szrj hstate.add_int (TYPE_UNSIGNED (TREE_TYPE (t)));
741338fd1498Szrj inchash::add_expr (TREE_OPERAND (t, 0), hstate, flags);
741438fd1498Szrj }
741538fd1498Szrj /* For OEP_ADDRESS_OF, hash MEM_EXPR[&decl, 0] the same as decl. */
741638fd1498Szrj else if (code == MEM_REF
741738fd1498Szrj && (flags & OEP_ADDRESS_OF) != 0
741838fd1498Szrj && TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
741938fd1498Szrj && DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0))
742038fd1498Szrj && integer_zerop (TREE_OPERAND (t, 1)))
742138fd1498Szrj inchash::add_expr (TREE_OPERAND (TREE_OPERAND (t, 0), 0),
742238fd1498Szrj hstate, flags);
742338fd1498Szrj /* Don't ICE on FE specific trees, or their arguments etc.
742438fd1498Szrj during operand_equal_p hash verification. */
742538fd1498Szrj else if (!IS_EXPR_CODE_CLASS (tclass))
742638fd1498Szrj gcc_assert (flags & OEP_HASH_CHECK);
742738fd1498Szrj else
742838fd1498Szrj {
742938fd1498Szrj unsigned int sflags = flags;
743038fd1498Szrj
743138fd1498Szrj hstate.add_object (code);
743238fd1498Szrj
743338fd1498Szrj switch (code)
743438fd1498Szrj {
743538fd1498Szrj case ADDR_EXPR:
743638fd1498Szrj gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
743738fd1498Szrj flags |= OEP_ADDRESS_OF;
743838fd1498Szrj sflags = flags;
743938fd1498Szrj break;
744038fd1498Szrj
744138fd1498Szrj case INDIRECT_REF:
744238fd1498Szrj case MEM_REF:
744338fd1498Szrj case TARGET_MEM_REF:
744438fd1498Szrj flags &= ~OEP_ADDRESS_OF;
744538fd1498Szrj sflags = flags;
744638fd1498Szrj break;
744738fd1498Szrj
744838fd1498Szrj case ARRAY_REF:
744938fd1498Szrj case ARRAY_RANGE_REF:
745038fd1498Szrj case COMPONENT_REF:
745138fd1498Szrj case BIT_FIELD_REF:
745238fd1498Szrj sflags &= ~OEP_ADDRESS_OF;
745338fd1498Szrj break;
745438fd1498Szrj
745538fd1498Szrj case COND_EXPR:
745638fd1498Szrj flags &= ~OEP_ADDRESS_OF;
745738fd1498Szrj break;
745838fd1498Szrj
745938fd1498Szrj case FMA_EXPR:
746038fd1498Szrj case WIDEN_MULT_PLUS_EXPR:
746138fd1498Szrj case WIDEN_MULT_MINUS_EXPR:
746238fd1498Szrj {
746338fd1498Szrj /* The multiplication operands are commutative. */
746438fd1498Szrj inchash::hash one, two;
746538fd1498Szrj inchash::add_expr (TREE_OPERAND (t, 0), one, flags);
746638fd1498Szrj inchash::add_expr (TREE_OPERAND (t, 1), two, flags);
746738fd1498Szrj hstate.add_commutative (one, two);
746838fd1498Szrj inchash::add_expr (TREE_OPERAND (t, 2), two, flags);
746938fd1498Szrj return;
747038fd1498Szrj }
747138fd1498Szrj
747238fd1498Szrj case CALL_EXPR:
747338fd1498Szrj if (CALL_EXPR_FN (t) == NULL_TREE)
747438fd1498Szrj hstate.add_int (CALL_EXPR_IFN (t));
747538fd1498Szrj break;
747638fd1498Szrj
747738fd1498Szrj case TARGET_EXPR:
747838fd1498Szrj /* For TARGET_EXPR, just hash on the TARGET_EXPR_SLOT.
747938fd1498Szrj Usually different TARGET_EXPRs just should use
748038fd1498Szrj different temporaries in their slots. */
748138fd1498Szrj inchash::add_expr (TARGET_EXPR_SLOT (t), hstate, flags);
748238fd1498Szrj return;
748338fd1498Szrj
748438fd1498Szrj default:
748538fd1498Szrj break;
748638fd1498Szrj }
748738fd1498Szrj
748838fd1498Szrj /* Don't hash the type, that can lead to having nodes which
748938fd1498Szrj compare equal according to operand_equal_p, but which
749038fd1498Szrj have different hash codes. */
749138fd1498Szrj if (code == NON_LVALUE_EXPR)
749238fd1498Szrj {
749338fd1498Szrj /* Make sure to include signness in the hash computation. */
749438fd1498Szrj hstate.add_int (TYPE_UNSIGNED (TREE_TYPE (t)));
749538fd1498Szrj inchash::add_expr (TREE_OPERAND (t, 0), hstate, flags);
749638fd1498Szrj }
749738fd1498Szrj
749838fd1498Szrj else if (commutative_tree_code (code))
749938fd1498Szrj {
750038fd1498Szrj /* It's a commutative expression. We want to hash it the same
750138fd1498Szrj however it appears. We do this by first hashing both operands
750238fd1498Szrj and then rehashing based on the order of their independent
750338fd1498Szrj hashes. */
750438fd1498Szrj inchash::hash one, two;
750538fd1498Szrj inchash::add_expr (TREE_OPERAND (t, 0), one, flags);
750638fd1498Szrj inchash::add_expr (TREE_OPERAND (t, 1), two, flags);
750738fd1498Szrj hstate.add_commutative (one, two);
750838fd1498Szrj }
750938fd1498Szrj else
751038fd1498Szrj for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i)
751138fd1498Szrj inchash::add_expr (TREE_OPERAND (t, i), hstate,
751238fd1498Szrj i == 0 ? flags : sflags);
751338fd1498Szrj }
751438fd1498Szrj return;
751538fd1498Szrj }
751638fd1498Szrj }
751738fd1498Szrj
751838fd1498Szrj }
751938fd1498Szrj
752038fd1498Szrj /* Constructors for pointer, array and function types.
752138fd1498Szrj (RECORD_TYPE, UNION_TYPE and ENUMERAL_TYPE nodes are
752238fd1498Szrj constructed by language-dependent code, not here.) */
752338fd1498Szrj
752438fd1498Szrj /* Construct, lay out and return the type of pointers to TO_TYPE with
752538fd1498Szrj mode MODE. If CAN_ALIAS_ALL is TRUE, indicate this type can
752638fd1498Szrj reference all of memory. If such a type has already been
752738fd1498Szrj constructed, reuse it. */
752838fd1498Szrj
752938fd1498Szrj tree
build_pointer_type_for_mode(tree to_type,machine_mode mode,bool can_alias_all)753038fd1498Szrj build_pointer_type_for_mode (tree to_type, machine_mode mode,
753138fd1498Szrj bool can_alias_all)
753238fd1498Szrj {
753338fd1498Szrj tree t;
753438fd1498Szrj bool could_alias = can_alias_all;
753538fd1498Szrj
753638fd1498Szrj if (to_type == error_mark_node)
753738fd1498Szrj return error_mark_node;
753838fd1498Szrj
753938fd1498Szrj /* If the pointed-to type has the may_alias attribute set, force
754038fd1498Szrj a TYPE_REF_CAN_ALIAS_ALL pointer to be generated. */
754138fd1498Szrj if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type)))
754238fd1498Szrj can_alias_all = true;
754338fd1498Szrj
754438fd1498Szrj /* In some cases, languages will have things that aren't a POINTER_TYPE
754538fd1498Szrj (such as a RECORD_TYPE for fat pointers in Ada) as TYPE_POINTER_TO.
754638fd1498Szrj In that case, return that type without regard to the rest of our
754738fd1498Szrj operands.
754838fd1498Szrj
754938fd1498Szrj ??? This is a kludge, but consistent with the way this function has
755038fd1498Szrj always operated and there doesn't seem to be a good way to avoid this
755138fd1498Szrj at the moment. */
755238fd1498Szrj if (TYPE_POINTER_TO (to_type) != 0
755338fd1498Szrj && TREE_CODE (TYPE_POINTER_TO (to_type)) != POINTER_TYPE)
755438fd1498Szrj return TYPE_POINTER_TO (to_type);
755538fd1498Szrj
755638fd1498Szrj /* First, if we already have a type for pointers to TO_TYPE and it's
755738fd1498Szrj the proper mode, use it. */
755838fd1498Szrj for (t = TYPE_POINTER_TO (to_type); t; t = TYPE_NEXT_PTR_TO (t))
755938fd1498Szrj if (TYPE_MODE (t) == mode && TYPE_REF_CAN_ALIAS_ALL (t) == can_alias_all)
756038fd1498Szrj return t;
756138fd1498Szrj
756238fd1498Szrj t = make_node (POINTER_TYPE);
756338fd1498Szrj
756438fd1498Szrj TREE_TYPE (t) = to_type;
756538fd1498Szrj SET_TYPE_MODE (t, mode);
756638fd1498Szrj TYPE_REF_CAN_ALIAS_ALL (t) = can_alias_all;
756738fd1498Szrj TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (to_type);
756838fd1498Szrj TYPE_POINTER_TO (to_type) = t;
756938fd1498Szrj
757038fd1498Szrj /* During LTO we do not set TYPE_CANONICAL of pointers and references. */
757138fd1498Szrj if (TYPE_STRUCTURAL_EQUALITY_P (to_type) || in_lto_p)
757238fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (t);
757338fd1498Szrj else if (TYPE_CANONICAL (to_type) != to_type || could_alias)
757438fd1498Szrj TYPE_CANONICAL (t)
757538fd1498Szrj = build_pointer_type_for_mode (TYPE_CANONICAL (to_type),
757638fd1498Szrj mode, false);
757738fd1498Szrj
757838fd1498Szrj /* Lay out the type. This function has many callers that are concerned
757938fd1498Szrj with expression-construction, and this simplifies them all. */
758038fd1498Szrj layout_type (t);
758138fd1498Szrj
758238fd1498Szrj return t;
758338fd1498Szrj }
758438fd1498Szrj
758538fd1498Szrj /* By default build pointers in ptr_mode. */
758638fd1498Szrj
758738fd1498Szrj tree
build_pointer_type(tree to_type)758838fd1498Szrj build_pointer_type (tree to_type)
758938fd1498Szrj {
759038fd1498Szrj addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
759138fd1498Szrj : TYPE_ADDR_SPACE (to_type);
759238fd1498Szrj machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
759338fd1498Szrj return build_pointer_type_for_mode (to_type, pointer_mode, false);
759438fd1498Szrj }
759538fd1498Szrj
759638fd1498Szrj /* Same as build_pointer_type_for_mode, but for REFERENCE_TYPE. */
759738fd1498Szrj
759838fd1498Szrj tree
build_reference_type_for_mode(tree to_type,machine_mode mode,bool can_alias_all)759938fd1498Szrj build_reference_type_for_mode (tree to_type, machine_mode mode,
760038fd1498Szrj bool can_alias_all)
760138fd1498Szrj {
760238fd1498Szrj tree t;
760338fd1498Szrj bool could_alias = can_alias_all;
760438fd1498Szrj
760538fd1498Szrj if (to_type == error_mark_node)
760638fd1498Szrj return error_mark_node;
760738fd1498Szrj
760838fd1498Szrj /* If the pointed-to type has the may_alias attribute set, force
760938fd1498Szrj a TYPE_REF_CAN_ALIAS_ALL pointer to be generated. */
761038fd1498Szrj if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type)))
761138fd1498Szrj can_alias_all = true;
761238fd1498Szrj
761338fd1498Szrj /* In some cases, languages will have things that aren't a REFERENCE_TYPE
761438fd1498Szrj (such as a RECORD_TYPE for fat pointers in Ada) as TYPE_REFERENCE_TO.
761538fd1498Szrj In that case, return that type without regard to the rest of our
761638fd1498Szrj operands.
761738fd1498Szrj
761838fd1498Szrj ??? This is a kludge, but consistent with the way this function has
761938fd1498Szrj always operated and there doesn't seem to be a good way to avoid this
762038fd1498Szrj at the moment. */
762138fd1498Szrj if (TYPE_REFERENCE_TO (to_type) != 0
762238fd1498Szrj && TREE_CODE (TYPE_REFERENCE_TO (to_type)) != REFERENCE_TYPE)
762338fd1498Szrj return TYPE_REFERENCE_TO (to_type);
762438fd1498Szrj
762538fd1498Szrj /* First, if we already have a type for pointers to TO_TYPE and it's
762638fd1498Szrj the proper mode, use it. */
762738fd1498Szrj for (t = TYPE_REFERENCE_TO (to_type); t; t = TYPE_NEXT_REF_TO (t))
762838fd1498Szrj if (TYPE_MODE (t) == mode && TYPE_REF_CAN_ALIAS_ALL (t) == can_alias_all)
762938fd1498Szrj return t;
763038fd1498Szrj
763138fd1498Szrj t = make_node (REFERENCE_TYPE);
763238fd1498Szrj
763338fd1498Szrj TREE_TYPE (t) = to_type;
763438fd1498Szrj SET_TYPE_MODE (t, mode);
763538fd1498Szrj TYPE_REF_CAN_ALIAS_ALL (t) = can_alias_all;
763638fd1498Szrj TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (to_type);
763738fd1498Szrj TYPE_REFERENCE_TO (to_type) = t;
763838fd1498Szrj
763938fd1498Szrj /* During LTO we do not set TYPE_CANONICAL of pointers and references. */
764038fd1498Szrj if (TYPE_STRUCTURAL_EQUALITY_P (to_type) || in_lto_p)
764138fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (t);
764238fd1498Szrj else if (TYPE_CANONICAL (to_type) != to_type || could_alias)
764338fd1498Szrj TYPE_CANONICAL (t)
764438fd1498Szrj = build_reference_type_for_mode (TYPE_CANONICAL (to_type),
764538fd1498Szrj mode, false);
764638fd1498Szrj
764738fd1498Szrj layout_type (t);
764838fd1498Szrj
764938fd1498Szrj return t;
765038fd1498Szrj }
765138fd1498Szrj
765238fd1498Szrj
765338fd1498Szrj /* Build the node for the type of references-to-TO_TYPE by default
765438fd1498Szrj in ptr_mode. */
765538fd1498Szrj
765638fd1498Szrj tree
build_reference_type(tree to_type)765738fd1498Szrj build_reference_type (tree to_type)
765838fd1498Szrj {
765938fd1498Szrj addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
766038fd1498Szrj : TYPE_ADDR_SPACE (to_type);
766138fd1498Szrj machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
766238fd1498Szrj return build_reference_type_for_mode (to_type, pointer_mode, false);
766338fd1498Szrj }
766438fd1498Szrj
766538fd1498Szrj #define MAX_INT_CACHED_PREC \
766638fd1498Szrj (HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
766738fd1498Szrj static GTY(()) tree nonstandard_integer_type_cache[2 * MAX_INT_CACHED_PREC + 2];
766838fd1498Szrj
766938fd1498Szrj /* Builds a signed or unsigned integer type of precision PRECISION.
767038fd1498Szrj Used for C bitfields whose precision does not match that of
767138fd1498Szrj built-in target types. */
767238fd1498Szrj tree
build_nonstandard_integer_type(unsigned HOST_WIDE_INT precision,int unsignedp)767338fd1498Szrj build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision,
767438fd1498Szrj int unsignedp)
767538fd1498Szrj {
767638fd1498Szrj tree itype, ret;
767738fd1498Szrj
767838fd1498Szrj if (unsignedp)
767938fd1498Szrj unsignedp = MAX_INT_CACHED_PREC + 1;
768038fd1498Szrj
768138fd1498Szrj if (precision <= MAX_INT_CACHED_PREC)
768238fd1498Szrj {
768338fd1498Szrj itype = nonstandard_integer_type_cache[precision + unsignedp];
768438fd1498Szrj if (itype)
768538fd1498Szrj return itype;
768638fd1498Szrj }
768738fd1498Szrj
768838fd1498Szrj itype = make_node (INTEGER_TYPE);
768938fd1498Szrj TYPE_PRECISION (itype) = precision;
769038fd1498Szrj
769138fd1498Szrj if (unsignedp)
769238fd1498Szrj fixup_unsigned_type (itype);
769338fd1498Szrj else
769438fd1498Szrj fixup_signed_type (itype);
769538fd1498Szrj
769638fd1498Szrj ret = itype;
769738fd1498Szrj
769838fd1498Szrj inchash::hash hstate;
769938fd1498Szrj inchash::add_expr (TYPE_MAX_VALUE (itype), hstate);
770038fd1498Szrj ret = type_hash_canon (hstate.end (), itype);
770138fd1498Szrj if (precision <= MAX_INT_CACHED_PREC)
770238fd1498Szrj nonstandard_integer_type_cache[precision + unsignedp] = ret;
770338fd1498Szrj
770438fd1498Szrj return ret;
770538fd1498Szrj }
770638fd1498Szrj
770738fd1498Szrj #define MAX_BOOL_CACHED_PREC \
770838fd1498Szrj (HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
770938fd1498Szrj static GTY(()) tree nonstandard_boolean_type_cache[MAX_BOOL_CACHED_PREC + 1];
771038fd1498Szrj
771138fd1498Szrj /* Builds a boolean type of precision PRECISION.
771238fd1498Szrj Used for boolean vectors to choose proper vector element size. */
771338fd1498Szrj tree
build_nonstandard_boolean_type(unsigned HOST_WIDE_INT precision)771438fd1498Szrj build_nonstandard_boolean_type (unsigned HOST_WIDE_INT precision)
771538fd1498Szrj {
771638fd1498Szrj tree type;
771738fd1498Szrj
771838fd1498Szrj if (precision <= MAX_BOOL_CACHED_PREC)
771938fd1498Szrj {
772038fd1498Szrj type = nonstandard_boolean_type_cache[precision];
772138fd1498Szrj if (type)
772238fd1498Szrj return type;
772338fd1498Szrj }
772438fd1498Szrj
772538fd1498Szrj type = make_node (BOOLEAN_TYPE);
772638fd1498Szrj TYPE_PRECISION (type) = precision;
772738fd1498Szrj fixup_signed_type (type);
772838fd1498Szrj
772938fd1498Szrj if (precision <= MAX_INT_CACHED_PREC)
773038fd1498Szrj nonstandard_boolean_type_cache[precision] = type;
773138fd1498Szrj
773238fd1498Szrj return type;
773338fd1498Szrj }
773438fd1498Szrj
773538fd1498Szrj /* Create a range of some discrete type TYPE (an INTEGER_TYPE, ENUMERAL_TYPE
773638fd1498Szrj or BOOLEAN_TYPE) with low bound LOWVAL and high bound HIGHVAL. If SHARED
773738fd1498Szrj is true, reuse such a type that has already been constructed. */
773838fd1498Szrj
773938fd1498Szrj static tree
build_range_type_1(tree type,tree lowval,tree highval,bool shared)774038fd1498Szrj build_range_type_1 (tree type, tree lowval, tree highval, bool shared)
774138fd1498Szrj {
774238fd1498Szrj tree itype = make_node (INTEGER_TYPE);
774338fd1498Szrj
774438fd1498Szrj TREE_TYPE (itype) = type;
774538fd1498Szrj
774638fd1498Szrj TYPE_MIN_VALUE (itype) = fold_convert (type, lowval);
774738fd1498Szrj TYPE_MAX_VALUE (itype) = highval ? fold_convert (type, highval) : NULL;
774838fd1498Szrj
774938fd1498Szrj TYPE_PRECISION (itype) = TYPE_PRECISION (type);
775038fd1498Szrj SET_TYPE_MODE (itype, TYPE_MODE (type));
775138fd1498Szrj TYPE_SIZE (itype) = TYPE_SIZE (type);
775238fd1498Szrj TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (type);
775338fd1498Szrj SET_TYPE_ALIGN (itype, TYPE_ALIGN (type));
775438fd1498Szrj TYPE_USER_ALIGN (itype) = TYPE_USER_ALIGN (type);
775538fd1498Szrj SET_TYPE_WARN_IF_NOT_ALIGN (itype, TYPE_WARN_IF_NOT_ALIGN (type));
775638fd1498Szrj
775738fd1498Szrj if (!shared)
775838fd1498Szrj return itype;
775938fd1498Szrj
776038fd1498Szrj if ((TYPE_MIN_VALUE (itype)
776138fd1498Szrj && TREE_CODE (TYPE_MIN_VALUE (itype)) != INTEGER_CST)
776238fd1498Szrj || (TYPE_MAX_VALUE (itype)
776338fd1498Szrj && TREE_CODE (TYPE_MAX_VALUE (itype)) != INTEGER_CST))
776438fd1498Szrj {
776538fd1498Szrj /* Since we cannot reliably merge this type, we need to compare it using
776638fd1498Szrj structural equality checks. */
776738fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (itype);
776838fd1498Szrj return itype;
776938fd1498Szrj }
777038fd1498Szrj
777138fd1498Szrj hashval_t hash = type_hash_canon_hash (itype);
777238fd1498Szrj itype = type_hash_canon (hash, itype);
777338fd1498Szrj
777438fd1498Szrj return itype;
777538fd1498Szrj }
777638fd1498Szrj
777738fd1498Szrj /* Wrapper around build_range_type_1 with SHARED set to true. */
777838fd1498Szrj
777938fd1498Szrj tree
build_range_type(tree type,tree lowval,tree highval)778038fd1498Szrj build_range_type (tree type, tree lowval, tree highval)
778138fd1498Szrj {
778238fd1498Szrj return build_range_type_1 (type, lowval, highval, true);
778338fd1498Szrj }
778438fd1498Szrj
778538fd1498Szrj /* Wrapper around build_range_type_1 with SHARED set to false. */
778638fd1498Szrj
778738fd1498Szrj tree
build_nonshared_range_type(tree type,tree lowval,tree highval)778838fd1498Szrj build_nonshared_range_type (tree type, tree lowval, tree highval)
778938fd1498Szrj {
779038fd1498Szrj return build_range_type_1 (type, lowval, highval, false);
779138fd1498Szrj }
779238fd1498Szrj
779338fd1498Szrj /* Create a type of integers to be the TYPE_DOMAIN of an ARRAY_TYPE.
779438fd1498Szrj MAXVAL should be the maximum value in the domain
779538fd1498Szrj (one less than the length of the array).
779638fd1498Szrj
779738fd1498Szrj The maximum value that MAXVAL can have is INT_MAX for a HOST_WIDE_INT.
779838fd1498Szrj We don't enforce this limit, that is up to caller (e.g. language front end).
779938fd1498Szrj The limit exists because the result is a signed type and we don't handle
780038fd1498Szrj sizes that use more than one HOST_WIDE_INT. */
780138fd1498Szrj
780238fd1498Szrj tree
build_index_type(tree maxval)780338fd1498Szrj build_index_type (tree maxval)
780438fd1498Szrj {
780538fd1498Szrj return build_range_type (sizetype, size_zero_node, maxval);
780638fd1498Szrj }
780738fd1498Szrj
780838fd1498Szrj /* Return true if the debug information for TYPE, a subtype, should be emitted
780938fd1498Szrj as a subrange type. If so, set LOWVAL to the low bound and HIGHVAL to the
781038fd1498Szrj high bound, respectively. Sometimes doing so unnecessarily obfuscates the
781138fd1498Szrj debug info and doesn't reflect the source code. */
781238fd1498Szrj
781338fd1498Szrj bool
subrange_type_for_debug_p(const_tree type,tree * lowval,tree * highval)781438fd1498Szrj subrange_type_for_debug_p (const_tree type, tree *lowval, tree *highval)
781538fd1498Szrj {
781638fd1498Szrj tree base_type = TREE_TYPE (type), low, high;
781738fd1498Szrj
781838fd1498Szrj /* Subrange types have a base type which is an integral type. */
781938fd1498Szrj if (!INTEGRAL_TYPE_P (base_type))
782038fd1498Szrj return false;
782138fd1498Szrj
782238fd1498Szrj /* Get the real bounds of the subtype. */
782338fd1498Szrj if (lang_hooks.types.get_subrange_bounds)
782438fd1498Szrj lang_hooks.types.get_subrange_bounds (type, &low, &high);
782538fd1498Szrj else
782638fd1498Szrj {
782738fd1498Szrj low = TYPE_MIN_VALUE (type);
782838fd1498Szrj high = TYPE_MAX_VALUE (type);
782938fd1498Szrj }
783038fd1498Szrj
783138fd1498Szrj /* If the type and its base type have the same representation and the same
783238fd1498Szrj name, then the type is not a subrange but a copy of the base type. */
783338fd1498Szrj if ((TREE_CODE (base_type) == INTEGER_TYPE
783438fd1498Szrj || TREE_CODE (base_type) == BOOLEAN_TYPE)
783538fd1498Szrj && int_size_in_bytes (type) == int_size_in_bytes (base_type)
783638fd1498Szrj && tree_int_cst_equal (low, TYPE_MIN_VALUE (base_type))
783738fd1498Szrj && tree_int_cst_equal (high, TYPE_MAX_VALUE (base_type))
783838fd1498Szrj && TYPE_IDENTIFIER (type) == TYPE_IDENTIFIER (base_type))
783938fd1498Szrj return false;
784038fd1498Szrj
784138fd1498Szrj if (lowval)
784238fd1498Szrj *lowval = low;
784338fd1498Szrj if (highval)
784438fd1498Szrj *highval = high;
784538fd1498Szrj return true;
784638fd1498Szrj }
784738fd1498Szrj
784838fd1498Szrj /* Construct, lay out and return the type of arrays of elements with ELT_TYPE
784938fd1498Szrj and number of elements specified by the range of values of INDEX_TYPE.
785038fd1498Szrj If TYPELESS_STORAGE is true, TYPE_TYPELESS_STORAGE flag is set on the type.
785138fd1498Szrj If SHARED is true, reuse such a type that has already been constructed. */
785238fd1498Szrj
785338fd1498Szrj static tree
build_array_type_1(tree elt_type,tree index_type,bool typeless_storage,bool shared)785438fd1498Szrj build_array_type_1 (tree elt_type, tree index_type, bool typeless_storage,
785538fd1498Szrj bool shared)
785638fd1498Szrj {
785738fd1498Szrj tree t;
785838fd1498Szrj
785938fd1498Szrj if (TREE_CODE (elt_type) == FUNCTION_TYPE)
786038fd1498Szrj {
786138fd1498Szrj error ("arrays of functions are not meaningful");
786238fd1498Szrj elt_type = integer_type_node;
786338fd1498Szrj }
786438fd1498Szrj
786538fd1498Szrj t = make_node (ARRAY_TYPE);
786638fd1498Szrj TREE_TYPE (t) = elt_type;
786738fd1498Szrj TYPE_DOMAIN (t) = index_type;
786838fd1498Szrj TYPE_ADDR_SPACE (t) = TYPE_ADDR_SPACE (elt_type);
786938fd1498Szrj TYPE_TYPELESS_STORAGE (t) = typeless_storage;
787038fd1498Szrj layout_type (t);
787138fd1498Szrj
787238fd1498Szrj /* If the element type is incomplete at this point we get marked for
787338fd1498Szrj structural equality. Do not record these types in the canonical
787438fd1498Szrj type hashtable. */
787538fd1498Szrj if (TYPE_STRUCTURAL_EQUALITY_P (t))
787638fd1498Szrj return t;
787738fd1498Szrj
787838fd1498Szrj if (shared)
787938fd1498Szrj {
788038fd1498Szrj hashval_t hash = type_hash_canon_hash (t);
788138fd1498Szrj t = type_hash_canon (hash, t);
788238fd1498Szrj }
788338fd1498Szrj
788438fd1498Szrj if (TYPE_CANONICAL (t) == t)
788538fd1498Szrj {
788638fd1498Szrj if (TYPE_STRUCTURAL_EQUALITY_P (elt_type)
788738fd1498Szrj || (index_type && TYPE_STRUCTURAL_EQUALITY_P (index_type))
788838fd1498Szrj || in_lto_p)
788938fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (t);
789038fd1498Szrj else if (TYPE_CANONICAL (elt_type) != elt_type
789138fd1498Szrj || (index_type && TYPE_CANONICAL (index_type) != index_type))
789238fd1498Szrj TYPE_CANONICAL (t)
789338fd1498Szrj = build_array_type_1 (TYPE_CANONICAL (elt_type),
789438fd1498Szrj index_type
789538fd1498Szrj ? TYPE_CANONICAL (index_type) : NULL_TREE,
789638fd1498Szrj typeless_storage, shared);
789738fd1498Szrj }
789838fd1498Szrj
789938fd1498Szrj return t;
790038fd1498Szrj }
790138fd1498Szrj
790238fd1498Szrj /* Wrapper around build_array_type_1 with SHARED set to true. */
790338fd1498Szrj
790438fd1498Szrj tree
build_array_type(tree elt_type,tree index_type,bool typeless_storage)790538fd1498Szrj build_array_type (tree elt_type, tree index_type, bool typeless_storage)
790638fd1498Szrj {
790738fd1498Szrj return build_array_type_1 (elt_type, index_type, typeless_storage, true);
790838fd1498Szrj }
790938fd1498Szrj
791038fd1498Szrj /* Wrapper around build_array_type_1 with SHARED set to false. */
791138fd1498Szrj
791238fd1498Szrj tree
build_nonshared_array_type(tree elt_type,tree index_type)791338fd1498Szrj build_nonshared_array_type (tree elt_type, tree index_type)
791438fd1498Szrj {
791538fd1498Szrj return build_array_type_1 (elt_type, index_type, false, false);
791638fd1498Szrj }
791738fd1498Szrj
791838fd1498Szrj /* Return a representation of ELT_TYPE[NELTS], using indices of type
791938fd1498Szrj sizetype. */
792038fd1498Szrj
792138fd1498Szrj tree
build_array_type_nelts(tree elt_type,poly_uint64 nelts)792238fd1498Szrj build_array_type_nelts (tree elt_type, poly_uint64 nelts)
792338fd1498Szrj {
792438fd1498Szrj return build_array_type (elt_type, build_index_type (size_int (nelts - 1)));
792538fd1498Szrj }
792638fd1498Szrj
792738fd1498Szrj /* Recursively examines the array elements of TYPE, until a non-array
792838fd1498Szrj element type is found. */
792938fd1498Szrj
793038fd1498Szrj tree
strip_array_types(tree type)793138fd1498Szrj strip_array_types (tree type)
793238fd1498Szrj {
793338fd1498Szrj while (TREE_CODE (type) == ARRAY_TYPE)
793438fd1498Szrj type = TREE_TYPE (type);
793538fd1498Szrj
793638fd1498Szrj return type;
793738fd1498Szrj }
793838fd1498Szrj
793938fd1498Szrj /* Computes the canonical argument types from the argument type list
794038fd1498Szrj ARGTYPES.
794138fd1498Szrj
794238fd1498Szrj Upon return, *ANY_STRUCTURAL_P will be true iff either it was true
794338fd1498Szrj on entry to this function, or if any of the ARGTYPES are
794438fd1498Szrj structural.
794538fd1498Szrj
794638fd1498Szrj Upon return, *ANY_NONCANONICAL_P will be true iff either it was
794738fd1498Szrj true on entry to this function, or if any of the ARGTYPES are
794838fd1498Szrj non-canonical.
794938fd1498Szrj
795038fd1498Szrj Returns a canonical argument list, which may be ARGTYPES when the
795138fd1498Szrj canonical argument list is unneeded (i.e., *ANY_STRUCTURAL_P is
795238fd1498Szrj true) or would not differ from ARGTYPES. */
795338fd1498Szrj
795438fd1498Szrj static tree
maybe_canonicalize_argtypes(tree argtypes,bool * any_structural_p,bool * any_noncanonical_p)795538fd1498Szrj maybe_canonicalize_argtypes (tree argtypes,
795638fd1498Szrj bool *any_structural_p,
795738fd1498Szrj bool *any_noncanonical_p)
795838fd1498Szrj {
795938fd1498Szrj tree arg;
796038fd1498Szrj bool any_noncanonical_argtypes_p = false;
796138fd1498Szrj
796238fd1498Szrj for (arg = argtypes; arg && !(*any_structural_p); arg = TREE_CHAIN (arg))
796338fd1498Szrj {
796438fd1498Szrj if (!TREE_VALUE (arg) || TREE_VALUE (arg) == error_mark_node)
796538fd1498Szrj /* Fail gracefully by stating that the type is structural. */
796638fd1498Szrj *any_structural_p = true;
796738fd1498Szrj else if (TYPE_STRUCTURAL_EQUALITY_P (TREE_VALUE (arg)))
796838fd1498Szrj *any_structural_p = true;
796938fd1498Szrj else if (TYPE_CANONICAL (TREE_VALUE (arg)) != TREE_VALUE (arg)
797038fd1498Szrj || TREE_PURPOSE (arg))
797138fd1498Szrj /* If the argument has a default argument, we consider it
797238fd1498Szrj non-canonical even though the type itself is canonical.
797338fd1498Szrj That way, different variants of function and method types
797438fd1498Szrj with default arguments will all point to the variant with
797538fd1498Szrj no defaults as their canonical type. */
797638fd1498Szrj any_noncanonical_argtypes_p = true;
797738fd1498Szrj }
797838fd1498Szrj
797938fd1498Szrj if (*any_structural_p)
798038fd1498Szrj return argtypes;
798138fd1498Szrj
798238fd1498Szrj if (any_noncanonical_argtypes_p)
798338fd1498Szrj {
798438fd1498Szrj /* Build the canonical list of argument types. */
798538fd1498Szrj tree canon_argtypes = NULL_TREE;
798638fd1498Szrj bool is_void = false;
798738fd1498Szrj
798838fd1498Szrj for (arg = argtypes; arg; arg = TREE_CHAIN (arg))
798938fd1498Szrj {
799038fd1498Szrj if (arg == void_list_node)
799138fd1498Szrj is_void = true;
799238fd1498Szrj else
799338fd1498Szrj canon_argtypes = tree_cons (NULL_TREE,
799438fd1498Szrj TYPE_CANONICAL (TREE_VALUE (arg)),
799538fd1498Szrj canon_argtypes);
799638fd1498Szrj }
799738fd1498Szrj
799838fd1498Szrj canon_argtypes = nreverse (canon_argtypes);
799938fd1498Szrj if (is_void)
800038fd1498Szrj canon_argtypes = chainon (canon_argtypes, void_list_node);
800138fd1498Szrj
800238fd1498Szrj /* There is a non-canonical type. */
800338fd1498Szrj *any_noncanonical_p = true;
800438fd1498Szrj return canon_argtypes;
800538fd1498Szrj }
800638fd1498Szrj
800738fd1498Szrj /* The canonical argument types are the same as ARGTYPES. */
800838fd1498Szrj return argtypes;
800938fd1498Szrj }
801038fd1498Szrj
801138fd1498Szrj /* Construct, lay out and return
801238fd1498Szrj the type of functions returning type VALUE_TYPE
801338fd1498Szrj given arguments of types ARG_TYPES.
801438fd1498Szrj ARG_TYPES is a chain of TREE_LIST nodes whose TREE_VALUEs
801538fd1498Szrj are data type nodes for the arguments of the function.
801638fd1498Szrj If such a type has already been constructed, reuse it. */
801738fd1498Szrj
801838fd1498Szrj tree
build_function_type(tree value_type,tree arg_types)801938fd1498Szrj build_function_type (tree value_type, tree arg_types)
802038fd1498Szrj {
802138fd1498Szrj tree t;
802238fd1498Szrj inchash::hash hstate;
802338fd1498Szrj bool any_structural_p, any_noncanonical_p;
802438fd1498Szrj tree canon_argtypes;
802538fd1498Szrj
8026*58e805e6Szrj gcc_assert (arg_types != error_mark_node);
8027*58e805e6Szrj
802838fd1498Szrj if (TREE_CODE (value_type) == FUNCTION_TYPE)
802938fd1498Szrj {
803038fd1498Szrj error ("function return type cannot be function");
803138fd1498Szrj value_type = integer_type_node;
803238fd1498Szrj }
803338fd1498Szrj
803438fd1498Szrj /* Make a node of the sort we want. */
803538fd1498Szrj t = make_node (FUNCTION_TYPE);
803638fd1498Szrj TREE_TYPE (t) = value_type;
803738fd1498Szrj TYPE_ARG_TYPES (t) = arg_types;
803838fd1498Szrj
803938fd1498Szrj /* If we already have such a type, use the old one. */
804038fd1498Szrj hashval_t hash = type_hash_canon_hash (t);
804138fd1498Szrj t = type_hash_canon (hash, t);
804238fd1498Szrj
804338fd1498Szrj /* Set up the canonical type. */
804438fd1498Szrj any_structural_p = TYPE_STRUCTURAL_EQUALITY_P (value_type);
804538fd1498Szrj any_noncanonical_p = TYPE_CANONICAL (value_type) != value_type;
804638fd1498Szrj canon_argtypes = maybe_canonicalize_argtypes (arg_types,
804738fd1498Szrj &any_structural_p,
804838fd1498Szrj &any_noncanonical_p);
804938fd1498Szrj if (any_structural_p)
805038fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (t);
805138fd1498Szrj else if (any_noncanonical_p)
805238fd1498Szrj TYPE_CANONICAL (t) = build_function_type (TYPE_CANONICAL (value_type),
805338fd1498Szrj canon_argtypes);
805438fd1498Szrj
805538fd1498Szrj if (!COMPLETE_TYPE_P (t))
805638fd1498Szrj layout_type (t);
805738fd1498Szrj return t;
805838fd1498Szrj }
805938fd1498Szrj
806038fd1498Szrj /* Build a function type. The RETURN_TYPE is the type returned by the
806138fd1498Szrj function. If VAARGS is set, no void_type_node is appended to the
806238fd1498Szrj list. ARGP must be always be terminated be a NULL_TREE. */
806338fd1498Szrj
806438fd1498Szrj static tree
build_function_type_list_1(bool vaargs,tree return_type,va_list argp)806538fd1498Szrj build_function_type_list_1 (bool vaargs, tree return_type, va_list argp)
806638fd1498Szrj {
806738fd1498Szrj tree t, args, last;
806838fd1498Szrj
806938fd1498Szrj t = va_arg (argp, tree);
807038fd1498Szrj for (args = NULL_TREE; t != NULL_TREE; t = va_arg (argp, tree))
807138fd1498Szrj args = tree_cons (NULL_TREE, t, args);
807238fd1498Szrj
807338fd1498Szrj if (vaargs)
807438fd1498Szrj {
807538fd1498Szrj last = args;
807638fd1498Szrj if (args != NULL_TREE)
807738fd1498Szrj args = nreverse (args);
807838fd1498Szrj gcc_assert (last != void_list_node);
807938fd1498Szrj }
808038fd1498Szrj else if (args == NULL_TREE)
808138fd1498Szrj args = void_list_node;
808238fd1498Szrj else
808338fd1498Szrj {
808438fd1498Szrj last = args;
808538fd1498Szrj args = nreverse (args);
808638fd1498Szrj TREE_CHAIN (last) = void_list_node;
808738fd1498Szrj }
808838fd1498Szrj args = build_function_type (return_type, args);
808938fd1498Szrj
809038fd1498Szrj return args;
809138fd1498Szrj }
809238fd1498Szrj
809338fd1498Szrj /* Build a function type. The RETURN_TYPE is the type returned by the
809438fd1498Szrj function. If additional arguments are provided, they are
809538fd1498Szrj additional argument types. The list of argument types must always
809638fd1498Szrj be terminated by NULL_TREE. */
809738fd1498Szrj
809838fd1498Szrj tree
build_function_type_list(tree return_type,...)809938fd1498Szrj build_function_type_list (tree return_type, ...)
810038fd1498Szrj {
810138fd1498Szrj tree args;
810238fd1498Szrj va_list p;
810338fd1498Szrj
810438fd1498Szrj va_start (p, return_type);
810538fd1498Szrj args = build_function_type_list_1 (false, return_type, p);
810638fd1498Szrj va_end (p);
810738fd1498Szrj return args;
810838fd1498Szrj }
810938fd1498Szrj
811038fd1498Szrj /* Build a variable argument function type. The RETURN_TYPE is the
811138fd1498Szrj type returned by the function. If additional arguments are provided,
811238fd1498Szrj they are additional argument types. The list of argument types must
811338fd1498Szrj always be terminated by NULL_TREE. */
811438fd1498Szrj
811538fd1498Szrj tree
build_varargs_function_type_list(tree return_type,...)811638fd1498Szrj build_varargs_function_type_list (tree return_type, ...)
811738fd1498Szrj {
811838fd1498Szrj tree args;
811938fd1498Szrj va_list p;
812038fd1498Szrj
812138fd1498Szrj va_start (p, return_type);
812238fd1498Szrj args = build_function_type_list_1 (true, return_type, p);
812338fd1498Szrj va_end (p);
812438fd1498Szrj
812538fd1498Szrj return args;
812638fd1498Szrj }
812738fd1498Szrj
812838fd1498Szrj /* Build a function type. RETURN_TYPE is the type returned by the
812938fd1498Szrj function; VAARGS indicates whether the function takes varargs. The
813038fd1498Szrj function takes N named arguments, the types of which are provided in
813138fd1498Szrj ARG_TYPES. */
813238fd1498Szrj
813338fd1498Szrj static tree
build_function_type_array_1(bool vaargs,tree return_type,int n,tree * arg_types)813438fd1498Szrj build_function_type_array_1 (bool vaargs, tree return_type, int n,
813538fd1498Szrj tree *arg_types)
813638fd1498Szrj {
813738fd1498Szrj int i;
813838fd1498Szrj tree t = vaargs ? NULL_TREE : void_list_node;
813938fd1498Szrj
814038fd1498Szrj for (i = n - 1; i >= 0; i--)
814138fd1498Szrj t = tree_cons (NULL_TREE, arg_types[i], t);
814238fd1498Szrj
814338fd1498Szrj return build_function_type (return_type, t);
814438fd1498Szrj }
814538fd1498Szrj
814638fd1498Szrj /* Build a function type. RETURN_TYPE is the type returned by the
814738fd1498Szrj function. The function takes N named arguments, the types of which
814838fd1498Szrj are provided in ARG_TYPES. */
814938fd1498Szrj
815038fd1498Szrj tree
build_function_type_array(tree return_type,int n,tree * arg_types)815138fd1498Szrj build_function_type_array (tree return_type, int n, tree *arg_types)
815238fd1498Szrj {
815338fd1498Szrj return build_function_type_array_1 (false, return_type, n, arg_types);
815438fd1498Szrj }
815538fd1498Szrj
815638fd1498Szrj /* Build a variable argument function type. RETURN_TYPE is the type
815738fd1498Szrj returned by the function. The function takes N named arguments, the
815838fd1498Szrj types of which are provided in ARG_TYPES. */
815938fd1498Szrj
816038fd1498Szrj tree
build_varargs_function_type_array(tree return_type,int n,tree * arg_types)816138fd1498Szrj build_varargs_function_type_array (tree return_type, int n, tree *arg_types)
816238fd1498Szrj {
816338fd1498Szrj return build_function_type_array_1 (true, return_type, n, arg_types);
816438fd1498Szrj }
816538fd1498Szrj
816638fd1498Szrj /* Build a METHOD_TYPE for a member of BASETYPE. The RETTYPE (a TYPE)
816738fd1498Szrj and ARGTYPES (a TREE_LIST) are the return type and arguments types
816838fd1498Szrj for the method. An implicit additional parameter (of type
816938fd1498Szrj pointer-to-BASETYPE) is added to the ARGTYPES. */
817038fd1498Szrj
817138fd1498Szrj tree
build_method_type_directly(tree basetype,tree rettype,tree argtypes)817238fd1498Szrj build_method_type_directly (tree basetype,
817338fd1498Szrj tree rettype,
817438fd1498Szrj tree argtypes)
817538fd1498Szrj {
817638fd1498Szrj tree t;
817738fd1498Szrj tree ptype;
817838fd1498Szrj bool any_structural_p, any_noncanonical_p;
817938fd1498Szrj tree canon_argtypes;
818038fd1498Szrj
818138fd1498Szrj /* Make a node of the sort we want. */
818238fd1498Szrj t = make_node (METHOD_TYPE);
818338fd1498Szrj
818438fd1498Szrj TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
818538fd1498Szrj TREE_TYPE (t) = rettype;
818638fd1498Szrj ptype = build_pointer_type (basetype);
818738fd1498Szrj
818838fd1498Szrj /* The actual arglist for this function includes a "hidden" argument
818938fd1498Szrj which is "this". Put it into the list of argument types. */
819038fd1498Szrj argtypes = tree_cons (NULL_TREE, ptype, argtypes);
819138fd1498Szrj TYPE_ARG_TYPES (t) = argtypes;
819238fd1498Szrj
819338fd1498Szrj /* If we already have such a type, use the old one. */
819438fd1498Szrj hashval_t hash = type_hash_canon_hash (t);
819538fd1498Szrj t = type_hash_canon (hash, t);
819638fd1498Szrj
819738fd1498Szrj /* Set up the canonical type. */
819838fd1498Szrj any_structural_p
819938fd1498Szrj = (TYPE_STRUCTURAL_EQUALITY_P (basetype)
820038fd1498Szrj || TYPE_STRUCTURAL_EQUALITY_P (rettype));
820138fd1498Szrj any_noncanonical_p
820238fd1498Szrj = (TYPE_CANONICAL (basetype) != basetype
820338fd1498Szrj || TYPE_CANONICAL (rettype) != rettype);
820438fd1498Szrj canon_argtypes = maybe_canonicalize_argtypes (TREE_CHAIN (argtypes),
820538fd1498Szrj &any_structural_p,
820638fd1498Szrj &any_noncanonical_p);
820738fd1498Szrj if (any_structural_p)
820838fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (t);
820938fd1498Szrj else if (any_noncanonical_p)
821038fd1498Szrj TYPE_CANONICAL (t)
821138fd1498Szrj = build_method_type_directly (TYPE_CANONICAL (basetype),
821238fd1498Szrj TYPE_CANONICAL (rettype),
821338fd1498Szrj canon_argtypes);
821438fd1498Szrj if (!COMPLETE_TYPE_P (t))
821538fd1498Szrj layout_type (t);
821638fd1498Szrj
821738fd1498Szrj return t;
821838fd1498Szrj }
821938fd1498Szrj
822038fd1498Szrj /* Construct, lay out and return the type of methods belonging to class
822138fd1498Szrj BASETYPE and whose arguments and values are described by TYPE.
822238fd1498Szrj If that type exists already, reuse it.
822338fd1498Szrj TYPE must be a FUNCTION_TYPE node. */
822438fd1498Szrj
822538fd1498Szrj tree
build_method_type(tree basetype,tree type)822638fd1498Szrj build_method_type (tree basetype, tree type)
822738fd1498Szrj {
822838fd1498Szrj gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
822938fd1498Szrj
823038fd1498Szrj return build_method_type_directly (basetype,
823138fd1498Szrj TREE_TYPE (type),
823238fd1498Szrj TYPE_ARG_TYPES (type));
823338fd1498Szrj }
823438fd1498Szrj
823538fd1498Szrj /* Construct, lay out and return the type of offsets to a value
823638fd1498Szrj of type TYPE, within an object of type BASETYPE.
823738fd1498Szrj If a suitable offset type exists already, reuse it. */
823838fd1498Szrj
823938fd1498Szrj tree
build_offset_type(tree basetype,tree type)824038fd1498Szrj build_offset_type (tree basetype, tree type)
824138fd1498Szrj {
824238fd1498Szrj tree t;
824338fd1498Szrj
824438fd1498Szrj /* Make a node of the sort we want. */
824538fd1498Szrj t = make_node (OFFSET_TYPE);
824638fd1498Szrj
824738fd1498Szrj TYPE_OFFSET_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
824838fd1498Szrj TREE_TYPE (t) = type;
824938fd1498Szrj
825038fd1498Szrj /* If we already have such a type, use the old one. */
825138fd1498Szrj hashval_t hash = type_hash_canon_hash (t);
825238fd1498Szrj t = type_hash_canon (hash, t);
825338fd1498Szrj
825438fd1498Szrj if (!COMPLETE_TYPE_P (t))
825538fd1498Szrj layout_type (t);
825638fd1498Szrj
825738fd1498Szrj if (TYPE_CANONICAL (t) == t)
825838fd1498Szrj {
825938fd1498Szrj if (TYPE_STRUCTURAL_EQUALITY_P (basetype)
826038fd1498Szrj || TYPE_STRUCTURAL_EQUALITY_P (type))
826138fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (t);
826238fd1498Szrj else if (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)) != basetype
826338fd1498Szrj || TYPE_CANONICAL (type) != type)
826438fd1498Szrj TYPE_CANONICAL (t)
826538fd1498Szrj = build_offset_type (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)),
826638fd1498Szrj TYPE_CANONICAL (type));
826738fd1498Szrj }
826838fd1498Szrj
826938fd1498Szrj return t;
827038fd1498Szrj }
827138fd1498Szrj
827238fd1498Szrj /* Create a complex type whose components are COMPONENT_TYPE.
827338fd1498Szrj
827438fd1498Szrj If NAMED is true, the type is given a TYPE_NAME. We do not always
827538fd1498Szrj do so because this creates a DECL node and thus make the DECL_UIDs
827638fd1498Szrj dependent on the type canonicalization hashtable, which is GC-ed,
827738fd1498Szrj so the DECL_UIDs would not be stable wrt garbage collection. */
827838fd1498Szrj
827938fd1498Szrj tree
build_complex_type(tree component_type,bool named)828038fd1498Szrj build_complex_type (tree component_type, bool named)
828138fd1498Szrj {
828238fd1498Szrj gcc_assert (INTEGRAL_TYPE_P (component_type)
828338fd1498Szrj || SCALAR_FLOAT_TYPE_P (component_type)
828438fd1498Szrj || FIXED_POINT_TYPE_P (component_type));
828538fd1498Szrj
828638fd1498Szrj /* Make a node of the sort we want. */
828738fd1498Szrj tree probe = make_node (COMPLEX_TYPE);
828838fd1498Szrj
828938fd1498Szrj TREE_TYPE (probe) = TYPE_MAIN_VARIANT (component_type);
829038fd1498Szrj
829138fd1498Szrj /* If we already have such a type, use the old one. */
829238fd1498Szrj hashval_t hash = type_hash_canon_hash (probe);
829338fd1498Szrj tree t = type_hash_canon (hash, probe);
829438fd1498Szrj
829538fd1498Szrj if (t == probe)
829638fd1498Szrj {
829738fd1498Szrj /* We created a new type. The hash insertion will have laid
829838fd1498Szrj out the type. We need to check the canonicalization and
829938fd1498Szrj maybe set the name. */
830038fd1498Szrj gcc_checking_assert (COMPLETE_TYPE_P (t)
830138fd1498Szrj && !TYPE_NAME (t)
830238fd1498Szrj && TYPE_CANONICAL (t) == t);
830338fd1498Szrj
830438fd1498Szrj if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (t)))
830538fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (t);
830638fd1498Szrj else if (TYPE_CANONICAL (TREE_TYPE (t)) != TREE_TYPE (t))
830738fd1498Szrj TYPE_CANONICAL (t)
830838fd1498Szrj = build_complex_type (TYPE_CANONICAL (TREE_TYPE (t)), named);
830938fd1498Szrj
831038fd1498Szrj /* We need to create a name, since complex is a fundamental type. */
831138fd1498Szrj if (named)
831238fd1498Szrj {
831338fd1498Szrj const char *name = NULL;
831438fd1498Szrj
831538fd1498Szrj if (TREE_TYPE (t) == char_type_node)
831638fd1498Szrj name = "complex char";
831738fd1498Szrj else if (TREE_TYPE (t) == signed_char_type_node)
831838fd1498Szrj name = "complex signed char";
831938fd1498Szrj else if (TREE_TYPE (t) == unsigned_char_type_node)
832038fd1498Szrj name = "complex unsigned char";
832138fd1498Szrj else if (TREE_TYPE (t) == short_integer_type_node)
832238fd1498Szrj name = "complex short int";
832338fd1498Szrj else if (TREE_TYPE (t) == short_unsigned_type_node)
832438fd1498Szrj name = "complex short unsigned int";
832538fd1498Szrj else if (TREE_TYPE (t) == integer_type_node)
832638fd1498Szrj name = "complex int";
832738fd1498Szrj else if (TREE_TYPE (t) == unsigned_type_node)
832838fd1498Szrj name = "complex unsigned int";
832938fd1498Szrj else if (TREE_TYPE (t) == long_integer_type_node)
833038fd1498Szrj name = "complex long int";
833138fd1498Szrj else if (TREE_TYPE (t) == long_unsigned_type_node)
833238fd1498Szrj name = "complex long unsigned int";
833338fd1498Szrj else if (TREE_TYPE (t) == long_long_integer_type_node)
833438fd1498Szrj name = "complex long long int";
833538fd1498Szrj else if (TREE_TYPE (t) == long_long_unsigned_type_node)
833638fd1498Szrj name = "complex long long unsigned int";
833738fd1498Szrj
833838fd1498Szrj if (name != NULL)
833938fd1498Szrj TYPE_NAME (t) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
834038fd1498Szrj get_identifier (name), t);
834138fd1498Szrj }
834238fd1498Szrj }
834338fd1498Szrj
834438fd1498Szrj return build_qualified_type (t, TYPE_QUALS (component_type));
834538fd1498Szrj }
834638fd1498Szrj
834738fd1498Szrj /* If TYPE is a real or complex floating-point type and the target
834838fd1498Szrj does not directly support arithmetic on TYPE then return the wider
834938fd1498Szrj type to be used for arithmetic on TYPE. Otherwise, return
835038fd1498Szrj NULL_TREE. */
835138fd1498Szrj
835238fd1498Szrj tree
excess_precision_type(tree type)835338fd1498Szrj excess_precision_type (tree type)
835438fd1498Szrj {
835538fd1498Szrj /* The target can give two different responses to the question of
835638fd1498Szrj which excess precision mode it would like depending on whether we
835738fd1498Szrj are in -fexcess-precision=standard or -fexcess-precision=fast. */
835838fd1498Szrj
835938fd1498Szrj enum excess_precision_type requested_type
836038fd1498Szrj = (flag_excess_precision == EXCESS_PRECISION_FAST
836138fd1498Szrj ? EXCESS_PRECISION_TYPE_FAST
836238fd1498Szrj : EXCESS_PRECISION_TYPE_STANDARD);
836338fd1498Szrj
836438fd1498Szrj enum flt_eval_method target_flt_eval_method
836538fd1498Szrj = targetm.c.excess_precision (requested_type);
836638fd1498Szrj
836738fd1498Szrj /* The target should not ask for unpredictable float evaluation (though
836838fd1498Szrj it might advertise that implicitly the evaluation is unpredictable,
836938fd1498Szrj but we don't care about that here, it will have been reported
837038fd1498Szrj elsewhere). If it does ask for unpredictable evaluation, we have
837138fd1498Szrj nothing to do here. */
837238fd1498Szrj gcc_assert (target_flt_eval_method != FLT_EVAL_METHOD_UNPREDICTABLE);
837338fd1498Szrj
837438fd1498Szrj /* Nothing to do. The target has asked for all types we know about
837538fd1498Szrj to be computed with their native precision and range. */
837638fd1498Szrj if (target_flt_eval_method == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
837738fd1498Szrj return NULL_TREE;
837838fd1498Szrj
837938fd1498Szrj /* The target will promote this type in a target-dependent way, so excess
838038fd1498Szrj precision ought to leave it alone. */
838138fd1498Szrj if (targetm.promoted_type (type) != NULL_TREE)
838238fd1498Szrj return NULL_TREE;
838338fd1498Szrj
838438fd1498Szrj machine_mode float16_type_mode = (float16_type_node
838538fd1498Szrj ? TYPE_MODE (float16_type_node)
838638fd1498Szrj : VOIDmode);
838738fd1498Szrj machine_mode float_type_mode = TYPE_MODE (float_type_node);
838838fd1498Szrj machine_mode double_type_mode = TYPE_MODE (double_type_node);
838938fd1498Szrj
839038fd1498Szrj switch (TREE_CODE (type))
839138fd1498Szrj {
839238fd1498Szrj case REAL_TYPE:
839338fd1498Szrj {
839438fd1498Szrj machine_mode type_mode = TYPE_MODE (type);
839538fd1498Szrj switch (target_flt_eval_method)
839638fd1498Szrj {
839738fd1498Szrj case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
839838fd1498Szrj if (type_mode == float16_type_mode)
839938fd1498Szrj return float_type_node;
840038fd1498Szrj break;
840138fd1498Szrj case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
840238fd1498Szrj if (type_mode == float16_type_mode
840338fd1498Szrj || type_mode == float_type_mode)
840438fd1498Szrj return double_type_node;
840538fd1498Szrj break;
840638fd1498Szrj case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
840738fd1498Szrj if (type_mode == float16_type_mode
840838fd1498Szrj || type_mode == float_type_mode
840938fd1498Szrj || type_mode == double_type_mode)
841038fd1498Szrj return long_double_type_node;
841138fd1498Szrj break;
841238fd1498Szrj default:
841338fd1498Szrj gcc_unreachable ();
841438fd1498Szrj }
841538fd1498Szrj break;
841638fd1498Szrj }
841738fd1498Szrj case COMPLEX_TYPE:
841838fd1498Szrj {
841938fd1498Szrj if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
842038fd1498Szrj return NULL_TREE;
842138fd1498Szrj machine_mode type_mode = TYPE_MODE (TREE_TYPE (type));
842238fd1498Szrj switch (target_flt_eval_method)
842338fd1498Szrj {
842438fd1498Szrj case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
842538fd1498Szrj if (type_mode == float16_type_mode)
842638fd1498Szrj return complex_float_type_node;
842738fd1498Szrj break;
842838fd1498Szrj case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
842938fd1498Szrj if (type_mode == float16_type_mode
843038fd1498Szrj || type_mode == float_type_mode)
843138fd1498Szrj return complex_double_type_node;
843238fd1498Szrj break;
843338fd1498Szrj case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
843438fd1498Szrj if (type_mode == float16_type_mode
843538fd1498Szrj || type_mode == float_type_mode
843638fd1498Szrj || type_mode == double_type_mode)
843738fd1498Szrj return complex_long_double_type_node;
843838fd1498Szrj break;
843938fd1498Szrj default:
844038fd1498Szrj gcc_unreachable ();
844138fd1498Szrj }
844238fd1498Szrj break;
844338fd1498Szrj }
844438fd1498Szrj default:
844538fd1498Szrj break;
844638fd1498Szrj }
844738fd1498Szrj
844838fd1498Szrj return NULL_TREE;
844938fd1498Szrj }
845038fd1498Szrj
845138fd1498Szrj /* Return OP, stripped of any conversions to wider types as much as is safe.
845238fd1498Szrj Converting the value back to OP's type makes a value equivalent to OP.
845338fd1498Szrj
845438fd1498Szrj If FOR_TYPE is nonzero, we return a value which, if converted to
845538fd1498Szrj type FOR_TYPE, would be equivalent to converting OP to type FOR_TYPE.
845638fd1498Szrj
845738fd1498Szrj OP must have integer, real or enumeral type. Pointers are not allowed!
845838fd1498Szrj
845938fd1498Szrj There are some cases where the obvious value we could return
846038fd1498Szrj would regenerate to OP if converted to OP's type,
846138fd1498Szrj but would not extend like OP to wider types.
846238fd1498Szrj If FOR_TYPE indicates such extension is contemplated, we eschew such values.
846338fd1498Szrj For example, if OP is (unsigned short)(signed char)-1,
846438fd1498Szrj we avoid returning (signed char)-1 if FOR_TYPE is int,
846538fd1498Szrj even though extending that to an unsigned short would regenerate OP,
846638fd1498Szrj since the result of extending (signed char)-1 to (int)
846738fd1498Szrj is different from (int) OP. */
846838fd1498Szrj
846938fd1498Szrj tree
get_unwidened(tree op,tree for_type)847038fd1498Szrj get_unwidened (tree op, tree for_type)
847138fd1498Szrj {
847238fd1498Szrj /* Set UNS initially if converting OP to FOR_TYPE is a zero-extension. */
847338fd1498Szrj tree type = TREE_TYPE (op);
847438fd1498Szrj unsigned final_prec
847538fd1498Szrj = TYPE_PRECISION (for_type != 0 ? for_type : type);
847638fd1498Szrj int uns
847738fd1498Szrj = (for_type != 0 && for_type != type
847838fd1498Szrj && final_prec > TYPE_PRECISION (type)
847938fd1498Szrj && TYPE_UNSIGNED (type));
848038fd1498Szrj tree win = op;
848138fd1498Szrj
848238fd1498Szrj while (CONVERT_EXPR_P (op))
848338fd1498Szrj {
848438fd1498Szrj int bitschange;
848538fd1498Szrj
848638fd1498Szrj /* TYPE_PRECISION on vector types has different meaning
848738fd1498Szrj (TYPE_VECTOR_SUBPARTS) and casts from vectors are view conversions,
848838fd1498Szrj so avoid them here. */
848938fd1498Szrj if (TREE_CODE (TREE_TYPE (TREE_OPERAND (op, 0))) == VECTOR_TYPE)
849038fd1498Szrj break;
849138fd1498Szrj
849238fd1498Szrj bitschange = TYPE_PRECISION (TREE_TYPE (op))
849338fd1498Szrj - TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op, 0)));
849438fd1498Szrj
849538fd1498Szrj /* Truncations are many-one so cannot be removed.
849638fd1498Szrj Unless we are later going to truncate down even farther. */
849738fd1498Szrj if (bitschange < 0
849838fd1498Szrj && final_prec > TYPE_PRECISION (TREE_TYPE (op)))
849938fd1498Szrj break;
850038fd1498Szrj
850138fd1498Szrj /* See what's inside this conversion. If we decide to strip it,
850238fd1498Szrj we will set WIN. */
850338fd1498Szrj op = TREE_OPERAND (op, 0);
850438fd1498Szrj
850538fd1498Szrj /* If we have not stripped any zero-extensions (uns is 0),
850638fd1498Szrj we can strip any kind of extension.
850738fd1498Szrj If we have previously stripped a zero-extension,
850838fd1498Szrj only zero-extensions can safely be stripped.
850938fd1498Szrj Any extension can be stripped if the bits it would produce
851038fd1498Szrj are all going to be discarded later by truncating to FOR_TYPE. */
851138fd1498Szrj
851238fd1498Szrj if (bitschange > 0)
851338fd1498Szrj {
851438fd1498Szrj if (! uns || final_prec <= TYPE_PRECISION (TREE_TYPE (op)))
851538fd1498Szrj win = op;
851638fd1498Szrj /* TYPE_UNSIGNED says whether this is a zero-extension.
851738fd1498Szrj Let's avoid computing it if it does not affect WIN
851838fd1498Szrj and if UNS will not be needed again. */
851938fd1498Szrj if ((uns
852038fd1498Szrj || CONVERT_EXPR_P (op))
852138fd1498Szrj && TYPE_UNSIGNED (TREE_TYPE (op)))
852238fd1498Szrj {
852338fd1498Szrj uns = 1;
852438fd1498Szrj win = op;
852538fd1498Szrj }
852638fd1498Szrj }
852738fd1498Szrj }
852838fd1498Szrj
852938fd1498Szrj /* If we finally reach a constant see if it fits in sth smaller and
853038fd1498Szrj in that case convert it. */
853138fd1498Szrj if (TREE_CODE (win) == INTEGER_CST)
853238fd1498Szrj {
853338fd1498Szrj tree wtype = TREE_TYPE (win);
853438fd1498Szrj unsigned prec = wi::min_precision (wi::to_wide (win), TYPE_SIGN (wtype));
853538fd1498Szrj if (for_type)
853638fd1498Szrj prec = MAX (prec, final_prec);
853738fd1498Szrj if (prec < TYPE_PRECISION (wtype))
853838fd1498Szrj {
853938fd1498Szrj tree t = lang_hooks.types.type_for_size (prec, TYPE_UNSIGNED (wtype));
854038fd1498Szrj if (t && TYPE_PRECISION (t) < TYPE_PRECISION (wtype))
854138fd1498Szrj win = fold_convert (t, win);
854238fd1498Szrj }
854338fd1498Szrj }
854438fd1498Szrj
854538fd1498Szrj return win;
854638fd1498Szrj }
854738fd1498Szrj
854838fd1498Szrj /* Return OP or a simpler expression for a narrower value
854938fd1498Szrj which can be sign-extended or zero-extended to give back OP.
855038fd1498Szrj Store in *UNSIGNEDP_PTR either 1 if the value should be zero-extended
855138fd1498Szrj or 0 if the value should be sign-extended. */
855238fd1498Szrj
855338fd1498Szrj tree
get_narrower(tree op,int * unsignedp_ptr)855438fd1498Szrj get_narrower (tree op, int *unsignedp_ptr)
855538fd1498Szrj {
855638fd1498Szrj int uns = 0;
855738fd1498Szrj int first = 1;
855838fd1498Szrj tree win = op;
855938fd1498Szrj bool integral_p = INTEGRAL_TYPE_P (TREE_TYPE (op));
856038fd1498Szrj
856138fd1498Szrj while (TREE_CODE (op) == NOP_EXPR)
856238fd1498Szrj {
856338fd1498Szrj int bitschange
856438fd1498Szrj = (TYPE_PRECISION (TREE_TYPE (op))
856538fd1498Szrj - TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op, 0))));
856638fd1498Szrj
856738fd1498Szrj /* Truncations are many-one so cannot be removed. */
856838fd1498Szrj if (bitschange < 0)
856938fd1498Szrj break;
857038fd1498Szrj
857138fd1498Szrj /* See what's inside this conversion. If we decide to strip it,
857238fd1498Szrj we will set WIN. */
857338fd1498Szrj
857438fd1498Szrj if (bitschange > 0)
857538fd1498Szrj {
857638fd1498Szrj op = TREE_OPERAND (op, 0);
857738fd1498Szrj /* An extension: the outermost one can be stripped,
857838fd1498Szrj but remember whether it is zero or sign extension. */
857938fd1498Szrj if (first)
858038fd1498Szrj uns = TYPE_UNSIGNED (TREE_TYPE (op));
858138fd1498Szrj /* Otherwise, if a sign extension has been stripped,
858238fd1498Szrj only sign extensions can now be stripped;
858338fd1498Szrj if a zero extension has been stripped, only zero-extensions. */
858438fd1498Szrj else if (uns != TYPE_UNSIGNED (TREE_TYPE (op)))
858538fd1498Szrj break;
858638fd1498Szrj first = 0;
858738fd1498Szrj }
858838fd1498Szrj else /* bitschange == 0 */
858938fd1498Szrj {
859038fd1498Szrj /* A change in nominal type can always be stripped, but we must
859138fd1498Szrj preserve the unsignedness. */
859238fd1498Szrj if (first)
859338fd1498Szrj uns = TYPE_UNSIGNED (TREE_TYPE (op));
859438fd1498Szrj first = 0;
859538fd1498Szrj op = TREE_OPERAND (op, 0);
859638fd1498Szrj /* Keep trying to narrow, but don't assign op to win if it
859738fd1498Szrj would turn an integral type into something else. */
859838fd1498Szrj if (INTEGRAL_TYPE_P (TREE_TYPE (op)) != integral_p)
859938fd1498Szrj continue;
860038fd1498Szrj }
860138fd1498Szrj
860238fd1498Szrj win = op;
860338fd1498Szrj }
860438fd1498Szrj
860538fd1498Szrj if (TREE_CODE (op) == COMPONENT_REF
860638fd1498Szrj /* Since type_for_size always gives an integer type. */
860738fd1498Szrj && TREE_CODE (TREE_TYPE (op)) != REAL_TYPE
860838fd1498Szrj && TREE_CODE (TREE_TYPE (op)) != FIXED_POINT_TYPE
860938fd1498Szrj /* Ensure field is laid out already. */
861038fd1498Szrj && DECL_SIZE (TREE_OPERAND (op, 1)) != 0
861138fd1498Szrj && tree_fits_uhwi_p (DECL_SIZE (TREE_OPERAND (op, 1))))
861238fd1498Szrj {
861338fd1498Szrj unsigned HOST_WIDE_INT innerprec
861438fd1498Szrj = tree_to_uhwi (DECL_SIZE (TREE_OPERAND (op, 1)));
861538fd1498Szrj int unsignedp = (DECL_UNSIGNED (TREE_OPERAND (op, 1))
861638fd1498Szrj || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 1))));
861738fd1498Szrj tree type = lang_hooks.types.type_for_size (innerprec, unsignedp);
861838fd1498Szrj
861938fd1498Szrj /* We can get this structure field in a narrower type that fits it,
862038fd1498Szrj but the resulting extension to its nominal type (a fullword type)
862138fd1498Szrj must satisfy the same conditions as for other extensions.
862238fd1498Szrj
862338fd1498Szrj Do this only for fields that are aligned (not bit-fields),
862438fd1498Szrj because when bit-field insns will be used there is no
862538fd1498Szrj advantage in doing this. */
862638fd1498Szrj
862738fd1498Szrj if (innerprec < TYPE_PRECISION (TREE_TYPE (op))
862838fd1498Szrj && ! DECL_BIT_FIELD (TREE_OPERAND (op, 1))
862938fd1498Szrj && (first || uns == DECL_UNSIGNED (TREE_OPERAND (op, 1)))
863038fd1498Szrj && type != 0)
863138fd1498Szrj {
863238fd1498Szrj if (first)
863338fd1498Szrj uns = DECL_UNSIGNED (TREE_OPERAND (op, 1));
863438fd1498Szrj win = fold_convert (type, op);
863538fd1498Szrj }
863638fd1498Szrj }
863738fd1498Szrj
863838fd1498Szrj *unsignedp_ptr = uns;
863938fd1498Szrj return win;
864038fd1498Szrj }
864138fd1498Szrj
864238fd1498Szrj /* Return true if integer constant C has a value that is permissible
864338fd1498Szrj for TYPE, an integral type. */
864438fd1498Szrj
864538fd1498Szrj bool
int_fits_type_p(const_tree c,const_tree type)864638fd1498Szrj int_fits_type_p (const_tree c, const_tree type)
864738fd1498Szrj {
864838fd1498Szrj tree type_low_bound, type_high_bound;
864938fd1498Szrj bool ok_for_low_bound, ok_for_high_bound;
865038fd1498Szrj signop sgn_c = TYPE_SIGN (TREE_TYPE (c));
865138fd1498Szrj
865238fd1498Szrj /* Non-standard boolean types can have arbitrary precision but various
865338fd1498Szrj transformations assume that they can only take values 0 and +/-1. */
865438fd1498Szrj if (TREE_CODE (type) == BOOLEAN_TYPE)
865538fd1498Szrj return wi::fits_to_boolean_p (wi::to_wide (c), type);
865638fd1498Szrj
865738fd1498Szrj retry:
865838fd1498Szrj type_low_bound = TYPE_MIN_VALUE (type);
865938fd1498Szrj type_high_bound = TYPE_MAX_VALUE (type);
866038fd1498Szrj
866138fd1498Szrj /* If at least one bound of the type is a constant integer, we can check
866238fd1498Szrj ourselves and maybe make a decision. If no such decision is possible, but
866338fd1498Szrj this type is a subtype, try checking against that. Otherwise, use
866438fd1498Szrj fits_to_tree_p, which checks against the precision.
866538fd1498Szrj
866638fd1498Szrj Compute the status for each possibly constant bound, and return if we see
866738fd1498Szrj one does not match. Use ok_for_xxx_bound for this purpose, assigning -1
866838fd1498Szrj for "unknown if constant fits", 0 for "constant known *not* to fit" and 1
866938fd1498Szrj for "constant known to fit". */
867038fd1498Szrj
867138fd1498Szrj /* Check if c >= type_low_bound. */
867238fd1498Szrj if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST)
867338fd1498Szrj {
867438fd1498Szrj if (tree_int_cst_lt (c, type_low_bound))
867538fd1498Szrj return false;
867638fd1498Szrj ok_for_low_bound = true;
867738fd1498Szrj }
867838fd1498Szrj else
867938fd1498Szrj ok_for_low_bound = false;
868038fd1498Szrj
868138fd1498Szrj /* Check if c <= type_high_bound. */
868238fd1498Szrj if (type_high_bound && TREE_CODE (type_high_bound) == INTEGER_CST)
868338fd1498Szrj {
868438fd1498Szrj if (tree_int_cst_lt (type_high_bound, c))
868538fd1498Szrj return false;
868638fd1498Szrj ok_for_high_bound = true;
868738fd1498Szrj }
868838fd1498Szrj else
868938fd1498Szrj ok_for_high_bound = false;
869038fd1498Szrj
869138fd1498Szrj /* If the constant fits both bounds, the result is known. */
869238fd1498Szrj if (ok_for_low_bound && ok_for_high_bound)
869338fd1498Szrj return true;
869438fd1498Szrj
869538fd1498Szrj /* Perform some generic filtering which may allow making a decision
869638fd1498Szrj even if the bounds are not constant. First, negative integers
869738fd1498Szrj never fit in unsigned types, */
869838fd1498Szrj if (TYPE_UNSIGNED (type) && sgn_c == SIGNED && wi::neg_p (wi::to_wide (c)))
869938fd1498Szrj return false;
870038fd1498Szrj
870138fd1498Szrj /* Second, narrower types always fit in wider ones. */
870238fd1498Szrj if (TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (c)))
870338fd1498Szrj return true;
870438fd1498Szrj
870538fd1498Szrj /* Third, unsigned integers with top bit set never fit signed types. */
870638fd1498Szrj if (!TYPE_UNSIGNED (type) && sgn_c == UNSIGNED)
870738fd1498Szrj {
870838fd1498Szrj int prec = GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (TREE_TYPE (c))) - 1;
870938fd1498Szrj if (prec < TYPE_PRECISION (TREE_TYPE (c)))
871038fd1498Szrj {
871138fd1498Szrj /* When a tree_cst is converted to a wide-int, the precision
871238fd1498Szrj is taken from the type. However, if the precision of the
871338fd1498Szrj mode underneath the type is smaller than that, it is
871438fd1498Szrj possible that the value will not fit. The test below
871538fd1498Szrj fails if any bit is set between the sign bit of the
871638fd1498Szrj underlying mode and the top bit of the type. */
871738fd1498Szrj if (wi::zext (wi::to_wide (c), prec - 1) != wi::to_wide (c))
871838fd1498Szrj return false;
871938fd1498Szrj }
872038fd1498Szrj else if (wi::neg_p (wi::to_wide (c)))
872138fd1498Szrj return false;
872238fd1498Szrj }
872338fd1498Szrj
872438fd1498Szrj /* If we haven't been able to decide at this point, there nothing more we
872538fd1498Szrj can check ourselves here. Look at the base type if we have one and it
872638fd1498Szrj has the same precision. */
872738fd1498Szrj if (TREE_CODE (type) == INTEGER_TYPE
872838fd1498Szrj && TREE_TYPE (type) != 0
872938fd1498Szrj && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (type)))
873038fd1498Szrj {
873138fd1498Szrj type = TREE_TYPE (type);
873238fd1498Szrj goto retry;
873338fd1498Szrj }
873438fd1498Szrj
873538fd1498Szrj /* Or to fits_to_tree_p, if nothing else. */
873638fd1498Szrj return wi::fits_to_tree_p (wi::to_wide (c), type);
873738fd1498Szrj }
873838fd1498Szrj
873938fd1498Szrj /* Stores bounds of an integer TYPE in MIN and MAX. If TYPE has non-constant
874038fd1498Szrj bounds or is a POINTER_TYPE, the maximum and/or minimum values that can be
874138fd1498Szrj represented (assuming two's-complement arithmetic) within the bit
874238fd1498Szrj precision of the type are returned instead. */
874338fd1498Szrj
874438fd1498Szrj void
get_type_static_bounds(const_tree type,mpz_t min,mpz_t max)874538fd1498Szrj get_type_static_bounds (const_tree type, mpz_t min, mpz_t max)
874638fd1498Szrj {
874738fd1498Szrj if (!POINTER_TYPE_P (type) && TYPE_MIN_VALUE (type)
874838fd1498Szrj && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST)
874938fd1498Szrj wi::to_mpz (wi::to_wide (TYPE_MIN_VALUE (type)), min, TYPE_SIGN (type));
875038fd1498Szrj else
875138fd1498Szrj {
875238fd1498Szrj if (TYPE_UNSIGNED (type))
875338fd1498Szrj mpz_set_ui (min, 0);
875438fd1498Szrj else
875538fd1498Szrj {
875638fd1498Szrj wide_int mn = wi::min_value (TYPE_PRECISION (type), SIGNED);
875738fd1498Szrj wi::to_mpz (mn, min, SIGNED);
875838fd1498Szrj }
875938fd1498Szrj }
876038fd1498Szrj
876138fd1498Szrj if (!POINTER_TYPE_P (type) && TYPE_MAX_VALUE (type)
876238fd1498Szrj && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST)
876338fd1498Szrj wi::to_mpz (wi::to_wide (TYPE_MAX_VALUE (type)), max, TYPE_SIGN (type));
876438fd1498Szrj else
876538fd1498Szrj {
876638fd1498Szrj wide_int mn = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
876738fd1498Szrj wi::to_mpz (mn, max, TYPE_SIGN (type));
876838fd1498Szrj }
876938fd1498Szrj }
877038fd1498Szrj
877138fd1498Szrj /* Return true if VAR is an automatic variable defined in function FN. */
877238fd1498Szrj
877338fd1498Szrj bool
auto_var_in_fn_p(const_tree var,const_tree fn)877438fd1498Szrj auto_var_in_fn_p (const_tree var, const_tree fn)
877538fd1498Szrj {
877638fd1498Szrj return (DECL_P (var) && DECL_CONTEXT (var) == fn
877738fd1498Szrj && ((((VAR_P (var) && ! DECL_EXTERNAL (var))
877838fd1498Szrj || TREE_CODE (var) == PARM_DECL)
877938fd1498Szrj && ! TREE_STATIC (var))
878038fd1498Szrj || TREE_CODE (var) == LABEL_DECL
878138fd1498Szrj || TREE_CODE (var) == RESULT_DECL));
878238fd1498Szrj }
878338fd1498Szrj
878438fd1498Szrj /* Subprogram of following function. Called by walk_tree.
878538fd1498Szrj
878638fd1498Szrj Return *TP if it is an automatic variable or parameter of the
878738fd1498Szrj function passed in as DATA. */
878838fd1498Szrj
878938fd1498Szrj static tree
find_var_from_fn(tree * tp,int * walk_subtrees,void * data)879038fd1498Szrj find_var_from_fn (tree *tp, int *walk_subtrees, void *data)
879138fd1498Szrj {
879238fd1498Szrj tree fn = (tree) data;
879338fd1498Szrj
879438fd1498Szrj if (TYPE_P (*tp))
879538fd1498Szrj *walk_subtrees = 0;
879638fd1498Szrj
879738fd1498Szrj else if (DECL_P (*tp)
879838fd1498Szrj && auto_var_in_fn_p (*tp, fn))
879938fd1498Szrj return *tp;
880038fd1498Szrj
880138fd1498Szrj return NULL_TREE;
880238fd1498Szrj }
880338fd1498Szrj
880438fd1498Szrj /* Returns true if T is, contains, or refers to a type with variable
880538fd1498Szrj size. For METHOD_TYPEs and FUNCTION_TYPEs we exclude the
880638fd1498Szrj arguments, but not the return type. If FN is nonzero, only return
880738fd1498Szrj true if a modifier of the type or position of FN is a variable or
880838fd1498Szrj parameter inside FN.
880938fd1498Szrj
881038fd1498Szrj This concept is more general than that of C99 'variably modified types':
881138fd1498Szrj in C99, a struct type is never variably modified because a VLA may not
881238fd1498Szrj appear as a structure member. However, in GNU C code like:
881338fd1498Szrj
881438fd1498Szrj struct S { int i[f()]; };
881538fd1498Szrj
881638fd1498Szrj is valid, and other languages may define similar constructs. */
881738fd1498Szrj
881838fd1498Szrj bool
variably_modified_type_p(tree type,tree fn)881938fd1498Szrj variably_modified_type_p (tree type, tree fn)
882038fd1498Szrj {
882138fd1498Szrj tree t;
882238fd1498Szrj
882338fd1498Szrj /* Test if T is either variable (if FN is zero) or an expression containing
882438fd1498Szrj a variable in FN. If TYPE isn't gimplified, return true also if
882538fd1498Szrj gimplify_one_sizepos would gimplify the expression into a local
882638fd1498Szrj variable. */
882738fd1498Szrj #define RETURN_TRUE_IF_VAR(T) \
882838fd1498Szrj do { tree _t = (T); \
882938fd1498Szrj if (_t != NULL_TREE \
883038fd1498Szrj && _t != error_mark_node \
883138fd1498Szrj && !CONSTANT_CLASS_P (_t) \
883238fd1498Szrj && TREE_CODE (_t) != PLACEHOLDER_EXPR \
883338fd1498Szrj && (!fn \
883438fd1498Szrj || (!TYPE_SIZES_GIMPLIFIED (type) \
883538fd1498Szrj && (TREE_CODE (_t) != VAR_DECL \
883638fd1498Szrj && !CONTAINS_PLACEHOLDER_P (_t))) \
883738fd1498Szrj || walk_tree (&_t, find_var_from_fn, fn, NULL))) \
883838fd1498Szrj return true; } while (0)
883938fd1498Szrj
884038fd1498Szrj if (type == error_mark_node)
884138fd1498Szrj return false;
884238fd1498Szrj
884338fd1498Szrj /* If TYPE itself has variable size, it is variably modified. */
884438fd1498Szrj RETURN_TRUE_IF_VAR (TYPE_SIZE (type));
884538fd1498Szrj RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT (type));
884638fd1498Szrj
884738fd1498Szrj switch (TREE_CODE (type))
884838fd1498Szrj {
884938fd1498Szrj case POINTER_TYPE:
885038fd1498Szrj case REFERENCE_TYPE:
885138fd1498Szrj case VECTOR_TYPE:
885238fd1498Szrj /* Ada can have pointer types refering to themselves indirectly. */
885338fd1498Szrj if (TREE_VISITED (type))
885438fd1498Szrj return false;
885538fd1498Szrj TREE_VISITED (type) = true;
885638fd1498Szrj if (variably_modified_type_p (TREE_TYPE (type), fn))
885738fd1498Szrj {
885838fd1498Szrj TREE_VISITED (type) = false;
885938fd1498Szrj return true;
886038fd1498Szrj }
886138fd1498Szrj TREE_VISITED (type) = false;
886238fd1498Szrj break;
886338fd1498Szrj
886438fd1498Szrj case FUNCTION_TYPE:
886538fd1498Szrj case METHOD_TYPE:
886638fd1498Szrj /* If TYPE is a function type, it is variably modified if the
886738fd1498Szrj return type is variably modified. */
886838fd1498Szrj if (variably_modified_type_p (TREE_TYPE (type), fn))
886938fd1498Szrj return true;
887038fd1498Szrj break;
887138fd1498Szrj
887238fd1498Szrj case INTEGER_TYPE:
887338fd1498Szrj case REAL_TYPE:
887438fd1498Szrj case FIXED_POINT_TYPE:
887538fd1498Szrj case ENUMERAL_TYPE:
887638fd1498Szrj case BOOLEAN_TYPE:
887738fd1498Szrj /* Scalar types are variably modified if their end points
887838fd1498Szrj aren't constant. */
887938fd1498Szrj RETURN_TRUE_IF_VAR (TYPE_MIN_VALUE (type));
888038fd1498Szrj RETURN_TRUE_IF_VAR (TYPE_MAX_VALUE (type));
888138fd1498Szrj break;
888238fd1498Szrj
888338fd1498Szrj case RECORD_TYPE:
888438fd1498Szrj case UNION_TYPE:
888538fd1498Szrj case QUAL_UNION_TYPE:
888638fd1498Szrj /* We can't see if any of the fields are variably-modified by the
888738fd1498Szrj definition we normally use, since that would produce infinite
888838fd1498Szrj recursion via pointers. */
888938fd1498Szrj /* This is variably modified if some field's type is. */
889038fd1498Szrj for (t = TYPE_FIELDS (type); t; t = DECL_CHAIN (t))
889138fd1498Szrj if (TREE_CODE (t) == FIELD_DECL)
889238fd1498Szrj {
889338fd1498Szrj RETURN_TRUE_IF_VAR (DECL_FIELD_OFFSET (t));
889438fd1498Szrj RETURN_TRUE_IF_VAR (DECL_SIZE (t));
889538fd1498Szrj RETURN_TRUE_IF_VAR (DECL_SIZE_UNIT (t));
889638fd1498Szrj
889738fd1498Szrj if (TREE_CODE (type) == QUAL_UNION_TYPE)
889838fd1498Szrj RETURN_TRUE_IF_VAR (DECL_QUALIFIER (t));
889938fd1498Szrj }
890038fd1498Szrj break;
890138fd1498Szrj
890238fd1498Szrj case ARRAY_TYPE:
890338fd1498Szrj /* Do not call ourselves to avoid infinite recursion. This is
890438fd1498Szrj variably modified if the element type is. */
890538fd1498Szrj RETURN_TRUE_IF_VAR (TYPE_SIZE (TREE_TYPE (type)));
890638fd1498Szrj RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT (TREE_TYPE (type)));
890738fd1498Szrj break;
890838fd1498Szrj
890938fd1498Szrj default:
891038fd1498Szrj break;
891138fd1498Szrj }
891238fd1498Szrj
891338fd1498Szrj /* The current language may have other cases to check, but in general,
891438fd1498Szrj all other types are not variably modified. */
891538fd1498Szrj return lang_hooks.tree_inlining.var_mod_type_p (type, fn);
891638fd1498Szrj
891738fd1498Szrj #undef RETURN_TRUE_IF_VAR
891838fd1498Szrj }
891938fd1498Szrj
892038fd1498Szrj /* Given a DECL or TYPE, return the scope in which it was declared, or
892138fd1498Szrj NULL_TREE if there is no containing scope. */
892238fd1498Szrj
892338fd1498Szrj tree
get_containing_scope(const_tree t)892438fd1498Szrj get_containing_scope (const_tree t)
892538fd1498Szrj {
892638fd1498Szrj return (TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t));
892738fd1498Szrj }
892838fd1498Szrj
892938fd1498Szrj /* Returns the ultimate TRANSLATION_UNIT_DECL context of DECL or NULL. */
893038fd1498Szrj
893138fd1498Szrj const_tree
get_ultimate_context(const_tree decl)893238fd1498Szrj get_ultimate_context (const_tree decl)
893338fd1498Szrj {
893438fd1498Szrj while (decl && TREE_CODE (decl) != TRANSLATION_UNIT_DECL)
893538fd1498Szrj {
893638fd1498Szrj if (TREE_CODE (decl) == BLOCK)
893738fd1498Szrj decl = BLOCK_SUPERCONTEXT (decl);
893838fd1498Szrj else
893938fd1498Szrj decl = get_containing_scope (decl);
894038fd1498Szrj }
894138fd1498Szrj return decl;
894238fd1498Szrj }
894338fd1498Szrj
894438fd1498Szrj /* Return the innermost context enclosing DECL that is
894538fd1498Szrj a FUNCTION_DECL, or zero if none. */
894638fd1498Szrj
894738fd1498Szrj tree
decl_function_context(const_tree decl)894838fd1498Szrj decl_function_context (const_tree decl)
894938fd1498Szrj {
895038fd1498Szrj tree context;
895138fd1498Szrj
895238fd1498Szrj if (TREE_CODE (decl) == ERROR_MARK)
895338fd1498Szrj return 0;
895438fd1498Szrj
895538fd1498Szrj /* C++ virtual functions use DECL_CONTEXT for the class of the vtable
895638fd1498Szrj where we look up the function at runtime. Such functions always take
895738fd1498Szrj a first argument of type 'pointer to real context'.
895838fd1498Szrj
895938fd1498Szrj C++ should really be fixed to use DECL_CONTEXT for the real context,
896038fd1498Szrj and use something else for the "virtual context". */
896138fd1498Szrj else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VINDEX (decl))
896238fd1498Szrj context
896338fd1498Szrj = TYPE_MAIN_VARIANT
896438fd1498Szrj (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
896538fd1498Szrj else
896638fd1498Szrj context = DECL_CONTEXT (decl);
896738fd1498Szrj
896838fd1498Szrj while (context && TREE_CODE (context) != FUNCTION_DECL)
896938fd1498Szrj {
897038fd1498Szrj if (TREE_CODE (context) == BLOCK)
897138fd1498Szrj context = BLOCK_SUPERCONTEXT (context);
897238fd1498Szrj else
897338fd1498Szrj context = get_containing_scope (context);
897438fd1498Szrj }
897538fd1498Szrj
897638fd1498Szrj return context;
897738fd1498Szrj }
897838fd1498Szrj
897938fd1498Szrj /* Return the innermost context enclosing DECL that is
898038fd1498Szrj a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE, or zero if none.
898138fd1498Szrj TYPE_DECLs and FUNCTION_DECLs are transparent to this function. */
898238fd1498Szrj
898338fd1498Szrj tree
decl_type_context(const_tree decl)898438fd1498Szrj decl_type_context (const_tree decl)
898538fd1498Szrj {
898638fd1498Szrj tree context = DECL_CONTEXT (decl);
898738fd1498Szrj
898838fd1498Szrj while (context)
898938fd1498Szrj switch (TREE_CODE (context))
899038fd1498Szrj {
899138fd1498Szrj case NAMESPACE_DECL:
899238fd1498Szrj case TRANSLATION_UNIT_DECL:
899338fd1498Szrj return NULL_TREE;
899438fd1498Szrj
899538fd1498Szrj case RECORD_TYPE:
899638fd1498Szrj case UNION_TYPE:
899738fd1498Szrj case QUAL_UNION_TYPE:
899838fd1498Szrj return context;
899938fd1498Szrj
900038fd1498Szrj case TYPE_DECL:
900138fd1498Szrj case FUNCTION_DECL:
900238fd1498Szrj context = DECL_CONTEXT (context);
900338fd1498Szrj break;
900438fd1498Szrj
900538fd1498Szrj case BLOCK:
900638fd1498Szrj context = BLOCK_SUPERCONTEXT (context);
900738fd1498Szrj break;
900838fd1498Szrj
900938fd1498Szrj default:
901038fd1498Szrj gcc_unreachable ();
901138fd1498Szrj }
901238fd1498Szrj
901338fd1498Szrj return NULL_TREE;
901438fd1498Szrj }
901538fd1498Szrj
901638fd1498Szrj /* CALL is a CALL_EXPR. Return the declaration for the function
901738fd1498Szrj called, or NULL_TREE if the called function cannot be
901838fd1498Szrj determined. */
901938fd1498Szrj
902038fd1498Szrj tree
get_callee_fndecl(const_tree call)902138fd1498Szrj get_callee_fndecl (const_tree call)
902238fd1498Szrj {
902338fd1498Szrj tree addr;
902438fd1498Szrj
902538fd1498Szrj if (call == error_mark_node)
902638fd1498Szrj return error_mark_node;
902738fd1498Szrj
902838fd1498Szrj /* It's invalid to call this function with anything but a
902938fd1498Szrj CALL_EXPR. */
903038fd1498Szrj gcc_assert (TREE_CODE (call) == CALL_EXPR);
903138fd1498Szrj
903238fd1498Szrj /* The first operand to the CALL is the address of the function
903338fd1498Szrj called. */
903438fd1498Szrj addr = CALL_EXPR_FN (call);
903538fd1498Szrj
903638fd1498Szrj /* If there is no function, return early. */
903738fd1498Szrj if (addr == NULL_TREE)
903838fd1498Szrj return NULL_TREE;
903938fd1498Szrj
904038fd1498Szrj STRIP_NOPS (addr);
904138fd1498Szrj
904238fd1498Szrj /* If this is a readonly function pointer, extract its initial value. */
904338fd1498Szrj if (DECL_P (addr) && TREE_CODE (addr) != FUNCTION_DECL
904438fd1498Szrj && TREE_READONLY (addr) && ! TREE_THIS_VOLATILE (addr)
904538fd1498Szrj && DECL_INITIAL (addr))
904638fd1498Szrj addr = DECL_INITIAL (addr);
904738fd1498Szrj
904838fd1498Szrj /* If the address is just `&f' for some function `f', then we know
904938fd1498Szrj that `f' is being called. */
905038fd1498Szrj if (TREE_CODE (addr) == ADDR_EXPR
905138fd1498Szrj && TREE_CODE (TREE_OPERAND (addr, 0)) == FUNCTION_DECL)
905238fd1498Szrj return TREE_OPERAND (addr, 0);
905338fd1498Szrj
905438fd1498Szrj /* We couldn't figure out what was being called. */
905538fd1498Szrj return NULL_TREE;
905638fd1498Szrj }
905738fd1498Szrj
905838fd1498Szrj /* If CALL_EXPR CALL calls a normal built-in function or an internal function,
905938fd1498Szrj return the associated function code, otherwise return CFN_LAST. */
906038fd1498Szrj
906138fd1498Szrj combined_fn
get_call_combined_fn(const_tree call)906238fd1498Szrj get_call_combined_fn (const_tree call)
906338fd1498Szrj {
906438fd1498Szrj /* It's invalid to call this function with anything but a CALL_EXPR. */
906538fd1498Szrj gcc_assert (TREE_CODE (call) == CALL_EXPR);
906638fd1498Szrj
906738fd1498Szrj if (!CALL_EXPR_FN (call))
906838fd1498Szrj return as_combined_fn (CALL_EXPR_IFN (call));
906938fd1498Szrj
907038fd1498Szrj tree fndecl = get_callee_fndecl (call);
907138fd1498Szrj if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
907238fd1498Szrj return as_combined_fn (DECL_FUNCTION_CODE (fndecl));
907338fd1498Szrj
907438fd1498Szrj return CFN_LAST;
907538fd1498Szrj }
907638fd1498Szrj
907738fd1498Szrj #define TREE_MEM_USAGE_SPACES 40
907838fd1498Szrj
907938fd1498Szrj /* Print debugging information about tree nodes generated during the compile,
908038fd1498Szrj and any language-specific information. */
908138fd1498Szrj
908238fd1498Szrj void
dump_tree_statistics(void)908338fd1498Szrj dump_tree_statistics (void)
908438fd1498Szrj {
908538fd1498Szrj if (GATHER_STATISTICS)
908638fd1498Szrj {
908738fd1498Szrj int i;
908838fd1498Szrj uint64_t total_nodes, total_bytes;
908938fd1498Szrj fprintf (stderr, "\nKind Nodes Bytes\n");
909038fd1498Szrj mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
909138fd1498Szrj total_nodes = total_bytes = 0;
909238fd1498Szrj for (i = 0; i < (int) all_kinds; i++)
909338fd1498Szrj {
909438fd1498Szrj fprintf (stderr, "%-20s %7" PRIu64 " %10" PRIu64 "\n",
909538fd1498Szrj tree_node_kind_names[i], tree_node_counts[i],
909638fd1498Szrj tree_node_sizes[i]);
909738fd1498Szrj total_nodes += tree_node_counts[i];
909838fd1498Szrj total_bytes += tree_node_sizes[i];
909938fd1498Szrj }
910038fd1498Szrj mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
910138fd1498Szrj fprintf (stderr, "%-20s %7" PRIu64 " %10" PRIu64 "\n", "Total",
910238fd1498Szrj total_nodes, total_bytes);
910338fd1498Szrj mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
910438fd1498Szrj fprintf (stderr, "Code Nodes\n");
910538fd1498Szrj mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
910638fd1498Szrj for (i = 0; i < (int) MAX_TREE_CODES; i++)
910738fd1498Szrj fprintf (stderr, "%-32s %7" PRIu64 "\n",
910838fd1498Szrj get_tree_code_name ((enum tree_code) i), tree_code_counts[i]);
910938fd1498Szrj mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
911038fd1498Szrj fprintf (stderr, "\n");
911138fd1498Szrj ssanames_print_statistics ();
911238fd1498Szrj fprintf (stderr, "\n");
911338fd1498Szrj phinodes_print_statistics ();
911438fd1498Szrj fprintf (stderr, "\n");
911538fd1498Szrj }
911638fd1498Szrj else
911738fd1498Szrj fprintf (stderr, "(No per-node statistics)\n");
911838fd1498Szrj
911938fd1498Szrj print_type_hash_statistics ();
912038fd1498Szrj print_debug_expr_statistics ();
912138fd1498Szrj print_value_expr_statistics ();
912238fd1498Szrj lang_hooks.print_statistics ();
912338fd1498Szrj }
912438fd1498Szrj
912538fd1498Szrj #define FILE_FUNCTION_FORMAT "_GLOBAL__%s_%s"
912638fd1498Szrj
912738fd1498Szrj /* Generate a crc32 of the low BYTES bytes of VALUE. */
912838fd1498Szrj
912938fd1498Szrj unsigned
crc32_unsigned_n(unsigned chksum,unsigned value,unsigned bytes)913038fd1498Szrj crc32_unsigned_n (unsigned chksum, unsigned value, unsigned bytes)
913138fd1498Szrj {
913238fd1498Szrj /* This relies on the raw feedback's top 4 bits being zero. */
913338fd1498Szrj #define FEEDBACK(X) ((X) * 0x04c11db7)
913438fd1498Szrj #define SYNDROME(X) (FEEDBACK ((X) & 1) ^ FEEDBACK ((X) & 2) \
913538fd1498Szrj ^ FEEDBACK ((X) & 4) ^ FEEDBACK ((X) & 8))
913638fd1498Szrj static const unsigned syndromes[16] =
913738fd1498Szrj {
913838fd1498Szrj SYNDROME(0x0), SYNDROME(0x1), SYNDROME(0x2), SYNDROME(0x3),
913938fd1498Szrj SYNDROME(0x4), SYNDROME(0x5), SYNDROME(0x6), SYNDROME(0x7),
914038fd1498Szrj SYNDROME(0x8), SYNDROME(0x9), SYNDROME(0xa), SYNDROME(0xb),
914138fd1498Szrj SYNDROME(0xc), SYNDROME(0xd), SYNDROME(0xe), SYNDROME(0xf),
914238fd1498Szrj };
914338fd1498Szrj #undef FEEDBACK
914438fd1498Szrj #undef SYNDROME
914538fd1498Szrj
914638fd1498Szrj value <<= (32 - bytes * 8);
914738fd1498Szrj for (unsigned ix = bytes * 2; ix--; value <<= 4)
914838fd1498Szrj {
914938fd1498Szrj unsigned feedback = syndromes[((value ^ chksum) >> 28) & 0xf];
915038fd1498Szrj
915138fd1498Szrj chksum = (chksum << 4) ^ feedback;
915238fd1498Szrj }
915338fd1498Szrj
915438fd1498Szrj return chksum;
915538fd1498Szrj }
915638fd1498Szrj
915738fd1498Szrj /* Generate a crc32 of a string. */
915838fd1498Szrj
915938fd1498Szrj unsigned
crc32_string(unsigned chksum,const char * string)916038fd1498Szrj crc32_string (unsigned chksum, const char *string)
916138fd1498Szrj {
916238fd1498Szrj do
916338fd1498Szrj chksum = crc32_byte (chksum, *string);
916438fd1498Szrj while (*string++);
916538fd1498Szrj return chksum;
916638fd1498Szrj }
916738fd1498Szrj
916838fd1498Szrj /* P is a string that will be used in a symbol. Mask out any characters
916938fd1498Szrj that are not valid in that context. */
917038fd1498Szrj
917138fd1498Szrj void
clean_symbol_name(char * p)917238fd1498Szrj clean_symbol_name (char *p)
917338fd1498Szrj {
917438fd1498Szrj for (; *p; p++)
917538fd1498Szrj if (! (ISALNUM (*p)
917638fd1498Szrj #ifndef NO_DOLLAR_IN_LABEL /* this for `$'; unlikely, but... -- kr */
917738fd1498Szrj || *p == '$'
917838fd1498Szrj #endif
917938fd1498Szrj #ifndef NO_DOT_IN_LABEL /* this for `.'; unlikely, but... */
918038fd1498Szrj || *p == '.'
918138fd1498Szrj #endif
918238fd1498Szrj ))
918338fd1498Szrj *p = '_';
918438fd1498Szrj }
918538fd1498Szrj
918638fd1498Szrj /* For anonymous aggregate types, we need some sort of name to
918738fd1498Szrj hold on to. In practice, this should not appear, but it should
918838fd1498Szrj not be harmful if it does. */
918938fd1498Szrj bool
anon_aggrname_p(const_tree id_node)919038fd1498Szrj anon_aggrname_p(const_tree id_node)
919138fd1498Szrj {
919238fd1498Szrj #ifndef NO_DOT_IN_LABEL
919338fd1498Szrj return (IDENTIFIER_POINTER (id_node)[0] == '.'
919438fd1498Szrj && IDENTIFIER_POINTER (id_node)[1] == '_');
919538fd1498Szrj #else /* NO_DOT_IN_LABEL */
919638fd1498Szrj #ifndef NO_DOLLAR_IN_LABEL
919738fd1498Szrj return (IDENTIFIER_POINTER (id_node)[0] == '$' \
919838fd1498Szrj && IDENTIFIER_POINTER (id_node)[1] == '_');
919938fd1498Szrj #else /* NO_DOLLAR_IN_LABEL */
920038fd1498Szrj #define ANON_AGGRNAME_PREFIX "__anon_"
920138fd1498Szrj return (!strncmp (IDENTIFIER_POINTER (id_node), ANON_AGGRNAME_PREFIX,
920238fd1498Szrj sizeof (ANON_AGGRNAME_PREFIX) - 1));
920338fd1498Szrj #endif /* NO_DOLLAR_IN_LABEL */
920438fd1498Szrj #endif /* NO_DOT_IN_LABEL */
920538fd1498Szrj }
920638fd1498Szrj
920738fd1498Szrj /* Return a format for an anonymous aggregate name. */
920838fd1498Szrj const char *
anon_aggrname_format()920938fd1498Szrj anon_aggrname_format()
921038fd1498Szrj {
921138fd1498Szrj #ifndef NO_DOT_IN_LABEL
921238fd1498Szrj return "._%d";
921338fd1498Szrj #else /* NO_DOT_IN_LABEL */
921438fd1498Szrj #ifndef NO_DOLLAR_IN_LABEL
921538fd1498Szrj return "$_%d";
921638fd1498Szrj #else /* NO_DOLLAR_IN_LABEL */
921738fd1498Szrj return "__anon_%d";
921838fd1498Szrj #endif /* NO_DOLLAR_IN_LABEL */
921938fd1498Szrj #endif /* NO_DOT_IN_LABEL */
922038fd1498Szrj }
922138fd1498Szrj
922238fd1498Szrj /* Generate a name for a special-purpose function.
922338fd1498Szrj The generated name may need to be unique across the whole link.
922438fd1498Szrj Changes to this function may also require corresponding changes to
922538fd1498Szrj xstrdup_mask_random.
922638fd1498Szrj TYPE is some string to identify the purpose of this function to the
922738fd1498Szrj linker or collect2; it must start with an uppercase letter,
922838fd1498Szrj one of:
922938fd1498Szrj I - for constructors
923038fd1498Szrj D - for destructors
923138fd1498Szrj N - for C++ anonymous namespaces
923238fd1498Szrj F - for DWARF unwind frame information. */
923338fd1498Szrj
923438fd1498Szrj tree
get_file_function_name(const char * type)923538fd1498Szrj get_file_function_name (const char *type)
923638fd1498Szrj {
923738fd1498Szrj char *buf;
923838fd1498Szrj const char *p;
923938fd1498Szrj char *q;
924038fd1498Szrj
924138fd1498Szrj /* If we already have a name we know to be unique, just use that. */
924238fd1498Szrj if (first_global_object_name)
924338fd1498Szrj p = q = ASTRDUP (first_global_object_name);
924438fd1498Szrj /* If the target is handling the constructors/destructors, they
924538fd1498Szrj will be local to this file and the name is only necessary for
924638fd1498Szrj debugging purposes.
924738fd1498Szrj We also assign sub_I and sub_D sufixes to constructors called from
924838fd1498Szrj the global static constructors. These are always local. */
924938fd1498Szrj else if (((type[0] == 'I' || type[0] == 'D') && targetm.have_ctors_dtors)
925038fd1498Szrj || (strncmp (type, "sub_", 4) == 0
925138fd1498Szrj && (type[4] == 'I' || type[4] == 'D')))
925238fd1498Szrj {
925338fd1498Szrj const char *file = main_input_filename;
925438fd1498Szrj if (! file)
925538fd1498Szrj file = LOCATION_FILE (input_location);
925638fd1498Szrj /* Just use the file's basename, because the full pathname
925738fd1498Szrj might be quite long. */
925838fd1498Szrj p = q = ASTRDUP (lbasename (file));
925938fd1498Szrj }
926038fd1498Szrj else
926138fd1498Szrj {
926238fd1498Szrj /* Otherwise, the name must be unique across the entire link.
926338fd1498Szrj We don't have anything that we know to be unique to this translation
926438fd1498Szrj unit, so use what we do have and throw in some randomness. */
926538fd1498Szrj unsigned len;
926638fd1498Szrj const char *name = weak_global_object_name;
926738fd1498Szrj const char *file = main_input_filename;
926838fd1498Szrj
926938fd1498Szrj if (! name)
927038fd1498Szrj name = "";
927138fd1498Szrj if (! file)
927238fd1498Szrj file = LOCATION_FILE (input_location);
927338fd1498Szrj
927438fd1498Szrj len = strlen (file);
927538fd1498Szrj q = (char *) alloca (9 + 19 + len + 1);
927638fd1498Szrj memcpy (q, file, len + 1);
927738fd1498Szrj
927838fd1498Szrj snprintf (q + len, 9 + 19 + 1, "_%08X_" HOST_WIDE_INT_PRINT_HEX,
927938fd1498Szrj crc32_string (0, name), get_random_seed (false));
928038fd1498Szrj
928138fd1498Szrj p = q;
928238fd1498Szrj }
928338fd1498Szrj
928438fd1498Szrj clean_symbol_name (q);
928538fd1498Szrj buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p)
928638fd1498Szrj + strlen (type));
928738fd1498Szrj
928838fd1498Szrj /* Set up the name of the file-level functions we may need.
928938fd1498Szrj Use a global object (which is already required to be unique over
929038fd1498Szrj the program) rather than the file name (which imposes extra
929138fd1498Szrj constraints). */
929238fd1498Szrj sprintf (buf, FILE_FUNCTION_FORMAT, type, p);
929338fd1498Szrj
929438fd1498Szrj return get_identifier (buf);
929538fd1498Szrj }
929638fd1498Szrj
929738fd1498Szrj #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
929838fd1498Szrj
929938fd1498Szrj /* Complain that the tree code of NODE does not match the expected 0
930038fd1498Szrj terminated list of trailing codes. The trailing code list can be
930138fd1498Szrj empty, for a more vague error message. FILE, LINE, and FUNCTION
930238fd1498Szrj are of the caller. */
930338fd1498Szrj
930438fd1498Szrj void
tree_check_failed(const_tree node,const char * file,int line,const char * function,...)930538fd1498Szrj tree_check_failed (const_tree node, const char *file,
930638fd1498Szrj int line, const char *function, ...)
930738fd1498Szrj {
930838fd1498Szrj va_list args;
930938fd1498Szrj const char *buffer;
931038fd1498Szrj unsigned length = 0;
931138fd1498Szrj enum tree_code code;
931238fd1498Szrj
931338fd1498Szrj va_start (args, function);
931438fd1498Szrj while ((code = (enum tree_code) va_arg (args, int)))
931538fd1498Szrj length += 4 + strlen (get_tree_code_name (code));
931638fd1498Szrj va_end (args);
931738fd1498Szrj if (length)
931838fd1498Szrj {
931938fd1498Szrj char *tmp;
932038fd1498Szrj va_start (args, function);
932138fd1498Szrj length += strlen ("expected ");
932238fd1498Szrj buffer = tmp = (char *) alloca (length);
932338fd1498Szrj length = 0;
932438fd1498Szrj while ((code = (enum tree_code) va_arg (args, int)))
932538fd1498Szrj {
932638fd1498Szrj const char *prefix = length ? " or " : "expected ";
932738fd1498Szrj
932838fd1498Szrj strcpy (tmp + length, prefix);
932938fd1498Szrj length += strlen (prefix);
933038fd1498Szrj strcpy (tmp + length, get_tree_code_name (code));
933138fd1498Szrj length += strlen (get_tree_code_name (code));
933238fd1498Szrj }
933338fd1498Szrj va_end (args);
933438fd1498Szrj }
933538fd1498Szrj else
933638fd1498Szrj buffer = "unexpected node";
933738fd1498Szrj
933838fd1498Szrj internal_error ("tree check: %s, have %s in %s, at %s:%d",
933938fd1498Szrj buffer, get_tree_code_name (TREE_CODE (node)),
934038fd1498Szrj function, trim_filename (file), line);
934138fd1498Szrj }
934238fd1498Szrj
934338fd1498Szrj /* Complain that the tree code of NODE does match the expected 0
934438fd1498Szrj terminated list of trailing codes. FILE, LINE, and FUNCTION are of
934538fd1498Szrj the caller. */
934638fd1498Szrj
934738fd1498Szrj void
tree_not_check_failed(const_tree node,const char * file,int line,const char * function,...)934838fd1498Szrj tree_not_check_failed (const_tree node, const char *file,
934938fd1498Szrj int line, const char *function, ...)
935038fd1498Szrj {
935138fd1498Szrj va_list args;
935238fd1498Szrj char *buffer;
935338fd1498Szrj unsigned length = 0;
935438fd1498Szrj enum tree_code code;
935538fd1498Szrj
935638fd1498Szrj va_start (args, function);
935738fd1498Szrj while ((code = (enum tree_code) va_arg (args, int)))
935838fd1498Szrj length += 4 + strlen (get_tree_code_name (code));
935938fd1498Szrj va_end (args);
936038fd1498Szrj va_start (args, function);
936138fd1498Szrj buffer = (char *) alloca (length);
936238fd1498Szrj length = 0;
936338fd1498Szrj while ((code = (enum tree_code) va_arg (args, int)))
936438fd1498Szrj {
936538fd1498Szrj if (length)
936638fd1498Szrj {
936738fd1498Szrj strcpy (buffer + length, " or ");
936838fd1498Szrj length += 4;
936938fd1498Szrj }
937038fd1498Szrj strcpy (buffer + length, get_tree_code_name (code));
937138fd1498Szrj length += strlen (get_tree_code_name (code));
937238fd1498Szrj }
937338fd1498Szrj va_end (args);
937438fd1498Szrj
937538fd1498Szrj internal_error ("tree check: expected none of %s, have %s in %s, at %s:%d",
937638fd1498Szrj buffer, get_tree_code_name (TREE_CODE (node)),
937738fd1498Szrj function, trim_filename (file), line);
937838fd1498Szrj }
937938fd1498Szrj
938038fd1498Szrj /* Similar to tree_check_failed, except that we check for a class of tree
938138fd1498Szrj code, given in CL. */
938238fd1498Szrj
938338fd1498Szrj void
tree_class_check_failed(const_tree node,const enum tree_code_class cl,const char * file,int line,const char * function)938438fd1498Szrj tree_class_check_failed (const_tree node, const enum tree_code_class cl,
938538fd1498Szrj const char *file, int line, const char *function)
938638fd1498Szrj {
938738fd1498Szrj internal_error
938838fd1498Szrj ("tree check: expected class %qs, have %qs (%s) in %s, at %s:%d",
938938fd1498Szrj TREE_CODE_CLASS_STRING (cl),
939038fd1498Szrj TREE_CODE_CLASS_STRING (TREE_CODE_CLASS (TREE_CODE (node))),
939138fd1498Szrj get_tree_code_name (TREE_CODE (node)), function, trim_filename (file), line);
939238fd1498Szrj }
939338fd1498Szrj
939438fd1498Szrj /* Similar to tree_check_failed, except that instead of specifying a
939538fd1498Szrj dozen codes, use the knowledge that they're all sequential. */
939638fd1498Szrj
939738fd1498Szrj void
tree_range_check_failed(const_tree node,const char * file,int line,const char * function,enum tree_code c1,enum tree_code c2)939838fd1498Szrj tree_range_check_failed (const_tree node, const char *file, int line,
939938fd1498Szrj const char *function, enum tree_code c1,
940038fd1498Szrj enum tree_code c2)
940138fd1498Szrj {
940238fd1498Szrj char *buffer;
940338fd1498Szrj unsigned length = 0;
940438fd1498Szrj unsigned int c;
940538fd1498Szrj
940638fd1498Szrj for (c = c1; c <= c2; ++c)
940738fd1498Szrj length += 4 + strlen (get_tree_code_name ((enum tree_code) c));
940838fd1498Szrj
940938fd1498Szrj length += strlen ("expected ");
941038fd1498Szrj buffer = (char *) alloca (length);
941138fd1498Szrj length = 0;
941238fd1498Szrj
941338fd1498Szrj for (c = c1; c <= c2; ++c)
941438fd1498Szrj {
941538fd1498Szrj const char *prefix = length ? " or " : "expected ";
941638fd1498Szrj
941738fd1498Szrj strcpy (buffer + length, prefix);
941838fd1498Szrj length += strlen (prefix);
941938fd1498Szrj strcpy (buffer + length, get_tree_code_name ((enum tree_code) c));
942038fd1498Szrj length += strlen (get_tree_code_name ((enum tree_code) c));
942138fd1498Szrj }
942238fd1498Szrj
942338fd1498Szrj internal_error ("tree check: %s, have %s in %s, at %s:%d",
942438fd1498Szrj buffer, get_tree_code_name (TREE_CODE (node)),
942538fd1498Szrj function, trim_filename (file), line);
942638fd1498Szrj }
942738fd1498Szrj
942838fd1498Szrj
942938fd1498Szrj /* Similar to tree_check_failed, except that we check that a tree does
943038fd1498Szrj not have the specified code, given in CL. */
943138fd1498Szrj
943238fd1498Szrj void
tree_not_class_check_failed(const_tree node,const enum tree_code_class cl,const char * file,int line,const char * function)943338fd1498Szrj tree_not_class_check_failed (const_tree node, const enum tree_code_class cl,
943438fd1498Szrj const char *file, int line, const char *function)
943538fd1498Szrj {
943638fd1498Szrj internal_error
943738fd1498Szrj ("tree check: did not expect class %qs, have %qs (%s) in %s, at %s:%d",
943838fd1498Szrj TREE_CODE_CLASS_STRING (cl),
943938fd1498Szrj TREE_CODE_CLASS_STRING (TREE_CODE_CLASS (TREE_CODE (node))),
944038fd1498Szrj get_tree_code_name (TREE_CODE (node)), function, trim_filename (file), line);
944138fd1498Szrj }
944238fd1498Szrj
944338fd1498Szrj
944438fd1498Szrj /* Similar to tree_check_failed but applied to OMP_CLAUSE codes. */
944538fd1498Szrj
944638fd1498Szrj void
omp_clause_check_failed(const_tree node,const char * file,int line,const char * function,enum omp_clause_code code)944738fd1498Szrj omp_clause_check_failed (const_tree node, const char *file, int line,
944838fd1498Szrj const char *function, enum omp_clause_code code)
944938fd1498Szrj {
945038fd1498Szrj internal_error ("tree check: expected omp_clause %s, have %s in %s, at %s:%d",
945138fd1498Szrj omp_clause_code_name[code], get_tree_code_name (TREE_CODE (node)),
945238fd1498Szrj function, trim_filename (file), line);
945338fd1498Szrj }
945438fd1498Szrj
945538fd1498Szrj
945638fd1498Szrj /* Similar to tree_range_check_failed but applied to OMP_CLAUSE codes. */
945738fd1498Szrj
945838fd1498Szrj void
omp_clause_range_check_failed(const_tree node,const char * file,int line,const char * function,enum omp_clause_code c1,enum omp_clause_code c2)945938fd1498Szrj omp_clause_range_check_failed (const_tree node, const char *file, int line,
946038fd1498Szrj const char *function, enum omp_clause_code c1,
946138fd1498Szrj enum omp_clause_code c2)
946238fd1498Szrj {
946338fd1498Szrj char *buffer;
946438fd1498Szrj unsigned length = 0;
946538fd1498Szrj unsigned int c;
946638fd1498Szrj
946738fd1498Szrj for (c = c1; c <= c2; ++c)
946838fd1498Szrj length += 4 + strlen (omp_clause_code_name[c]);
946938fd1498Szrj
947038fd1498Szrj length += strlen ("expected ");
947138fd1498Szrj buffer = (char *) alloca (length);
947238fd1498Szrj length = 0;
947338fd1498Szrj
947438fd1498Szrj for (c = c1; c <= c2; ++c)
947538fd1498Szrj {
947638fd1498Szrj const char *prefix = length ? " or " : "expected ";
947738fd1498Szrj
947838fd1498Szrj strcpy (buffer + length, prefix);
947938fd1498Szrj length += strlen (prefix);
948038fd1498Szrj strcpy (buffer + length, omp_clause_code_name[c]);
948138fd1498Szrj length += strlen (omp_clause_code_name[c]);
948238fd1498Szrj }
948338fd1498Szrj
948438fd1498Szrj internal_error ("tree check: %s, have %s in %s, at %s:%d",
948538fd1498Szrj buffer, omp_clause_code_name[TREE_CODE (node)],
948638fd1498Szrj function, trim_filename (file), line);
948738fd1498Szrj }
948838fd1498Szrj
948938fd1498Szrj
949038fd1498Szrj #undef DEFTREESTRUCT
949138fd1498Szrj #define DEFTREESTRUCT(VAL, NAME) NAME,
949238fd1498Szrj
949338fd1498Szrj static const char *ts_enum_names[] = {
949438fd1498Szrj #include "treestruct.def"
949538fd1498Szrj };
949638fd1498Szrj #undef DEFTREESTRUCT
949738fd1498Szrj
949838fd1498Szrj #define TS_ENUM_NAME(EN) (ts_enum_names[(EN)])
949938fd1498Szrj
950038fd1498Szrj /* Similar to tree_class_check_failed, except that we check for
950138fd1498Szrj whether CODE contains the tree structure identified by EN. */
950238fd1498Szrj
950338fd1498Szrj void
tree_contains_struct_check_failed(const_tree node,const enum tree_node_structure_enum en,const char * file,int line,const char * function)950438fd1498Szrj tree_contains_struct_check_failed (const_tree node,
950538fd1498Szrj const enum tree_node_structure_enum en,
950638fd1498Szrj const char *file, int line,
950738fd1498Szrj const char *function)
950838fd1498Szrj {
950938fd1498Szrj internal_error
951038fd1498Szrj ("tree check: expected tree that contains %qs structure, have %qs in %s, at %s:%d",
951138fd1498Szrj TS_ENUM_NAME (en),
951238fd1498Szrj get_tree_code_name (TREE_CODE (node)), function, trim_filename (file), line);
951338fd1498Szrj }
951438fd1498Szrj
951538fd1498Szrj
951638fd1498Szrj /* Similar to above, except that the check is for the bounds of a TREE_VEC's
951738fd1498Szrj (dynamically sized) vector. */
951838fd1498Szrj
951938fd1498Szrj void
tree_int_cst_elt_check_failed(int idx,int len,const char * file,int line,const char * function)952038fd1498Szrj tree_int_cst_elt_check_failed (int idx, int len, const char *file, int line,
952138fd1498Szrj const char *function)
952238fd1498Szrj {
952338fd1498Szrj internal_error
952438fd1498Szrj ("tree check: accessed elt %d of tree_int_cst with %d elts in %s, at %s:%d",
952538fd1498Szrj idx + 1, len, function, trim_filename (file), line);
952638fd1498Szrj }
952738fd1498Szrj
952838fd1498Szrj /* Similar to above, except that the check is for the bounds of a TREE_VEC's
952938fd1498Szrj (dynamically sized) vector. */
953038fd1498Szrj
953138fd1498Szrj void
tree_vec_elt_check_failed(int idx,int len,const char * file,int line,const char * function)953238fd1498Szrj tree_vec_elt_check_failed (int idx, int len, const char *file, int line,
953338fd1498Szrj const char *function)
953438fd1498Szrj {
953538fd1498Szrj internal_error
953638fd1498Szrj ("tree check: accessed elt %d of tree_vec with %d elts in %s, at %s:%d",
953738fd1498Szrj idx + 1, len, function, trim_filename (file), line);
953838fd1498Szrj }
953938fd1498Szrj
954038fd1498Szrj /* Similar to above, except that the check is for the bounds of the operand
954138fd1498Szrj vector of an expression node EXP. */
954238fd1498Szrj
954338fd1498Szrj void
tree_operand_check_failed(int idx,const_tree exp,const char * file,int line,const char * function)954438fd1498Szrj tree_operand_check_failed (int idx, const_tree exp, const char *file,
954538fd1498Szrj int line, const char *function)
954638fd1498Szrj {
954738fd1498Szrj enum tree_code code = TREE_CODE (exp);
954838fd1498Szrj internal_error
954938fd1498Szrj ("tree check: accessed operand %d of %s with %d operands in %s, at %s:%d",
955038fd1498Szrj idx + 1, get_tree_code_name (code), TREE_OPERAND_LENGTH (exp),
955138fd1498Szrj function, trim_filename (file), line);
955238fd1498Szrj }
955338fd1498Szrj
955438fd1498Szrj /* Similar to above, except that the check is for the number of
955538fd1498Szrj operands of an OMP_CLAUSE node. */
955638fd1498Szrj
955738fd1498Szrj void
omp_clause_operand_check_failed(int idx,const_tree t,const char * file,int line,const char * function)955838fd1498Szrj omp_clause_operand_check_failed (int idx, const_tree t, const char *file,
955938fd1498Szrj int line, const char *function)
956038fd1498Szrj {
956138fd1498Szrj internal_error
956238fd1498Szrj ("tree check: accessed operand %d of omp_clause %s with %d operands "
956338fd1498Szrj "in %s, at %s:%d", idx + 1, omp_clause_code_name[OMP_CLAUSE_CODE (t)],
956438fd1498Szrj omp_clause_num_ops [OMP_CLAUSE_CODE (t)], function,
956538fd1498Szrj trim_filename (file), line);
956638fd1498Szrj }
956738fd1498Szrj #endif /* ENABLE_TREE_CHECKING */
956838fd1498Szrj
956938fd1498Szrj /* Create a new vector type node holding NUNITS units of type INNERTYPE,
957038fd1498Szrj and mapped to the machine mode MODE. Initialize its fields and build
957138fd1498Szrj the information necessary for debugging output. */
957238fd1498Szrj
957338fd1498Szrj static tree
make_vector_type(tree innertype,poly_int64 nunits,machine_mode mode)957438fd1498Szrj make_vector_type (tree innertype, poly_int64 nunits, machine_mode mode)
957538fd1498Szrj {
957638fd1498Szrj tree t;
957738fd1498Szrj tree mv_innertype = TYPE_MAIN_VARIANT (innertype);
957838fd1498Szrj
957938fd1498Szrj t = make_node (VECTOR_TYPE);
958038fd1498Szrj TREE_TYPE (t) = mv_innertype;
958138fd1498Szrj SET_TYPE_VECTOR_SUBPARTS (t, nunits);
958238fd1498Szrj SET_TYPE_MODE (t, mode);
958338fd1498Szrj
958438fd1498Szrj if (TYPE_STRUCTURAL_EQUALITY_P (mv_innertype) || in_lto_p)
958538fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (t);
958638fd1498Szrj else if ((TYPE_CANONICAL (mv_innertype) != innertype
958738fd1498Szrj || mode != VOIDmode)
958838fd1498Szrj && !VECTOR_BOOLEAN_TYPE_P (t))
958938fd1498Szrj TYPE_CANONICAL (t)
959038fd1498Szrj = make_vector_type (TYPE_CANONICAL (mv_innertype), nunits, VOIDmode);
959138fd1498Szrj
959238fd1498Szrj layout_type (t);
959338fd1498Szrj
959438fd1498Szrj hashval_t hash = type_hash_canon_hash (t);
959538fd1498Szrj t = type_hash_canon (hash, t);
959638fd1498Szrj
959738fd1498Szrj /* We have built a main variant, based on the main variant of the
959838fd1498Szrj inner type. Use it to build the variant we return. */
959938fd1498Szrj if ((TYPE_ATTRIBUTES (innertype) || TYPE_QUALS (innertype))
960038fd1498Szrj && TREE_TYPE (t) != innertype)
960138fd1498Szrj return build_type_attribute_qual_variant (t,
960238fd1498Szrj TYPE_ATTRIBUTES (innertype),
960338fd1498Szrj TYPE_QUALS (innertype));
960438fd1498Szrj
960538fd1498Szrj return t;
960638fd1498Szrj }
960738fd1498Szrj
960838fd1498Szrj static tree
make_or_reuse_type(unsigned size,int unsignedp)960938fd1498Szrj make_or_reuse_type (unsigned size, int unsignedp)
961038fd1498Szrj {
961138fd1498Szrj int i;
961238fd1498Szrj
961338fd1498Szrj if (size == INT_TYPE_SIZE)
961438fd1498Szrj return unsignedp ? unsigned_type_node : integer_type_node;
961538fd1498Szrj if (size == CHAR_TYPE_SIZE)
961638fd1498Szrj return unsignedp ? unsigned_char_type_node : signed_char_type_node;
961738fd1498Szrj if (size == SHORT_TYPE_SIZE)
961838fd1498Szrj return unsignedp ? short_unsigned_type_node : short_integer_type_node;
961938fd1498Szrj if (size == LONG_TYPE_SIZE)
962038fd1498Szrj return unsignedp ? long_unsigned_type_node : long_integer_type_node;
962138fd1498Szrj if (size == LONG_LONG_TYPE_SIZE)
962238fd1498Szrj return (unsignedp ? long_long_unsigned_type_node
962338fd1498Szrj : long_long_integer_type_node);
962438fd1498Szrj
962538fd1498Szrj for (i = 0; i < NUM_INT_N_ENTS; i ++)
962638fd1498Szrj if (size == int_n_data[i].bitsize
962738fd1498Szrj && int_n_enabled_p[i])
962838fd1498Szrj return (unsignedp ? int_n_trees[i].unsigned_type
962938fd1498Szrj : int_n_trees[i].signed_type);
963038fd1498Szrj
963138fd1498Szrj if (unsignedp)
963238fd1498Szrj return make_unsigned_type (size);
963338fd1498Szrj else
963438fd1498Szrj return make_signed_type (size);
963538fd1498Szrj }
963638fd1498Szrj
963738fd1498Szrj /* Create or reuse a fract type by SIZE, UNSIGNEDP, and SATP. */
963838fd1498Szrj
963938fd1498Szrj static tree
make_or_reuse_fract_type(unsigned size,int unsignedp,int satp)964038fd1498Szrj make_or_reuse_fract_type (unsigned size, int unsignedp, int satp)
964138fd1498Szrj {
964238fd1498Szrj if (satp)
964338fd1498Szrj {
964438fd1498Szrj if (size == SHORT_FRACT_TYPE_SIZE)
964538fd1498Szrj return unsignedp ? sat_unsigned_short_fract_type_node
964638fd1498Szrj : sat_short_fract_type_node;
964738fd1498Szrj if (size == FRACT_TYPE_SIZE)
964838fd1498Szrj return unsignedp ? sat_unsigned_fract_type_node : sat_fract_type_node;
964938fd1498Szrj if (size == LONG_FRACT_TYPE_SIZE)
965038fd1498Szrj return unsignedp ? sat_unsigned_long_fract_type_node
965138fd1498Szrj : sat_long_fract_type_node;
965238fd1498Szrj if (size == LONG_LONG_FRACT_TYPE_SIZE)
965338fd1498Szrj return unsignedp ? sat_unsigned_long_long_fract_type_node
965438fd1498Szrj : sat_long_long_fract_type_node;
965538fd1498Szrj }
965638fd1498Szrj else
965738fd1498Szrj {
965838fd1498Szrj if (size == SHORT_FRACT_TYPE_SIZE)
965938fd1498Szrj return unsignedp ? unsigned_short_fract_type_node
966038fd1498Szrj : short_fract_type_node;
966138fd1498Szrj if (size == FRACT_TYPE_SIZE)
966238fd1498Szrj return unsignedp ? unsigned_fract_type_node : fract_type_node;
966338fd1498Szrj if (size == LONG_FRACT_TYPE_SIZE)
966438fd1498Szrj return unsignedp ? unsigned_long_fract_type_node
966538fd1498Szrj : long_fract_type_node;
966638fd1498Szrj if (size == LONG_LONG_FRACT_TYPE_SIZE)
966738fd1498Szrj return unsignedp ? unsigned_long_long_fract_type_node
966838fd1498Szrj : long_long_fract_type_node;
966938fd1498Szrj }
967038fd1498Szrj
967138fd1498Szrj return make_fract_type (size, unsignedp, satp);
967238fd1498Szrj }
967338fd1498Szrj
967438fd1498Szrj /* Create or reuse an accum type by SIZE, UNSIGNEDP, and SATP. */
967538fd1498Szrj
967638fd1498Szrj static tree
make_or_reuse_accum_type(unsigned size,int unsignedp,int satp)967738fd1498Szrj make_or_reuse_accum_type (unsigned size, int unsignedp, int satp)
967838fd1498Szrj {
967938fd1498Szrj if (satp)
968038fd1498Szrj {
968138fd1498Szrj if (size == SHORT_ACCUM_TYPE_SIZE)
968238fd1498Szrj return unsignedp ? sat_unsigned_short_accum_type_node
968338fd1498Szrj : sat_short_accum_type_node;
968438fd1498Szrj if (size == ACCUM_TYPE_SIZE)
968538fd1498Szrj return unsignedp ? sat_unsigned_accum_type_node : sat_accum_type_node;
968638fd1498Szrj if (size == LONG_ACCUM_TYPE_SIZE)
968738fd1498Szrj return unsignedp ? sat_unsigned_long_accum_type_node
968838fd1498Szrj : sat_long_accum_type_node;
968938fd1498Szrj if (size == LONG_LONG_ACCUM_TYPE_SIZE)
969038fd1498Szrj return unsignedp ? sat_unsigned_long_long_accum_type_node
969138fd1498Szrj : sat_long_long_accum_type_node;
969238fd1498Szrj }
969338fd1498Szrj else
969438fd1498Szrj {
969538fd1498Szrj if (size == SHORT_ACCUM_TYPE_SIZE)
969638fd1498Szrj return unsignedp ? unsigned_short_accum_type_node
969738fd1498Szrj : short_accum_type_node;
969838fd1498Szrj if (size == ACCUM_TYPE_SIZE)
969938fd1498Szrj return unsignedp ? unsigned_accum_type_node : accum_type_node;
970038fd1498Szrj if (size == LONG_ACCUM_TYPE_SIZE)
970138fd1498Szrj return unsignedp ? unsigned_long_accum_type_node
970238fd1498Szrj : long_accum_type_node;
970338fd1498Szrj if (size == LONG_LONG_ACCUM_TYPE_SIZE)
970438fd1498Szrj return unsignedp ? unsigned_long_long_accum_type_node
970538fd1498Szrj : long_long_accum_type_node;
970638fd1498Szrj }
970738fd1498Szrj
970838fd1498Szrj return make_accum_type (size, unsignedp, satp);
970938fd1498Szrj }
971038fd1498Szrj
971138fd1498Szrj
971238fd1498Szrj /* Create an atomic variant node for TYPE. This routine is called
971338fd1498Szrj during initialization of data types to create the 5 basic atomic
971438fd1498Szrj types. The generic build_variant_type function requires these to
971538fd1498Szrj already be set up in order to function properly, so cannot be
971638fd1498Szrj called from there. If ALIGN is non-zero, then ensure alignment is
971738fd1498Szrj overridden to this value. */
971838fd1498Szrj
971938fd1498Szrj static tree
build_atomic_base(tree type,unsigned int align)972038fd1498Szrj build_atomic_base (tree type, unsigned int align)
972138fd1498Szrj {
972238fd1498Szrj tree t;
972338fd1498Szrj
972438fd1498Szrj /* Make sure its not already registered. */
972538fd1498Szrj if ((t = get_qualified_type (type, TYPE_QUAL_ATOMIC)))
972638fd1498Szrj return t;
972738fd1498Szrj
972838fd1498Szrj t = build_variant_type_copy (type);
972938fd1498Szrj set_type_quals (t, TYPE_QUAL_ATOMIC);
973038fd1498Szrj
973138fd1498Szrj if (align)
973238fd1498Szrj SET_TYPE_ALIGN (t, align);
973338fd1498Szrj
973438fd1498Szrj return t;
973538fd1498Szrj }
973638fd1498Szrj
973738fd1498Szrj /* Information about the _FloatN and _FloatNx types. This must be in
973838fd1498Szrj the same order as the corresponding TI_* enum values. */
973938fd1498Szrj const floatn_type_info floatn_nx_types[NUM_FLOATN_NX_TYPES] =
974038fd1498Szrj {
974138fd1498Szrj { 16, false },
974238fd1498Szrj { 32, false },
974338fd1498Szrj { 64, false },
974438fd1498Szrj { 128, false },
974538fd1498Szrj { 32, true },
974638fd1498Szrj { 64, true },
974738fd1498Szrj { 128, true },
974838fd1498Szrj };
974938fd1498Szrj
975038fd1498Szrj
975138fd1498Szrj /* Create nodes for all integer types (and error_mark_node) using the sizes
975238fd1498Szrj of C datatypes. SIGNED_CHAR specifies whether char is signed. */
975338fd1498Szrj
975438fd1498Szrj void
build_common_tree_nodes(bool signed_char)975538fd1498Szrj build_common_tree_nodes (bool signed_char)
975638fd1498Szrj {
975738fd1498Szrj int i;
975838fd1498Szrj
975938fd1498Szrj error_mark_node = make_node (ERROR_MARK);
976038fd1498Szrj TREE_TYPE (error_mark_node) = error_mark_node;
976138fd1498Szrj
976238fd1498Szrj initialize_sizetypes ();
976338fd1498Szrj
976438fd1498Szrj /* Define both `signed char' and `unsigned char'. */
976538fd1498Szrj signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
976638fd1498Szrj TYPE_STRING_FLAG (signed_char_type_node) = 1;
976738fd1498Szrj unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
976838fd1498Szrj TYPE_STRING_FLAG (unsigned_char_type_node) = 1;
976938fd1498Szrj
977038fd1498Szrj /* Define `char', which is like either `signed char' or `unsigned char'
977138fd1498Szrj but not the same as either. */
977238fd1498Szrj char_type_node
977338fd1498Szrj = (signed_char
977438fd1498Szrj ? make_signed_type (CHAR_TYPE_SIZE)
977538fd1498Szrj : make_unsigned_type (CHAR_TYPE_SIZE));
977638fd1498Szrj TYPE_STRING_FLAG (char_type_node) = 1;
977738fd1498Szrj
977838fd1498Szrj short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
977938fd1498Szrj short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
978038fd1498Szrj integer_type_node = make_signed_type (INT_TYPE_SIZE);
978138fd1498Szrj unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
978238fd1498Szrj long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
978338fd1498Szrj long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
978438fd1498Szrj long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
978538fd1498Szrj long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
978638fd1498Szrj
978738fd1498Szrj for (i = 0; i < NUM_INT_N_ENTS; i ++)
978838fd1498Szrj {
978938fd1498Szrj int_n_trees[i].signed_type = make_signed_type (int_n_data[i].bitsize);
979038fd1498Szrj int_n_trees[i].unsigned_type = make_unsigned_type (int_n_data[i].bitsize);
979138fd1498Szrj TYPE_SIZE (int_n_trees[i].signed_type) = bitsize_int (int_n_data[i].bitsize);
979238fd1498Szrj TYPE_SIZE (int_n_trees[i].unsigned_type) = bitsize_int (int_n_data[i].bitsize);
979338fd1498Szrj
9794*58e805e6Szrj if (int_n_enabled_p[i])
979538fd1498Szrj {
979638fd1498Szrj integer_types[itk_intN_0 + i * 2] = int_n_trees[i].signed_type;
979738fd1498Szrj integer_types[itk_unsigned_intN_0 + i * 2] = int_n_trees[i].unsigned_type;
979838fd1498Szrj }
979938fd1498Szrj }
980038fd1498Szrj
980138fd1498Szrj /* Define a boolean type. This type only represents boolean values but
980238fd1498Szrj may be larger than char depending on the value of BOOL_TYPE_SIZE. */
980338fd1498Szrj boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
980438fd1498Szrj TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
980538fd1498Szrj TYPE_PRECISION (boolean_type_node) = 1;
980638fd1498Szrj TYPE_MAX_VALUE (boolean_type_node) = build_int_cst (boolean_type_node, 1);
980738fd1498Szrj
980838fd1498Szrj /* Define what type to use for size_t. */
980938fd1498Szrj if (strcmp (SIZE_TYPE, "unsigned int") == 0)
981038fd1498Szrj size_type_node = unsigned_type_node;
981138fd1498Szrj else if (strcmp (SIZE_TYPE, "long unsigned int") == 0)
981238fd1498Szrj size_type_node = long_unsigned_type_node;
981338fd1498Szrj else if (strcmp (SIZE_TYPE, "long long unsigned int") == 0)
981438fd1498Szrj size_type_node = long_long_unsigned_type_node;
981538fd1498Szrj else if (strcmp (SIZE_TYPE, "short unsigned int") == 0)
981638fd1498Szrj size_type_node = short_unsigned_type_node;
981738fd1498Szrj else
981838fd1498Szrj {
981938fd1498Szrj int i;
982038fd1498Szrj
982138fd1498Szrj size_type_node = NULL_TREE;
982238fd1498Szrj for (i = 0; i < NUM_INT_N_ENTS; i++)
982338fd1498Szrj if (int_n_enabled_p[i])
982438fd1498Szrj {
982538fd1498Szrj char name[50];
982638fd1498Szrj sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
982738fd1498Szrj
982838fd1498Szrj if (strcmp (name, SIZE_TYPE) == 0)
982938fd1498Szrj {
983038fd1498Szrj size_type_node = int_n_trees[i].unsigned_type;
983138fd1498Szrj }
983238fd1498Szrj }
983338fd1498Szrj if (size_type_node == NULL_TREE)
983438fd1498Szrj gcc_unreachable ();
983538fd1498Szrj }
983638fd1498Szrj
983738fd1498Szrj /* Define what type to use for ptrdiff_t. */
983838fd1498Szrj if (strcmp (PTRDIFF_TYPE, "int") == 0)
983938fd1498Szrj ptrdiff_type_node = integer_type_node;
984038fd1498Szrj else if (strcmp (PTRDIFF_TYPE, "long int") == 0)
984138fd1498Szrj ptrdiff_type_node = long_integer_type_node;
984238fd1498Szrj else if (strcmp (PTRDIFF_TYPE, "long long int") == 0)
984338fd1498Szrj ptrdiff_type_node = long_long_integer_type_node;
984438fd1498Szrj else if (strcmp (PTRDIFF_TYPE, "short int") == 0)
984538fd1498Szrj ptrdiff_type_node = short_integer_type_node;
984638fd1498Szrj else
984738fd1498Szrj {
984838fd1498Szrj ptrdiff_type_node = NULL_TREE;
984938fd1498Szrj for (int i = 0; i < NUM_INT_N_ENTS; i++)
985038fd1498Szrj if (int_n_enabled_p[i])
985138fd1498Szrj {
985238fd1498Szrj char name[50];
985338fd1498Szrj sprintf (name, "__int%d", int_n_data[i].bitsize);
985438fd1498Szrj if (strcmp (name, PTRDIFF_TYPE) == 0)
985538fd1498Szrj ptrdiff_type_node = int_n_trees[i].signed_type;
985638fd1498Szrj }
985738fd1498Szrj if (ptrdiff_type_node == NULL_TREE)
985838fd1498Szrj gcc_unreachable ();
985938fd1498Szrj }
986038fd1498Szrj
986138fd1498Szrj /* Fill in the rest of the sized types. Reuse existing type nodes
986238fd1498Szrj when possible. */
986338fd1498Szrj intQI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (QImode), 0);
986438fd1498Szrj intHI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (HImode), 0);
986538fd1498Szrj intSI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (SImode), 0);
986638fd1498Szrj intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 0);
986738fd1498Szrj intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 0);
986838fd1498Szrj
986938fd1498Szrj unsigned_intQI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (QImode), 1);
987038fd1498Szrj unsigned_intHI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (HImode), 1);
987138fd1498Szrj unsigned_intSI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (SImode), 1);
987238fd1498Szrj unsigned_intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 1);
987338fd1498Szrj unsigned_intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 1);
987438fd1498Szrj
987538fd1498Szrj /* Don't call build_qualified type for atomics. That routine does
987638fd1498Szrj special processing for atomics, and until they are initialized
987738fd1498Szrj it's better not to make that call.
987838fd1498Szrj
987938fd1498Szrj Check to see if there is a target override for atomic types. */
988038fd1498Szrj
988138fd1498Szrj atomicQI_type_node = build_atomic_base (unsigned_intQI_type_node,
988238fd1498Szrj targetm.atomic_align_for_mode (QImode));
988338fd1498Szrj atomicHI_type_node = build_atomic_base (unsigned_intHI_type_node,
988438fd1498Szrj targetm.atomic_align_for_mode (HImode));
988538fd1498Szrj atomicSI_type_node = build_atomic_base (unsigned_intSI_type_node,
988638fd1498Szrj targetm.atomic_align_for_mode (SImode));
988738fd1498Szrj atomicDI_type_node = build_atomic_base (unsigned_intDI_type_node,
988838fd1498Szrj targetm.atomic_align_for_mode (DImode));
988938fd1498Szrj atomicTI_type_node = build_atomic_base (unsigned_intTI_type_node,
989038fd1498Szrj targetm.atomic_align_for_mode (TImode));
989138fd1498Szrj
989238fd1498Szrj access_public_node = get_identifier ("public");
989338fd1498Szrj access_protected_node = get_identifier ("protected");
989438fd1498Szrj access_private_node = get_identifier ("private");
989538fd1498Szrj
989638fd1498Szrj /* Define these next since types below may used them. */
989738fd1498Szrj integer_zero_node = build_int_cst (integer_type_node, 0);
989838fd1498Szrj integer_one_node = build_int_cst (integer_type_node, 1);
989938fd1498Szrj integer_three_node = build_int_cst (integer_type_node, 3);
990038fd1498Szrj integer_minus_one_node = build_int_cst (integer_type_node, -1);
990138fd1498Szrj
990238fd1498Szrj size_zero_node = size_int (0);
990338fd1498Szrj size_one_node = size_int (1);
990438fd1498Szrj bitsize_zero_node = bitsize_int (0);
990538fd1498Szrj bitsize_one_node = bitsize_int (1);
990638fd1498Szrj bitsize_unit_node = bitsize_int (BITS_PER_UNIT);
990738fd1498Szrj
990838fd1498Szrj boolean_false_node = TYPE_MIN_VALUE (boolean_type_node);
990938fd1498Szrj boolean_true_node = TYPE_MAX_VALUE (boolean_type_node);
991038fd1498Szrj
991138fd1498Szrj void_type_node = make_node (VOID_TYPE);
991238fd1498Szrj layout_type (void_type_node);
991338fd1498Szrj
991438fd1498Szrj pointer_bounds_type_node = targetm.chkp_bound_type ();
991538fd1498Szrj
991638fd1498Szrj /* We are not going to have real types in C with less than byte alignment,
991738fd1498Szrj so we might as well not have any types that claim to have it. */
991838fd1498Szrj SET_TYPE_ALIGN (void_type_node, BITS_PER_UNIT);
991938fd1498Szrj TYPE_USER_ALIGN (void_type_node) = 0;
992038fd1498Szrj
992138fd1498Szrj void_node = make_node (VOID_CST);
992238fd1498Szrj TREE_TYPE (void_node) = void_type_node;
992338fd1498Szrj
992438fd1498Szrj null_pointer_node = build_int_cst (build_pointer_type (void_type_node), 0);
992538fd1498Szrj layout_type (TREE_TYPE (null_pointer_node));
992638fd1498Szrj
992738fd1498Szrj ptr_type_node = build_pointer_type (void_type_node);
992838fd1498Szrj const_ptr_type_node
992938fd1498Szrj = build_pointer_type (build_type_variant (void_type_node, 1, 0));
993038fd1498Szrj for (unsigned i = 0;
993138fd1498Szrj i < sizeof (builtin_structptr_types) / sizeof (builtin_structptr_type);
993238fd1498Szrj ++i)
993338fd1498Szrj builtin_structptr_types[i].node = builtin_structptr_types[i].base;
993438fd1498Szrj
993538fd1498Szrj pointer_sized_int_node = build_nonstandard_integer_type (POINTER_SIZE, 1);
993638fd1498Szrj
993738fd1498Szrj float_type_node = make_node (REAL_TYPE);
993838fd1498Szrj TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
993938fd1498Szrj layout_type (float_type_node);
994038fd1498Szrj
994138fd1498Szrj double_type_node = make_node (REAL_TYPE);
994238fd1498Szrj TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
994338fd1498Szrj layout_type (double_type_node);
994438fd1498Szrj
994538fd1498Szrj long_double_type_node = make_node (REAL_TYPE);
994638fd1498Szrj TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
994738fd1498Szrj layout_type (long_double_type_node);
994838fd1498Szrj
994938fd1498Szrj for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
995038fd1498Szrj {
995138fd1498Szrj int n = floatn_nx_types[i].n;
995238fd1498Szrj bool extended = floatn_nx_types[i].extended;
995338fd1498Szrj scalar_float_mode mode;
995438fd1498Szrj if (!targetm.floatn_mode (n, extended).exists (&mode))
995538fd1498Szrj continue;
995638fd1498Szrj int precision = GET_MODE_PRECISION (mode);
995738fd1498Szrj /* Work around the rs6000 KFmode having precision 113 not
995838fd1498Szrj 128. */
995938fd1498Szrj const struct real_format *fmt = REAL_MODE_FORMAT (mode);
996038fd1498Szrj gcc_assert (fmt->b == 2 && fmt->emin + fmt->emax == 3);
996138fd1498Szrj int min_precision = fmt->p + ceil_log2 (fmt->emax - fmt->emin);
996238fd1498Szrj if (!extended)
996338fd1498Szrj gcc_assert (min_precision == n);
996438fd1498Szrj if (precision < min_precision)
996538fd1498Szrj precision = min_precision;
996638fd1498Szrj FLOATN_NX_TYPE_NODE (i) = make_node (REAL_TYPE);
996738fd1498Szrj TYPE_PRECISION (FLOATN_NX_TYPE_NODE (i)) = precision;
996838fd1498Szrj layout_type (FLOATN_NX_TYPE_NODE (i));
996938fd1498Szrj SET_TYPE_MODE (FLOATN_NX_TYPE_NODE (i), mode);
997038fd1498Szrj }
997138fd1498Szrj
997238fd1498Szrj float_ptr_type_node = build_pointer_type (float_type_node);
997338fd1498Szrj double_ptr_type_node = build_pointer_type (double_type_node);
997438fd1498Szrj long_double_ptr_type_node = build_pointer_type (long_double_type_node);
997538fd1498Szrj integer_ptr_type_node = build_pointer_type (integer_type_node);
997638fd1498Szrj
997738fd1498Szrj /* Fixed size integer types. */
997838fd1498Szrj uint16_type_node = make_or_reuse_type (16, 1);
997938fd1498Szrj uint32_type_node = make_or_reuse_type (32, 1);
998038fd1498Szrj uint64_type_node = make_or_reuse_type (64, 1);
998138fd1498Szrj
998238fd1498Szrj /* Decimal float types. */
998338fd1498Szrj dfloat32_type_node = make_node (REAL_TYPE);
998438fd1498Szrj TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE;
998538fd1498Szrj SET_TYPE_MODE (dfloat32_type_node, SDmode);
998638fd1498Szrj layout_type (dfloat32_type_node);
998738fd1498Szrj dfloat32_ptr_type_node = build_pointer_type (dfloat32_type_node);
998838fd1498Szrj
998938fd1498Szrj dfloat64_type_node = make_node (REAL_TYPE);
999038fd1498Szrj TYPE_PRECISION (dfloat64_type_node) = DECIMAL64_TYPE_SIZE;
999138fd1498Szrj SET_TYPE_MODE (dfloat64_type_node, DDmode);
999238fd1498Szrj layout_type (dfloat64_type_node);
999338fd1498Szrj dfloat64_ptr_type_node = build_pointer_type (dfloat64_type_node);
999438fd1498Szrj
999538fd1498Szrj dfloat128_type_node = make_node (REAL_TYPE);
999638fd1498Szrj TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE;
999738fd1498Szrj SET_TYPE_MODE (dfloat128_type_node, TDmode);
999838fd1498Szrj layout_type (dfloat128_type_node);
999938fd1498Szrj dfloat128_ptr_type_node = build_pointer_type (dfloat128_type_node);
1000038fd1498Szrj
1000138fd1498Szrj complex_integer_type_node = build_complex_type (integer_type_node, true);
1000238fd1498Szrj complex_float_type_node = build_complex_type (float_type_node, true);
1000338fd1498Szrj complex_double_type_node = build_complex_type (double_type_node, true);
1000438fd1498Szrj complex_long_double_type_node = build_complex_type (long_double_type_node,
1000538fd1498Szrj true);
1000638fd1498Szrj
1000738fd1498Szrj for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
1000838fd1498Szrj {
1000938fd1498Szrj if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE)
1001038fd1498Szrj COMPLEX_FLOATN_NX_TYPE_NODE (i)
1001138fd1498Szrj = build_complex_type (FLOATN_NX_TYPE_NODE (i));
1001238fd1498Szrj }
1001338fd1498Szrj
1001438fd1498Szrj /* Make fixed-point nodes based on sat/non-sat and signed/unsigned. */
1001538fd1498Szrj #define MAKE_FIXED_TYPE_NODE(KIND,SIZE) \
1001638fd1498Szrj sat_ ## KIND ## _type_node = \
1001738fd1498Szrj make_sat_signed_ ## KIND ## _type (SIZE); \
1001838fd1498Szrj sat_unsigned_ ## KIND ## _type_node = \
1001938fd1498Szrj make_sat_unsigned_ ## KIND ## _type (SIZE); \
1002038fd1498Szrj KIND ## _type_node = make_signed_ ## KIND ## _type (SIZE); \
1002138fd1498Szrj unsigned_ ## KIND ## _type_node = \
1002238fd1498Szrj make_unsigned_ ## KIND ## _type (SIZE);
1002338fd1498Szrj
1002438fd1498Szrj #define MAKE_FIXED_TYPE_NODE_WIDTH(KIND,WIDTH,SIZE) \
1002538fd1498Szrj sat_ ## WIDTH ## KIND ## _type_node = \
1002638fd1498Szrj make_sat_signed_ ## KIND ## _type (SIZE); \
1002738fd1498Szrj sat_unsigned_ ## WIDTH ## KIND ## _type_node = \
1002838fd1498Szrj make_sat_unsigned_ ## KIND ## _type (SIZE); \
1002938fd1498Szrj WIDTH ## KIND ## _type_node = make_signed_ ## KIND ## _type (SIZE); \
1003038fd1498Szrj unsigned_ ## WIDTH ## KIND ## _type_node = \
1003138fd1498Szrj make_unsigned_ ## KIND ## _type (SIZE);
1003238fd1498Szrj
1003338fd1498Szrj /* Make fixed-point type nodes based on four different widths. */
1003438fd1498Szrj #define MAKE_FIXED_TYPE_NODE_FAMILY(N1,N2) \
1003538fd1498Szrj MAKE_FIXED_TYPE_NODE_WIDTH (N1, short_, SHORT_ ## N2 ## _TYPE_SIZE) \
1003638fd1498Szrj MAKE_FIXED_TYPE_NODE (N1, N2 ## _TYPE_SIZE) \
1003738fd1498Szrj MAKE_FIXED_TYPE_NODE_WIDTH (N1, long_, LONG_ ## N2 ## _TYPE_SIZE) \
1003838fd1498Szrj MAKE_FIXED_TYPE_NODE_WIDTH (N1, long_long_, LONG_LONG_ ## N2 ## _TYPE_SIZE)
1003938fd1498Szrj
1004038fd1498Szrj /* Make fixed-point mode nodes based on sat/non-sat and signed/unsigned. */
1004138fd1498Szrj #define MAKE_FIXED_MODE_NODE(KIND,NAME,MODE) \
1004238fd1498Szrj NAME ## _type_node = \
1004338fd1498Szrj make_or_reuse_signed_ ## KIND ## _type (GET_MODE_BITSIZE (MODE ## mode)); \
1004438fd1498Szrj u ## NAME ## _type_node = \
1004538fd1498Szrj make_or_reuse_unsigned_ ## KIND ## _type \
1004638fd1498Szrj (GET_MODE_BITSIZE (U ## MODE ## mode)); \
1004738fd1498Szrj sat_ ## NAME ## _type_node = \
1004838fd1498Szrj make_or_reuse_sat_signed_ ## KIND ## _type \
1004938fd1498Szrj (GET_MODE_BITSIZE (MODE ## mode)); \
1005038fd1498Szrj sat_u ## NAME ## _type_node = \
1005138fd1498Szrj make_or_reuse_sat_unsigned_ ## KIND ## _type \
1005238fd1498Szrj (GET_MODE_BITSIZE (U ## MODE ## mode));
1005338fd1498Szrj
1005438fd1498Szrj /* Fixed-point type and mode nodes. */
1005538fd1498Szrj MAKE_FIXED_TYPE_NODE_FAMILY (fract, FRACT)
1005638fd1498Szrj MAKE_FIXED_TYPE_NODE_FAMILY (accum, ACCUM)
1005738fd1498Szrj MAKE_FIXED_MODE_NODE (fract, qq, QQ)
1005838fd1498Szrj MAKE_FIXED_MODE_NODE (fract, hq, HQ)
1005938fd1498Szrj MAKE_FIXED_MODE_NODE (fract, sq, SQ)
1006038fd1498Szrj MAKE_FIXED_MODE_NODE (fract, dq, DQ)
1006138fd1498Szrj MAKE_FIXED_MODE_NODE (fract, tq, TQ)
1006238fd1498Szrj MAKE_FIXED_MODE_NODE (accum, ha, HA)
1006338fd1498Szrj MAKE_FIXED_MODE_NODE (accum, sa, SA)
1006438fd1498Szrj MAKE_FIXED_MODE_NODE (accum, da, DA)
1006538fd1498Szrj MAKE_FIXED_MODE_NODE (accum, ta, TA)
1006638fd1498Szrj
1006738fd1498Szrj {
1006838fd1498Szrj tree t = targetm.build_builtin_va_list ();
1006938fd1498Szrj
1007038fd1498Szrj /* Many back-ends define record types without setting TYPE_NAME.
1007138fd1498Szrj If we copied the record type here, we'd keep the original
1007238fd1498Szrj record type without a name. This breaks name mangling. So,
1007338fd1498Szrj don't copy record types and let c_common_nodes_and_builtins()
1007438fd1498Szrj declare the type to be __builtin_va_list. */
1007538fd1498Szrj if (TREE_CODE (t) != RECORD_TYPE)
1007638fd1498Szrj t = build_variant_type_copy (t);
1007738fd1498Szrj
1007838fd1498Szrj va_list_type_node = t;
1007938fd1498Szrj }
1008038fd1498Szrj }
1008138fd1498Szrj
1008238fd1498Szrj /* Modify DECL for given flags.
1008338fd1498Szrj TM_PURE attribute is set only on types, so the function will modify
1008438fd1498Szrj DECL's type when ECF_TM_PURE is used. */
1008538fd1498Szrj
1008638fd1498Szrj void
set_call_expr_flags(tree decl,int flags)1008738fd1498Szrj set_call_expr_flags (tree decl, int flags)
1008838fd1498Szrj {
1008938fd1498Szrj if (flags & ECF_NOTHROW)
1009038fd1498Szrj TREE_NOTHROW (decl) = 1;
1009138fd1498Szrj if (flags & ECF_CONST)
1009238fd1498Szrj TREE_READONLY (decl) = 1;
1009338fd1498Szrj if (flags & ECF_PURE)
1009438fd1498Szrj DECL_PURE_P (decl) = 1;
1009538fd1498Szrj if (flags & ECF_LOOPING_CONST_OR_PURE)
1009638fd1498Szrj DECL_LOOPING_CONST_OR_PURE_P (decl) = 1;
1009738fd1498Szrj if (flags & ECF_NOVOPS)
1009838fd1498Szrj DECL_IS_NOVOPS (decl) = 1;
1009938fd1498Szrj if (flags & ECF_NORETURN)
1010038fd1498Szrj TREE_THIS_VOLATILE (decl) = 1;
1010138fd1498Szrj if (flags & ECF_MALLOC)
1010238fd1498Szrj DECL_IS_MALLOC (decl) = 1;
1010338fd1498Szrj if (flags & ECF_RETURNS_TWICE)
1010438fd1498Szrj DECL_IS_RETURNS_TWICE (decl) = 1;
1010538fd1498Szrj if (flags & ECF_LEAF)
1010638fd1498Szrj DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"),
1010738fd1498Szrj NULL, DECL_ATTRIBUTES (decl));
1010838fd1498Szrj if (flags & ECF_COLD)
1010938fd1498Szrj DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("cold"),
1011038fd1498Szrj NULL, DECL_ATTRIBUTES (decl));
1011138fd1498Szrj if (flags & ECF_RET1)
1011238fd1498Szrj DECL_ATTRIBUTES (decl)
1011338fd1498Szrj = tree_cons (get_identifier ("fn spec"),
1011438fd1498Szrj build_tree_list (NULL_TREE, build_string (1, "1")),
1011538fd1498Szrj DECL_ATTRIBUTES (decl));
1011638fd1498Szrj if ((flags & ECF_TM_PURE) && flag_tm)
1011738fd1498Szrj apply_tm_attr (decl, get_identifier ("transaction_pure"));
1011838fd1498Szrj /* Looping const or pure is implied by noreturn.
1011938fd1498Szrj There is currently no way to declare looping const or looping pure alone. */
1012038fd1498Szrj gcc_assert (!(flags & ECF_LOOPING_CONST_OR_PURE)
1012138fd1498Szrj || ((flags & ECF_NORETURN) && (flags & (ECF_CONST | ECF_PURE))));
1012238fd1498Szrj }
1012338fd1498Szrj
1012438fd1498Szrj
1012538fd1498Szrj /* A subroutine of build_common_builtin_nodes. Define a builtin function. */
1012638fd1498Szrj
1012738fd1498Szrj static void
local_define_builtin(const char * name,tree type,enum built_in_function code,const char * library_name,int ecf_flags)1012838fd1498Szrj local_define_builtin (const char *name, tree type, enum built_in_function code,
1012938fd1498Szrj const char *library_name, int ecf_flags)
1013038fd1498Szrj {
1013138fd1498Szrj tree decl;
1013238fd1498Szrj
1013338fd1498Szrj decl = add_builtin_function (name, type, code, BUILT_IN_NORMAL,
1013438fd1498Szrj library_name, NULL_TREE);
1013538fd1498Szrj set_call_expr_flags (decl, ecf_flags);
1013638fd1498Szrj
1013738fd1498Szrj set_builtin_decl (code, decl, true);
1013838fd1498Szrj }
1013938fd1498Szrj
1014038fd1498Szrj /* Call this function after instantiating all builtins that the language
1014138fd1498Szrj front end cares about. This will build the rest of the builtins
1014238fd1498Szrj and internal functions that are relied upon by the tree optimizers and
1014338fd1498Szrj the middle-end. */
1014438fd1498Szrj
1014538fd1498Szrj void
build_common_builtin_nodes(void)1014638fd1498Szrj build_common_builtin_nodes (void)
1014738fd1498Szrj {
1014838fd1498Szrj tree tmp, ftype;
1014938fd1498Szrj int ecf_flags;
1015038fd1498Szrj
1015138fd1498Szrj if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE)
1015238fd1498Szrj || !builtin_decl_explicit_p (BUILT_IN_ABORT))
1015338fd1498Szrj {
1015438fd1498Szrj ftype = build_function_type (void_type_node, void_list_node);
1015538fd1498Szrj if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE))
1015638fd1498Szrj local_define_builtin ("__builtin_unreachable", ftype,
1015738fd1498Szrj BUILT_IN_UNREACHABLE,
1015838fd1498Szrj "__builtin_unreachable",
1015938fd1498Szrj ECF_NOTHROW | ECF_LEAF | ECF_NORETURN
1016038fd1498Szrj | ECF_CONST | ECF_COLD);
1016138fd1498Szrj if (!builtin_decl_explicit_p (BUILT_IN_ABORT))
1016238fd1498Szrj local_define_builtin ("__builtin_abort", ftype, BUILT_IN_ABORT,
1016338fd1498Szrj "abort",
1016438fd1498Szrj ECF_LEAF | ECF_NORETURN | ECF_CONST | ECF_COLD);
1016538fd1498Szrj }
1016638fd1498Szrj
1016738fd1498Szrj if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY)
1016838fd1498Szrj || !builtin_decl_explicit_p (BUILT_IN_MEMMOVE))
1016938fd1498Szrj {
1017038fd1498Szrj ftype = build_function_type_list (ptr_type_node,
1017138fd1498Szrj ptr_type_node, const_ptr_type_node,
1017238fd1498Szrj size_type_node, NULL_TREE);
1017338fd1498Szrj
1017438fd1498Szrj if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY))
1017538fd1498Szrj local_define_builtin ("__builtin_memcpy", ftype, BUILT_IN_MEMCPY,
1017638fd1498Szrj "memcpy", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
1017738fd1498Szrj if (!builtin_decl_explicit_p (BUILT_IN_MEMMOVE))
1017838fd1498Szrj local_define_builtin ("__builtin_memmove", ftype, BUILT_IN_MEMMOVE,
1017938fd1498Szrj "memmove", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
1018038fd1498Szrj }
1018138fd1498Szrj
1018238fd1498Szrj if (!builtin_decl_explicit_p (BUILT_IN_MEMCMP))
1018338fd1498Szrj {
1018438fd1498Szrj ftype = build_function_type_list (integer_type_node, const_ptr_type_node,
1018538fd1498Szrj const_ptr_type_node, size_type_node,
1018638fd1498Szrj NULL_TREE);
1018738fd1498Szrj local_define_builtin ("__builtin_memcmp", ftype, BUILT_IN_MEMCMP,
1018838fd1498Szrj "memcmp", ECF_PURE | ECF_NOTHROW | ECF_LEAF);
1018938fd1498Szrj }
1019038fd1498Szrj
1019138fd1498Szrj if (!builtin_decl_explicit_p (BUILT_IN_MEMSET))
1019238fd1498Szrj {
1019338fd1498Szrj ftype = build_function_type_list (ptr_type_node,
1019438fd1498Szrj ptr_type_node, integer_type_node,
1019538fd1498Szrj size_type_node, NULL_TREE);
1019638fd1498Szrj local_define_builtin ("__builtin_memset", ftype, BUILT_IN_MEMSET,
1019738fd1498Szrj "memset", ECF_NOTHROW | ECF_LEAF | ECF_RET1);
1019838fd1498Szrj }
1019938fd1498Szrj
1020038fd1498Szrj /* If we're checking the stack, `alloca' can throw. */
1020138fd1498Szrj const int alloca_flags
1020238fd1498Szrj = ECF_MALLOC | ECF_LEAF | (flag_stack_check ? 0 : ECF_NOTHROW);
1020338fd1498Szrj
1020438fd1498Szrj if (!builtin_decl_explicit_p (BUILT_IN_ALLOCA))
1020538fd1498Szrj {
1020638fd1498Szrj ftype = build_function_type_list (ptr_type_node,
1020738fd1498Szrj size_type_node, NULL_TREE);
1020838fd1498Szrj local_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA,
1020938fd1498Szrj "alloca", alloca_flags);
1021038fd1498Szrj }
1021138fd1498Szrj
1021238fd1498Szrj ftype = build_function_type_list (ptr_type_node, size_type_node,
1021338fd1498Szrj size_type_node, NULL_TREE);
1021438fd1498Szrj local_define_builtin ("__builtin_alloca_with_align", ftype,
1021538fd1498Szrj BUILT_IN_ALLOCA_WITH_ALIGN,
1021638fd1498Szrj "__builtin_alloca_with_align",
1021738fd1498Szrj alloca_flags);
1021838fd1498Szrj
1021938fd1498Szrj ftype = build_function_type_list (ptr_type_node, size_type_node,
1022038fd1498Szrj size_type_node, size_type_node, NULL_TREE);
1022138fd1498Szrj local_define_builtin ("__builtin_alloca_with_align_and_max", ftype,
1022238fd1498Szrj BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX,
1022338fd1498Szrj "__builtin_alloca_with_align_and_max",
1022438fd1498Szrj alloca_flags);
1022538fd1498Szrj
1022638fd1498Szrj ftype = build_function_type_list (void_type_node,
1022738fd1498Szrj ptr_type_node, ptr_type_node,
1022838fd1498Szrj ptr_type_node, NULL_TREE);
1022938fd1498Szrj local_define_builtin ("__builtin_init_trampoline", ftype,
1023038fd1498Szrj BUILT_IN_INIT_TRAMPOLINE,
1023138fd1498Szrj "__builtin_init_trampoline", ECF_NOTHROW | ECF_LEAF);
1023238fd1498Szrj local_define_builtin ("__builtin_init_heap_trampoline", ftype,
1023338fd1498Szrj BUILT_IN_INIT_HEAP_TRAMPOLINE,
1023438fd1498Szrj "__builtin_init_heap_trampoline",
1023538fd1498Szrj ECF_NOTHROW | ECF_LEAF);
1023638fd1498Szrj local_define_builtin ("__builtin_init_descriptor", ftype,
1023738fd1498Szrj BUILT_IN_INIT_DESCRIPTOR,
1023838fd1498Szrj "__builtin_init_descriptor", ECF_NOTHROW | ECF_LEAF);
1023938fd1498Szrj
1024038fd1498Szrj ftype = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE);
1024138fd1498Szrj local_define_builtin ("__builtin_adjust_trampoline", ftype,
1024238fd1498Szrj BUILT_IN_ADJUST_TRAMPOLINE,
1024338fd1498Szrj "__builtin_adjust_trampoline",
1024438fd1498Szrj ECF_CONST | ECF_NOTHROW);
1024538fd1498Szrj local_define_builtin ("__builtin_adjust_descriptor", ftype,
1024638fd1498Szrj BUILT_IN_ADJUST_DESCRIPTOR,
1024738fd1498Szrj "__builtin_adjust_descriptor",
1024838fd1498Szrj ECF_CONST | ECF_NOTHROW);
1024938fd1498Szrj
1025038fd1498Szrj ftype = build_function_type_list (void_type_node,
1025138fd1498Szrj ptr_type_node, ptr_type_node, NULL_TREE);
1025238fd1498Szrj local_define_builtin ("__builtin_nonlocal_goto", ftype,
1025338fd1498Szrj BUILT_IN_NONLOCAL_GOTO,
1025438fd1498Szrj "__builtin_nonlocal_goto",
1025538fd1498Szrj ECF_NORETURN | ECF_NOTHROW);
1025638fd1498Szrj
1025738fd1498Szrj ftype = build_function_type_list (void_type_node,
1025838fd1498Szrj ptr_type_node, ptr_type_node, NULL_TREE);
1025938fd1498Szrj local_define_builtin ("__builtin_setjmp_setup", ftype,
1026038fd1498Szrj BUILT_IN_SETJMP_SETUP,
1026138fd1498Szrj "__builtin_setjmp_setup", ECF_NOTHROW);
1026238fd1498Szrj
1026338fd1498Szrj ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1026438fd1498Szrj local_define_builtin ("__builtin_setjmp_receiver", ftype,
1026538fd1498Szrj BUILT_IN_SETJMP_RECEIVER,
1026638fd1498Szrj "__builtin_setjmp_receiver", ECF_NOTHROW | ECF_LEAF);
1026738fd1498Szrj
1026838fd1498Szrj ftype = build_function_type_list (ptr_type_node, NULL_TREE);
1026938fd1498Szrj local_define_builtin ("__builtin_stack_save", ftype, BUILT_IN_STACK_SAVE,
1027038fd1498Szrj "__builtin_stack_save", ECF_NOTHROW | ECF_LEAF);
1027138fd1498Szrj
1027238fd1498Szrj ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1027338fd1498Szrj local_define_builtin ("__builtin_stack_restore", ftype,
1027438fd1498Szrj BUILT_IN_STACK_RESTORE,
1027538fd1498Szrj "__builtin_stack_restore", ECF_NOTHROW | ECF_LEAF);
1027638fd1498Szrj
1027738fd1498Szrj ftype = build_function_type_list (integer_type_node, const_ptr_type_node,
1027838fd1498Szrj const_ptr_type_node, size_type_node,
1027938fd1498Szrj NULL_TREE);
1028038fd1498Szrj local_define_builtin ("__builtin_memcmp_eq", ftype, BUILT_IN_MEMCMP_EQ,
1028138fd1498Szrj "__builtin_memcmp_eq",
1028238fd1498Szrj ECF_PURE | ECF_NOTHROW | ECF_LEAF);
1028338fd1498Szrj
1028438fd1498Szrj /* If there's a possibility that we might use the ARM EABI, build the
1028538fd1498Szrj alternate __cxa_end_cleanup node used to resume from C++. */
1028638fd1498Szrj if (targetm.arm_eabi_unwinder)
1028738fd1498Szrj {
1028838fd1498Szrj ftype = build_function_type_list (void_type_node, NULL_TREE);
1028938fd1498Szrj local_define_builtin ("__builtin_cxa_end_cleanup", ftype,
1029038fd1498Szrj BUILT_IN_CXA_END_CLEANUP,
1029138fd1498Szrj "__cxa_end_cleanup", ECF_NORETURN | ECF_LEAF);
1029238fd1498Szrj }
1029338fd1498Szrj
1029438fd1498Szrj ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1029538fd1498Szrj local_define_builtin ("__builtin_unwind_resume", ftype,
1029638fd1498Szrj BUILT_IN_UNWIND_RESUME,
1029738fd1498Szrj ((targetm_common.except_unwind_info (&global_options)
1029838fd1498Szrj == UI_SJLJ)
1029938fd1498Szrj ? "_Unwind_SjLj_Resume" : "_Unwind_Resume"),
1030038fd1498Szrj ECF_NORETURN);
1030138fd1498Szrj
1030238fd1498Szrj if (builtin_decl_explicit (BUILT_IN_RETURN_ADDRESS) == NULL_TREE)
1030338fd1498Szrj {
1030438fd1498Szrj ftype = build_function_type_list (ptr_type_node, integer_type_node,
1030538fd1498Szrj NULL_TREE);
1030638fd1498Szrj local_define_builtin ("__builtin_return_address", ftype,
1030738fd1498Szrj BUILT_IN_RETURN_ADDRESS,
1030838fd1498Szrj "__builtin_return_address",
1030938fd1498Szrj ECF_NOTHROW);
1031038fd1498Szrj }
1031138fd1498Szrj
1031238fd1498Szrj if (!builtin_decl_explicit_p (BUILT_IN_PROFILE_FUNC_ENTER)
1031338fd1498Szrj || !builtin_decl_explicit_p (BUILT_IN_PROFILE_FUNC_EXIT))
1031438fd1498Szrj {
1031538fd1498Szrj ftype = build_function_type_list (void_type_node, ptr_type_node,
1031638fd1498Szrj ptr_type_node, NULL_TREE);
1031738fd1498Szrj if (!builtin_decl_explicit_p (BUILT_IN_PROFILE_FUNC_ENTER))
1031838fd1498Szrj local_define_builtin ("__cyg_profile_func_enter", ftype,
1031938fd1498Szrj BUILT_IN_PROFILE_FUNC_ENTER,
1032038fd1498Szrj "__cyg_profile_func_enter", 0);
1032138fd1498Szrj if (!builtin_decl_explicit_p (BUILT_IN_PROFILE_FUNC_EXIT))
1032238fd1498Szrj local_define_builtin ("__cyg_profile_func_exit", ftype,
1032338fd1498Szrj BUILT_IN_PROFILE_FUNC_EXIT,
1032438fd1498Szrj "__cyg_profile_func_exit", 0);
1032538fd1498Szrj }
1032638fd1498Szrj
1032738fd1498Szrj /* The exception object and filter values from the runtime. The argument
1032838fd1498Szrj must be zero before exception lowering, i.e. from the front end. After
1032938fd1498Szrj exception lowering, it will be the region number for the exception
1033038fd1498Szrj landing pad. These functions are PURE instead of CONST to prevent
1033138fd1498Szrj them from being hoisted past the exception edge that will initialize
1033238fd1498Szrj its value in the landing pad. */
1033338fd1498Szrj ftype = build_function_type_list (ptr_type_node,
1033438fd1498Szrj integer_type_node, NULL_TREE);
1033538fd1498Szrj ecf_flags = ECF_PURE | ECF_NOTHROW | ECF_LEAF;
1033638fd1498Szrj /* Only use TM_PURE if we have TM language support. */
1033738fd1498Szrj if (builtin_decl_explicit_p (BUILT_IN_TM_LOAD_1))
1033838fd1498Szrj ecf_flags |= ECF_TM_PURE;
1033938fd1498Szrj local_define_builtin ("__builtin_eh_pointer", ftype, BUILT_IN_EH_POINTER,
1034038fd1498Szrj "__builtin_eh_pointer", ecf_flags);
1034138fd1498Szrj
1034238fd1498Szrj tmp = lang_hooks.types.type_for_mode (targetm.eh_return_filter_mode (), 0);
1034338fd1498Szrj ftype = build_function_type_list (tmp, integer_type_node, NULL_TREE);
1034438fd1498Szrj local_define_builtin ("__builtin_eh_filter", ftype, BUILT_IN_EH_FILTER,
1034538fd1498Szrj "__builtin_eh_filter", ECF_PURE | ECF_NOTHROW | ECF_LEAF);
1034638fd1498Szrj
1034738fd1498Szrj ftype = build_function_type_list (void_type_node,
1034838fd1498Szrj integer_type_node, integer_type_node,
1034938fd1498Szrj NULL_TREE);
1035038fd1498Szrj local_define_builtin ("__builtin_eh_copy_values", ftype,
1035138fd1498Szrj BUILT_IN_EH_COPY_VALUES,
1035238fd1498Szrj "__builtin_eh_copy_values", ECF_NOTHROW);
1035338fd1498Szrj
1035438fd1498Szrj /* Complex multiplication and division. These are handled as builtins
1035538fd1498Szrj rather than optabs because emit_library_call_value doesn't support
1035638fd1498Szrj complex. Further, we can do slightly better with folding these
1035738fd1498Szrj beasties if the real and complex parts of the arguments are separate. */
1035838fd1498Szrj {
1035938fd1498Szrj int mode;
1036038fd1498Szrj
1036138fd1498Szrj for (mode = MIN_MODE_COMPLEX_FLOAT; mode <= MAX_MODE_COMPLEX_FLOAT; ++mode)
1036238fd1498Szrj {
1036338fd1498Szrj char mode_name_buf[4], *q;
1036438fd1498Szrj const char *p;
1036538fd1498Szrj enum built_in_function mcode, dcode;
1036638fd1498Szrj tree type, inner_type;
1036738fd1498Szrj const char *prefix = "__";
1036838fd1498Szrj
1036938fd1498Szrj if (targetm.libfunc_gnu_prefix)
1037038fd1498Szrj prefix = "__gnu_";
1037138fd1498Szrj
1037238fd1498Szrj type = lang_hooks.types.type_for_mode ((machine_mode) mode, 0);
1037338fd1498Szrj if (type == NULL)
1037438fd1498Szrj continue;
1037538fd1498Szrj inner_type = TREE_TYPE (type);
1037638fd1498Szrj
1037738fd1498Szrj ftype = build_function_type_list (type, inner_type, inner_type,
1037838fd1498Szrj inner_type, inner_type, NULL_TREE);
1037938fd1498Szrj
1038038fd1498Szrj mcode = ((enum built_in_function)
1038138fd1498Szrj (BUILT_IN_COMPLEX_MUL_MIN + mode - MIN_MODE_COMPLEX_FLOAT));
1038238fd1498Szrj dcode = ((enum built_in_function)
1038338fd1498Szrj (BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT));
1038438fd1498Szrj
1038538fd1498Szrj for (p = GET_MODE_NAME (mode), q = mode_name_buf; *p; p++, q++)
1038638fd1498Szrj *q = TOLOWER (*p);
1038738fd1498Szrj *q = '\0';
1038838fd1498Szrj
1038938fd1498Szrj built_in_names[mcode] = concat (prefix, "mul", mode_name_buf, "3",
1039038fd1498Szrj NULL);
1039138fd1498Szrj local_define_builtin (built_in_names[mcode], ftype, mcode,
1039238fd1498Szrj built_in_names[mcode],
1039338fd1498Szrj ECF_CONST | ECF_NOTHROW | ECF_LEAF);
1039438fd1498Szrj
1039538fd1498Szrj built_in_names[dcode] = concat (prefix, "div", mode_name_buf, "3",
1039638fd1498Szrj NULL);
1039738fd1498Szrj local_define_builtin (built_in_names[dcode], ftype, dcode,
1039838fd1498Szrj built_in_names[dcode],
1039938fd1498Szrj ECF_CONST | ECF_NOTHROW | ECF_LEAF);
1040038fd1498Szrj }
1040138fd1498Szrj }
1040238fd1498Szrj
1040338fd1498Szrj init_internal_fns ();
1040438fd1498Szrj }
1040538fd1498Szrj
1040638fd1498Szrj /* HACK. GROSS. This is absolutely disgusting. I wish there was a
1040738fd1498Szrj better way.
1040838fd1498Szrj
1040938fd1498Szrj If we requested a pointer to a vector, build up the pointers that
1041038fd1498Szrj we stripped off while looking for the inner type. Similarly for
1041138fd1498Szrj return values from functions.
1041238fd1498Szrj
1041338fd1498Szrj The argument TYPE is the top of the chain, and BOTTOM is the
1041438fd1498Szrj new type which we will point to. */
1041538fd1498Szrj
1041638fd1498Szrj tree
reconstruct_complex_type(tree type,tree bottom)1041738fd1498Szrj reconstruct_complex_type (tree type, tree bottom)
1041838fd1498Szrj {
1041938fd1498Szrj tree inner, outer;
1042038fd1498Szrj
1042138fd1498Szrj if (TREE_CODE (type) == POINTER_TYPE)
1042238fd1498Szrj {
1042338fd1498Szrj inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
1042438fd1498Szrj outer = build_pointer_type_for_mode (inner, TYPE_MODE (type),
1042538fd1498Szrj TYPE_REF_CAN_ALIAS_ALL (type));
1042638fd1498Szrj }
1042738fd1498Szrj else if (TREE_CODE (type) == REFERENCE_TYPE)
1042838fd1498Szrj {
1042938fd1498Szrj inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
1043038fd1498Szrj outer = build_reference_type_for_mode (inner, TYPE_MODE (type),
1043138fd1498Szrj TYPE_REF_CAN_ALIAS_ALL (type));
1043238fd1498Szrj }
1043338fd1498Szrj else if (TREE_CODE (type) == ARRAY_TYPE)
1043438fd1498Szrj {
1043538fd1498Szrj inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
1043638fd1498Szrj outer = build_array_type (inner, TYPE_DOMAIN (type));
1043738fd1498Szrj }
1043838fd1498Szrj else if (TREE_CODE (type) == FUNCTION_TYPE)
1043938fd1498Szrj {
1044038fd1498Szrj inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
1044138fd1498Szrj outer = build_function_type (inner, TYPE_ARG_TYPES (type));
1044238fd1498Szrj }
1044338fd1498Szrj else if (TREE_CODE (type) == METHOD_TYPE)
1044438fd1498Szrj {
1044538fd1498Szrj inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
1044638fd1498Szrj /* The build_method_type_directly() routine prepends 'this' to argument list,
1044738fd1498Szrj so we must compensate by getting rid of it. */
1044838fd1498Szrj outer
1044938fd1498Szrj = build_method_type_directly
1045038fd1498Szrj (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))),
1045138fd1498Szrj inner,
1045238fd1498Szrj TREE_CHAIN (TYPE_ARG_TYPES (type)));
1045338fd1498Szrj }
1045438fd1498Szrj else if (TREE_CODE (type) == OFFSET_TYPE)
1045538fd1498Szrj {
1045638fd1498Szrj inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
1045738fd1498Szrj outer = build_offset_type (TYPE_OFFSET_BASETYPE (type), inner);
1045838fd1498Szrj }
1045938fd1498Szrj else
1046038fd1498Szrj return bottom;
1046138fd1498Szrj
1046238fd1498Szrj return build_type_attribute_qual_variant (outer, TYPE_ATTRIBUTES (type),
1046338fd1498Szrj TYPE_QUALS (type));
1046438fd1498Szrj }
1046538fd1498Szrj
1046638fd1498Szrj /* Returns a vector tree node given a mode (integer, vector, or BLKmode) and
1046738fd1498Szrj the inner type. */
1046838fd1498Szrj tree
build_vector_type_for_mode(tree innertype,machine_mode mode)1046938fd1498Szrj build_vector_type_for_mode (tree innertype, machine_mode mode)
1047038fd1498Szrj {
1047138fd1498Szrj poly_int64 nunits;
1047238fd1498Szrj unsigned int bitsize;
1047338fd1498Szrj
1047438fd1498Szrj switch (GET_MODE_CLASS (mode))
1047538fd1498Szrj {
1047638fd1498Szrj case MODE_VECTOR_BOOL:
1047738fd1498Szrj case MODE_VECTOR_INT:
1047838fd1498Szrj case MODE_VECTOR_FLOAT:
1047938fd1498Szrj case MODE_VECTOR_FRACT:
1048038fd1498Szrj case MODE_VECTOR_UFRACT:
1048138fd1498Szrj case MODE_VECTOR_ACCUM:
1048238fd1498Szrj case MODE_VECTOR_UACCUM:
1048338fd1498Szrj nunits = GET_MODE_NUNITS (mode);
1048438fd1498Szrj break;
1048538fd1498Szrj
1048638fd1498Szrj case MODE_INT:
1048738fd1498Szrj /* Check that there are no leftover bits. */
1048838fd1498Szrj bitsize = GET_MODE_BITSIZE (as_a <scalar_int_mode> (mode));
1048938fd1498Szrj gcc_assert (bitsize % TREE_INT_CST_LOW (TYPE_SIZE (innertype)) == 0);
1049038fd1498Szrj nunits = bitsize / TREE_INT_CST_LOW (TYPE_SIZE (innertype));
1049138fd1498Szrj break;
1049238fd1498Szrj
1049338fd1498Szrj default:
1049438fd1498Szrj gcc_unreachable ();
1049538fd1498Szrj }
1049638fd1498Szrj
1049738fd1498Szrj return make_vector_type (innertype, nunits, mode);
1049838fd1498Szrj }
1049938fd1498Szrj
1050038fd1498Szrj /* Similarly, but takes the inner type and number of units, which must be
1050138fd1498Szrj a power of two. */
1050238fd1498Szrj
1050338fd1498Szrj tree
build_vector_type(tree innertype,poly_int64 nunits)1050438fd1498Szrj build_vector_type (tree innertype, poly_int64 nunits)
1050538fd1498Szrj {
1050638fd1498Szrj return make_vector_type (innertype, nunits, VOIDmode);
1050738fd1498Szrj }
1050838fd1498Szrj
1050938fd1498Szrj /* Build truth vector with specified length and number of units. */
1051038fd1498Szrj
1051138fd1498Szrj tree
build_truth_vector_type(poly_uint64 nunits,poly_uint64 vector_size)1051238fd1498Szrj build_truth_vector_type (poly_uint64 nunits, poly_uint64 vector_size)
1051338fd1498Szrj {
1051438fd1498Szrj machine_mode mask_mode
1051538fd1498Szrj = targetm.vectorize.get_mask_mode (nunits, vector_size).else_blk ();
1051638fd1498Szrj
1051738fd1498Szrj poly_uint64 vsize;
1051838fd1498Szrj if (mask_mode == BLKmode)
1051938fd1498Szrj vsize = vector_size * BITS_PER_UNIT;
1052038fd1498Szrj else
1052138fd1498Szrj vsize = GET_MODE_BITSIZE (mask_mode);
1052238fd1498Szrj
1052338fd1498Szrj unsigned HOST_WIDE_INT esize = vector_element_size (vsize, nunits);
1052438fd1498Szrj
1052538fd1498Szrj tree bool_type = build_nonstandard_boolean_type (esize);
1052638fd1498Szrj
1052738fd1498Szrj return make_vector_type (bool_type, nunits, mask_mode);
1052838fd1498Szrj }
1052938fd1498Szrj
1053038fd1498Szrj /* Returns a vector type corresponding to a comparison of VECTYPE. */
1053138fd1498Szrj
1053238fd1498Szrj tree
build_same_sized_truth_vector_type(tree vectype)1053338fd1498Szrj build_same_sized_truth_vector_type (tree vectype)
1053438fd1498Szrj {
1053538fd1498Szrj if (VECTOR_BOOLEAN_TYPE_P (vectype))
1053638fd1498Szrj return vectype;
1053738fd1498Szrj
1053838fd1498Szrj poly_uint64 size = GET_MODE_SIZE (TYPE_MODE (vectype));
1053938fd1498Szrj
1054038fd1498Szrj if (known_eq (size, 0U))
1054138fd1498Szrj size = tree_to_uhwi (TYPE_SIZE_UNIT (vectype));
1054238fd1498Szrj
1054338fd1498Szrj return build_truth_vector_type (TYPE_VECTOR_SUBPARTS (vectype), size);
1054438fd1498Szrj }
1054538fd1498Szrj
1054638fd1498Szrj /* Similarly, but builds a variant type with TYPE_VECTOR_OPAQUE set. */
1054738fd1498Szrj
1054838fd1498Szrj tree
build_opaque_vector_type(tree innertype,poly_int64 nunits)1054938fd1498Szrj build_opaque_vector_type (tree innertype, poly_int64 nunits)
1055038fd1498Szrj {
1055138fd1498Szrj tree t = make_vector_type (innertype, nunits, VOIDmode);
1055238fd1498Szrj tree cand;
1055338fd1498Szrj /* We always build the non-opaque variant before the opaque one,
1055438fd1498Szrj so if it already exists, it is TYPE_NEXT_VARIANT of this one. */
1055538fd1498Szrj cand = TYPE_NEXT_VARIANT (t);
1055638fd1498Szrj if (cand
1055738fd1498Szrj && TYPE_VECTOR_OPAQUE (cand)
1055838fd1498Szrj && check_qualified_type (cand, t, TYPE_QUALS (t)))
1055938fd1498Szrj return cand;
1056038fd1498Szrj /* Othewise build a variant type and make sure to queue it after
1056138fd1498Szrj the non-opaque type. */
1056238fd1498Szrj cand = build_distinct_type_copy (t);
1056338fd1498Szrj TYPE_VECTOR_OPAQUE (cand) = true;
1056438fd1498Szrj TYPE_CANONICAL (cand) = TYPE_CANONICAL (t);
1056538fd1498Szrj TYPE_NEXT_VARIANT (cand) = TYPE_NEXT_VARIANT (t);
1056638fd1498Szrj TYPE_NEXT_VARIANT (t) = cand;
1056738fd1498Szrj TYPE_MAIN_VARIANT (cand) = TYPE_MAIN_VARIANT (t);
1056838fd1498Szrj return cand;
1056938fd1498Szrj }
1057038fd1498Szrj
1057138fd1498Szrj /* Return the value of element I of VECTOR_CST T as a wide_int. */
1057238fd1498Szrj
1057338fd1498Szrj wide_int
vector_cst_int_elt(const_tree t,unsigned int i)1057438fd1498Szrj vector_cst_int_elt (const_tree t, unsigned int i)
1057538fd1498Szrj {
1057638fd1498Szrj /* First handle elements that are directly encoded. */
1057738fd1498Szrj unsigned int encoded_nelts = vector_cst_encoded_nelts (t);
1057838fd1498Szrj if (i < encoded_nelts)
1057938fd1498Szrj return wi::to_wide (VECTOR_CST_ENCODED_ELT (t, i));
1058038fd1498Szrj
1058138fd1498Szrj /* Identify the pattern that contains element I and work out the index of
1058238fd1498Szrj the last encoded element for that pattern. */
1058338fd1498Szrj unsigned int npatterns = VECTOR_CST_NPATTERNS (t);
1058438fd1498Szrj unsigned int pattern = i % npatterns;
1058538fd1498Szrj unsigned int count = i / npatterns;
1058638fd1498Szrj unsigned int final_i = encoded_nelts - npatterns + pattern;
1058738fd1498Szrj
1058838fd1498Szrj /* If there are no steps, the final encoded value is the right one. */
1058938fd1498Szrj if (!VECTOR_CST_STEPPED_P (t))
1059038fd1498Szrj return wi::to_wide (VECTOR_CST_ENCODED_ELT (t, final_i));
1059138fd1498Szrj
1059238fd1498Szrj /* Otherwise work out the value from the last two encoded elements. */
1059338fd1498Szrj tree v1 = VECTOR_CST_ENCODED_ELT (t, final_i - npatterns);
1059438fd1498Szrj tree v2 = VECTOR_CST_ENCODED_ELT (t, final_i);
1059538fd1498Szrj wide_int diff = wi::to_wide (v2) - wi::to_wide (v1);
1059638fd1498Szrj return wi::to_wide (v2) + (count - 2) * diff;
1059738fd1498Szrj }
1059838fd1498Szrj
1059938fd1498Szrj /* Return the value of element I of VECTOR_CST T. */
1060038fd1498Szrj
1060138fd1498Szrj tree
vector_cst_elt(const_tree t,unsigned int i)1060238fd1498Szrj vector_cst_elt (const_tree t, unsigned int i)
1060338fd1498Szrj {
1060438fd1498Szrj /* First handle elements that are directly encoded. */
1060538fd1498Szrj unsigned int encoded_nelts = vector_cst_encoded_nelts (t);
1060638fd1498Szrj if (i < encoded_nelts)
1060738fd1498Szrj return VECTOR_CST_ENCODED_ELT (t, i);
1060838fd1498Szrj
1060938fd1498Szrj /* If there are no steps, the final encoded value is the right one. */
1061038fd1498Szrj if (!VECTOR_CST_STEPPED_P (t))
1061138fd1498Szrj {
1061238fd1498Szrj /* Identify the pattern that contains element I and work out the index of
1061338fd1498Szrj the last encoded element for that pattern. */
1061438fd1498Szrj unsigned int npatterns = VECTOR_CST_NPATTERNS (t);
1061538fd1498Szrj unsigned int pattern = i % npatterns;
1061638fd1498Szrj unsigned int final_i = encoded_nelts - npatterns + pattern;
1061738fd1498Szrj return VECTOR_CST_ENCODED_ELT (t, final_i);
1061838fd1498Szrj }
1061938fd1498Szrj
1062038fd1498Szrj /* Otherwise work out the value from the last two encoded elements. */
1062138fd1498Szrj return wide_int_to_tree (TREE_TYPE (TREE_TYPE (t)),
1062238fd1498Szrj vector_cst_int_elt (t, i));
1062338fd1498Szrj }
1062438fd1498Szrj
1062538fd1498Szrj /* Given an initializer INIT, return TRUE if INIT is zero or some
1062638fd1498Szrj aggregate of zeros. Otherwise return FALSE. */
1062738fd1498Szrj bool
initializer_zerop(const_tree init)1062838fd1498Szrj initializer_zerop (const_tree init)
1062938fd1498Szrj {
1063038fd1498Szrj tree elt;
1063138fd1498Szrj
1063238fd1498Szrj STRIP_NOPS (init);
1063338fd1498Szrj
1063438fd1498Szrj switch (TREE_CODE (init))
1063538fd1498Szrj {
1063638fd1498Szrj case INTEGER_CST:
1063738fd1498Szrj return integer_zerop (init);
1063838fd1498Szrj
1063938fd1498Szrj case REAL_CST:
1064038fd1498Szrj /* ??? Note that this is not correct for C4X float formats. There,
1064138fd1498Szrj a bit pattern of all zeros is 1.0; 0.0 is encoded with the most
1064238fd1498Szrj negative exponent. */
1064338fd1498Szrj return real_zerop (init)
1064438fd1498Szrj && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (init));
1064538fd1498Szrj
1064638fd1498Szrj case FIXED_CST:
1064738fd1498Szrj return fixed_zerop (init);
1064838fd1498Szrj
1064938fd1498Szrj case COMPLEX_CST:
1065038fd1498Szrj return integer_zerop (init)
1065138fd1498Szrj || (real_zerop (init)
1065238fd1498Szrj && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_REALPART (init)))
1065338fd1498Szrj && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_IMAGPART (init))));
1065438fd1498Szrj
1065538fd1498Szrj case VECTOR_CST:
1065638fd1498Szrj return (VECTOR_CST_NPATTERNS (init) == 1
1065738fd1498Szrj && VECTOR_CST_DUPLICATE_P (init)
1065838fd1498Szrj && initializer_zerop (VECTOR_CST_ENCODED_ELT (init, 0)));
1065938fd1498Szrj
1066038fd1498Szrj case CONSTRUCTOR:
1066138fd1498Szrj {
1066238fd1498Szrj unsigned HOST_WIDE_INT idx;
1066338fd1498Szrj
1066438fd1498Szrj if (TREE_CLOBBER_P (init))
1066538fd1498Szrj return false;
1066638fd1498Szrj FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), idx, elt)
1066738fd1498Szrj if (!initializer_zerop (elt))
1066838fd1498Szrj return false;
1066938fd1498Szrj return true;
1067038fd1498Szrj }
1067138fd1498Szrj
1067238fd1498Szrj case STRING_CST:
1067338fd1498Szrj {
1067438fd1498Szrj int i;
1067538fd1498Szrj
1067638fd1498Szrj /* We need to loop through all elements to handle cases like
1067738fd1498Szrj "\0" and "\0foobar". */
1067838fd1498Szrj for (i = 0; i < TREE_STRING_LENGTH (init); ++i)
1067938fd1498Szrj if (TREE_STRING_POINTER (init)[i] != '\0')
1068038fd1498Szrj return false;
1068138fd1498Szrj
1068238fd1498Szrj return true;
1068338fd1498Szrj }
1068438fd1498Szrj
1068538fd1498Szrj default:
1068638fd1498Szrj return false;
1068738fd1498Szrj }
1068838fd1498Szrj }
1068938fd1498Szrj
1069038fd1498Szrj /* Check if vector VEC consists of all the equal elements and
1069138fd1498Szrj that the number of elements corresponds to the type of VEC.
1069238fd1498Szrj The function returns first element of the vector
1069338fd1498Szrj or NULL_TREE if the vector is not uniform. */
1069438fd1498Szrj tree
uniform_vector_p(const_tree vec)1069538fd1498Szrj uniform_vector_p (const_tree vec)
1069638fd1498Szrj {
1069738fd1498Szrj tree first, t;
1069838fd1498Szrj unsigned HOST_WIDE_INT i, nelts;
1069938fd1498Szrj
1070038fd1498Szrj if (vec == NULL_TREE)
1070138fd1498Szrj return NULL_TREE;
1070238fd1498Szrj
1070338fd1498Szrj gcc_assert (VECTOR_TYPE_P (TREE_TYPE (vec)));
1070438fd1498Szrj
1070538fd1498Szrj if (TREE_CODE (vec) == VEC_DUPLICATE_EXPR)
1070638fd1498Szrj return TREE_OPERAND (vec, 0);
1070738fd1498Szrj
1070838fd1498Szrj else if (TREE_CODE (vec) == VECTOR_CST)
1070938fd1498Szrj {
1071038fd1498Szrj if (VECTOR_CST_NPATTERNS (vec) == 1 && VECTOR_CST_DUPLICATE_P (vec))
1071138fd1498Szrj return VECTOR_CST_ENCODED_ELT (vec, 0);
1071238fd1498Szrj return NULL_TREE;
1071338fd1498Szrj }
1071438fd1498Szrj
1071538fd1498Szrj else if (TREE_CODE (vec) == CONSTRUCTOR
1071638fd1498Szrj && TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec)).is_constant (&nelts))
1071738fd1498Szrj {
1071838fd1498Szrj first = error_mark_node;
1071938fd1498Szrj
1072038fd1498Szrj FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (vec), i, t)
1072138fd1498Szrj {
1072238fd1498Szrj if (i == 0)
1072338fd1498Szrj {
1072438fd1498Szrj first = t;
1072538fd1498Szrj continue;
1072638fd1498Szrj }
1072738fd1498Szrj if (!operand_equal_p (first, t, 0))
1072838fd1498Szrj return NULL_TREE;
1072938fd1498Szrj }
1073038fd1498Szrj if (i != nelts)
1073138fd1498Szrj return NULL_TREE;
1073238fd1498Szrj
1073338fd1498Szrj return first;
1073438fd1498Szrj }
1073538fd1498Szrj
1073638fd1498Szrj return NULL_TREE;
1073738fd1498Szrj }
1073838fd1498Szrj
1073938fd1498Szrj /* Build an empty statement at location LOC. */
1074038fd1498Szrj
1074138fd1498Szrj tree
build_empty_stmt(location_t loc)1074238fd1498Szrj build_empty_stmt (location_t loc)
1074338fd1498Szrj {
1074438fd1498Szrj tree t = build1 (NOP_EXPR, void_type_node, size_zero_node);
1074538fd1498Szrj SET_EXPR_LOCATION (t, loc);
1074638fd1498Szrj return t;
1074738fd1498Szrj }
1074838fd1498Szrj
1074938fd1498Szrj
1075038fd1498Szrj /* Build an OpenMP clause with code CODE. LOC is the location of the
1075138fd1498Szrj clause. */
1075238fd1498Szrj
1075338fd1498Szrj tree
build_omp_clause(location_t loc,enum omp_clause_code code)1075438fd1498Szrj build_omp_clause (location_t loc, enum omp_clause_code code)
1075538fd1498Szrj {
1075638fd1498Szrj tree t;
1075738fd1498Szrj int size, length;
1075838fd1498Szrj
1075938fd1498Szrj length = omp_clause_num_ops[code];
1076038fd1498Szrj size = (sizeof (struct tree_omp_clause) + (length - 1) * sizeof (tree));
1076138fd1498Szrj
1076238fd1498Szrj record_node_allocation_statistics (OMP_CLAUSE, size);
1076338fd1498Szrj
1076438fd1498Szrj t = (tree) ggc_internal_alloc (size);
1076538fd1498Szrj memset (t, 0, size);
1076638fd1498Szrj TREE_SET_CODE (t, OMP_CLAUSE);
1076738fd1498Szrj OMP_CLAUSE_SET_CODE (t, code);
1076838fd1498Szrj OMP_CLAUSE_LOCATION (t) = loc;
1076938fd1498Szrj
1077038fd1498Szrj return t;
1077138fd1498Szrj }
1077238fd1498Szrj
1077338fd1498Szrj /* Build a tcc_vl_exp object with code CODE and room for LEN operands. LEN
1077438fd1498Szrj includes the implicit operand count in TREE_OPERAND 0, and so must be >= 1.
1077538fd1498Szrj Except for the CODE and operand count field, other storage for the
1077638fd1498Szrj object is initialized to zeros. */
1077738fd1498Szrj
1077838fd1498Szrj tree
build_vl_exp(enum tree_code code,int len MEM_STAT_DECL)1077938fd1498Szrj build_vl_exp (enum tree_code code, int len MEM_STAT_DECL)
1078038fd1498Szrj {
1078138fd1498Szrj tree t;
1078238fd1498Szrj int length = (len - 1) * sizeof (tree) + sizeof (struct tree_exp);
1078338fd1498Szrj
1078438fd1498Szrj gcc_assert (TREE_CODE_CLASS (code) == tcc_vl_exp);
1078538fd1498Szrj gcc_assert (len >= 1);
1078638fd1498Szrj
1078738fd1498Szrj record_node_allocation_statistics (code, length);
1078838fd1498Szrj
1078938fd1498Szrj t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT);
1079038fd1498Szrj
1079138fd1498Szrj TREE_SET_CODE (t, code);
1079238fd1498Szrj
1079338fd1498Szrj /* Can't use TREE_OPERAND to store the length because if checking is
1079438fd1498Szrj enabled, it will try to check the length before we store it. :-P */
1079538fd1498Szrj t->exp.operands[0] = build_int_cst (sizetype, len);
1079638fd1498Szrj
1079738fd1498Szrj return t;
1079838fd1498Szrj }
1079938fd1498Szrj
1080038fd1498Szrj /* Helper function for build_call_* functions; build a CALL_EXPR with
1080138fd1498Szrj indicated RETURN_TYPE, FN, and NARGS, but do not initialize any of
1080238fd1498Szrj the argument slots. */
1080338fd1498Szrj
1080438fd1498Szrj static tree
build_call_1(tree return_type,tree fn,int nargs)1080538fd1498Szrj build_call_1 (tree return_type, tree fn, int nargs)
1080638fd1498Szrj {
1080738fd1498Szrj tree t;
1080838fd1498Szrj
1080938fd1498Szrj t = build_vl_exp (CALL_EXPR, nargs + 3);
1081038fd1498Szrj TREE_TYPE (t) = return_type;
1081138fd1498Szrj CALL_EXPR_FN (t) = fn;
1081238fd1498Szrj CALL_EXPR_STATIC_CHAIN (t) = NULL;
1081338fd1498Szrj
1081438fd1498Szrj return t;
1081538fd1498Szrj }
1081638fd1498Szrj
1081738fd1498Szrj /* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and
1081838fd1498Szrj FN and a null static chain slot. NARGS is the number of call arguments
1081938fd1498Szrj which are specified as "..." arguments. */
1082038fd1498Szrj
1082138fd1498Szrj tree
build_call_nary(tree return_type,tree fn,int nargs,...)1082238fd1498Szrj build_call_nary (tree return_type, tree fn, int nargs, ...)
1082338fd1498Szrj {
1082438fd1498Szrj tree ret;
1082538fd1498Szrj va_list args;
1082638fd1498Szrj va_start (args, nargs);
1082738fd1498Szrj ret = build_call_valist (return_type, fn, nargs, args);
1082838fd1498Szrj va_end (args);
1082938fd1498Szrj return ret;
1083038fd1498Szrj }
1083138fd1498Szrj
1083238fd1498Szrj /* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and
1083338fd1498Szrj FN and a null static chain slot. NARGS is the number of call arguments
1083438fd1498Szrj which are specified as a va_list ARGS. */
1083538fd1498Szrj
1083638fd1498Szrj tree
build_call_valist(tree return_type,tree fn,int nargs,va_list args)1083738fd1498Szrj build_call_valist (tree return_type, tree fn, int nargs, va_list args)
1083838fd1498Szrj {
1083938fd1498Szrj tree t;
1084038fd1498Szrj int i;
1084138fd1498Szrj
1084238fd1498Szrj t = build_call_1 (return_type, fn, nargs);
1084338fd1498Szrj for (i = 0; i < nargs; i++)
1084438fd1498Szrj CALL_EXPR_ARG (t, i) = va_arg (args, tree);
1084538fd1498Szrj process_call_operands (t);
1084638fd1498Szrj return t;
1084738fd1498Szrj }
1084838fd1498Szrj
1084938fd1498Szrj /* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and
1085038fd1498Szrj FN and a null static chain slot. NARGS is the number of call arguments
1085138fd1498Szrj which are specified as a tree array ARGS. */
1085238fd1498Szrj
1085338fd1498Szrj tree
build_call_array_loc(location_t loc,tree return_type,tree fn,int nargs,const tree * args)1085438fd1498Szrj build_call_array_loc (location_t loc, tree return_type, tree fn,
1085538fd1498Szrj int nargs, const tree *args)
1085638fd1498Szrj {
1085738fd1498Szrj tree t;
1085838fd1498Szrj int i;
1085938fd1498Szrj
1086038fd1498Szrj t = build_call_1 (return_type, fn, nargs);
1086138fd1498Szrj for (i = 0; i < nargs; i++)
1086238fd1498Szrj CALL_EXPR_ARG (t, i) = args[i];
1086338fd1498Szrj process_call_operands (t);
1086438fd1498Szrj SET_EXPR_LOCATION (t, loc);
1086538fd1498Szrj return t;
1086638fd1498Szrj }
1086738fd1498Szrj
1086838fd1498Szrj /* Like build_call_array, but takes a vec. */
1086938fd1498Szrj
1087038fd1498Szrj tree
build_call_vec(tree return_type,tree fn,vec<tree,va_gc> * args)1087138fd1498Szrj build_call_vec (tree return_type, tree fn, vec<tree, va_gc> *args)
1087238fd1498Szrj {
1087338fd1498Szrj tree ret, t;
1087438fd1498Szrj unsigned int ix;
1087538fd1498Szrj
1087638fd1498Szrj ret = build_call_1 (return_type, fn, vec_safe_length (args));
1087738fd1498Szrj FOR_EACH_VEC_SAFE_ELT (args, ix, t)
1087838fd1498Szrj CALL_EXPR_ARG (ret, ix) = t;
1087938fd1498Szrj process_call_operands (ret);
1088038fd1498Szrj return ret;
1088138fd1498Szrj }
1088238fd1498Szrj
1088338fd1498Szrj /* Conveniently construct a function call expression. FNDECL names the
1088438fd1498Szrj function to be called and N arguments are passed in the array
1088538fd1498Szrj ARGARRAY. */
1088638fd1498Szrj
1088738fd1498Szrj tree
build_call_expr_loc_array(location_t loc,tree fndecl,int n,tree * argarray)1088838fd1498Szrj build_call_expr_loc_array (location_t loc, tree fndecl, int n, tree *argarray)
1088938fd1498Szrj {
1089038fd1498Szrj tree fntype = TREE_TYPE (fndecl);
1089138fd1498Szrj tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
1089238fd1498Szrj
1089338fd1498Szrj return fold_build_call_array_loc (loc, TREE_TYPE (fntype), fn, n, argarray);
1089438fd1498Szrj }
1089538fd1498Szrj
1089638fd1498Szrj /* Conveniently construct a function call expression. FNDECL names the
1089738fd1498Szrj function to be called and the arguments are passed in the vector
1089838fd1498Szrj VEC. */
1089938fd1498Szrj
1090038fd1498Szrj tree
build_call_expr_loc_vec(location_t loc,tree fndecl,vec<tree,va_gc> * vec)1090138fd1498Szrj build_call_expr_loc_vec (location_t loc, tree fndecl, vec<tree, va_gc> *vec)
1090238fd1498Szrj {
1090338fd1498Szrj return build_call_expr_loc_array (loc, fndecl, vec_safe_length (vec),
1090438fd1498Szrj vec_safe_address (vec));
1090538fd1498Szrj }
1090638fd1498Szrj
1090738fd1498Szrj
1090838fd1498Szrj /* Conveniently construct a function call expression. FNDECL names the
1090938fd1498Szrj function to be called, N is the number of arguments, and the "..."
1091038fd1498Szrj parameters are the argument expressions. */
1091138fd1498Szrj
1091238fd1498Szrj tree
build_call_expr_loc(location_t loc,tree fndecl,int n,...)1091338fd1498Szrj build_call_expr_loc (location_t loc, tree fndecl, int n, ...)
1091438fd1498Szrj {
1091538fd1498Szrj va_list ap;
1091638fd1498Szrj tree *argarray = XALLOCAVEC (tree, n);
1091738fd1498Szrj int i;
1091838fd1498Szrj
1091938fd1498Szrj va_start (ap, n);
1092038fd1498Szrj for (i = 0; i < n; i++)
1092138fd1498Szrj argarray[i] = va_arg (ap, tree);
1092238fd1498Szrj va_end (ap);
1092338fd1498Szrj return build_call_expr_loc_array (loc, fndecl, n, argarray);
1092438fd1498Szrj }
1092538fd1498Szrj
1092638fd1498Szrj /* Like build_call_expr_loc (UNKNOWN_LOCATION, ...). Duplicated because
1092738fd1498Szrj varargs macros aren't supported by all bootstrap compilers. */
1092838fd1498Szrj
1092938fd1498Szrj tree
build_call_expr(tree fndecl,int n,...)1093038fd1498Szrj build_call_expr (tree fndecl, int n, ...)
1093138fd1498Szrj {
1093238fd1498Szrj va_list ap;
1093338fd1498Szrj tree *argarray = XALLOCAVEC (tree, n);
1093438fd1498Szrj int i;
1093538fd1498Szrj
1093638fd1498Szrj va_start (ap, n);
1093738fd1498Szrj for (i = 0; i < n; i++)
1093838fd1498Szrj argarray[i] = va_arg (ap, tree);
1093938fd1498Szrj va_end (ap);
1094038fd1498Szrj return build_call_expr_loc_array (UNKNOWN_LOCATION, fndecl, n, argarray);
1094138fd1498Szrj }
1094238fd1498Szrj
1094338fd1498Szrj /* Build an internal call to IFN, with arguments ARGS[0:N-1] and with return
1094438fd1498Szrj type TYPE. This is just like CALL_EXPR, except its CALL_EXPR_FN is NULL.
1094538fd1498Szrj It will get gimplified later into an ordinary internal function. */
1094638fd1498Szrj
1094738fd1498Szrj tree
build_call_expr_internal_loc_array(location_t loc,internal_fn ifn,tree type,int n,const tree * args)1094838fd1498Szrj build_call_expr_internal_loc_array (location_t loc, internal_fn ifn,
1094938fd1498Szrj tree type, int n, const tree *args)
1095038fd1498Szrj {
1095138fd1498Szrj tree t = build_call_1 (type, NULL_TREE, n);
1095238fd1498Szrj for (int i = 0; i < n; ++i)
1095338fd1498Szrj CALL_EXPR_ARG (t, i) = args[i];
1095438fd1498Szrj SET_EXPR_LOCATION (t, loc);
1095538fd1498Szrj CALL_EXPR_IFN (t) = ifn;
1095638fd1498Szrj return t;
1095738fd1498Szrj }
1095838fd1498Szrj
1095938fd1498Szrj /* Build internal call expression. This is just like CALL_EXPR, except
1096038fd1498Szrj its CALL_EXPR_FN is NULL. It will get gimplified later into ordinary
1096138fd1498Szrj internal function. */
1096238fd1498Szrj
1096338fd1498Szrj tree
build_call_expr_internal_loc(location_t loc,enum internal_fn ifn,tree type,int n,...)1096438fd1498Szrj build_call_expr_internal_loc (location_t loc, enum internal_fn ifn,
1096538fd1498Szrj tree type, int n, ...)
1096638fd1498Szrj {
1096738fd1498Szrj va_list ap;
1096838fd1498Szrj tree *argarray = XALLOCAVEC (tree, n);
1096938fd1498Szrj int i;
1097038fd1498Szrj
1097138fd1498Szrj va_start (ap, n);
1097238fd1498Szrj for (i = 0; i < n; i++)
1097338fd1498Szrj argarray[i] = va_arg (ap, tree);
1097438fd1498Szrj va_end (ap);
1097538fd1498Szrj return build_call_expr_internal_loc_array (loc, ifn, type, n, argarray);
1097638fd1498Szrj }
1097738fd1498Szrj
1097838fd1498Szrj /* Return a function call to FN, if the target is guaranteed to support it,
1097938fd1498Szrj or null otherwise.
1098038fd1498Szrj
1098138fd1498Szrj N is the number of arguments, passed in the "...", and TYPE is the
1098238fd1498Szrj type of the return value. */
1098338fd1498Szrj
1098438fd1498Szrj tree
maybe_build_call_expr_loc(location_t loc,combined_fn fn,tree type,int n,...)1098538fd1498Szrj maybe_build_call_expr_loc (location_t loc, combined_fn fn, tree type,
1098638fd1498Szrj int n, ...)
1098738fd1498Szrj {
1098838fd1498Szrj va_list ap;
1098938fd1498Szrj tree *argarray = XALLOCAVEC (tree, n);
1099038fd1498Szrj int i;
1099138fd1498Szrj
1099238fd1498Szrj va_start (ap, n);
1099338fd1498Szrj for (i = 0; i < n; i++)
1099438fd1498Szrj argarray[i] = va_arg (ap, tree);
1099538fd1498Szrj va_end (ap);
1099638fd1498Szrj if (internal_fn_p (fn))
1099738fd1498Szrj {
1099838fd1498Szrj internal_fn ifn = as_internal_fn (fn);
1099938fd1498Szrj if (direct_internal_fn_p (ifn))
1100038fd1498Szrj {
1100138fd1498Szrj tree_pair types = direct_internal_fn_types (ifn, type, argarray);
1100238fd1498Szrj if (!direct_internal_fn_supported_p (ifn, types,
1100338fd1498Szrj OPTIMIZE_FOR_BOTH))
1100438fd1498Szrj return NULL_TREE;
1100538fd1498Szrj }
1100638fd1498Szrj return build_call_expr_internal_loc_array (loc, ifn, type, n, argarray);
1100738fd1498Szrj }
1100838fd1498Szrj else
1100938fd1498Szrj {
1101038fd1498Szrj tree fndecl = builtin_decl_implicit (as_builtin_fn (fn));
1101138fd1498Szrj if (!fndecl)
1101238fd1498Szrj return NULL_TREE;
1101338fd1498Szrj return build_call_expr_loc_array (loc, fndecl, n, argarray);
1101438fd1498Szrj }
1101538fd1498Szrj }
1101638fd1498Szrj
1101738fd1498Szrj /* Return a function call to the appropriate builtin alloca variant.
1101838fd1498Szrj
1101938fd1498Szrj SIZE is the size to be allocated. ALIGN, if non-zero, is the requested
1102038fd1498Szrj alignment of the allocated area. MAX_SIZE, if non-negative, is an upper
1102138fd1498Szrj bound for SIZE in case it is not a fixed value. */
1102238fd1498Szrj
1102338fd1498Szrj tree
build_alloca_call_expr(tree size,unsigned int align,HOST_WIDE_INT max_size)1102438fd1498Szrj build_alloca_call_expr (tree size, unsigned int align, HOST_WIDE_INT max_size)
1102538fd1498Szrj {
1102638fd1498Szrj if (max_size >= 0)
1102738fd1498Szrj {
1102838fd1498Szrj tree t = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX);
1102938fd1498Szrj return
1103038fd1498Szrj build_call_expr (t, 3, size, size_int (align), size_int (max_size));
1103138fd1498Szrj }
1103238fd1498Szrj else if (align > 0)
1103338fd1498Szrj {
1103438fd1498Szrj tree t = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
1103538fd1498Szrj return build_call_expr (t, 2, size, size_int (align));
1103638fd1498Szrj }
1103738fd1498Szrj else
1103838fd1498Szrj {
1103938fd1498Szrj tree t = builtin_decl_explicit (BUILT_IN_ALLOCA);
1104038fd1498Szrj return build_call_expr (t, 1, size);
1104138fd1498Szrj }
1104238fd1498Szrj }
1104338fd1498Szrj
1104438fd1498Szrj /* Create a new constant string literal and return a char* pointer to it.
1104538fd1498Szrj The STRING_CST value is the LEN characters at STR. */
1104638fd1498Szrj tree
build_string_literal(int len,const char * str)1104738fd1498Szrj build_string_literal (int len, const char *str)
1104838fd1498Szrj {
1104938fd1498Szrj tree t, elem, index, type;
1105038fd1498Szrj
1105138fd1498Szrj t = build_string (len, str);
1105238fd1498Szrj elem = build_type_variant (char_type_node, 1, 0);
1105338fd1498Szrj index = build_index_type (size_int (len - 1));
1105438fd1498Szrj type = build_array_type (elem, index);
1105538fd1498Szrj TREE_TYPE (t) = type;
1105638fd1498Szrj TREE_CONSTANT (t) = 1;
1105738fd1498Szrj TREE_READONLY (t) = 1;
1105838fd1498Szrj TREE_STATIC (t) = 1;
1105938fd1498Szrj
1106038fd1498Szrj type = build_pointer_type (elem);
1106138fd1498Szrj t = build1 (ADDR_EXPR, type,
1106238fd1498Szrj build4 (ARRAY_REF, elem,
1106338fd1498Szrj t, integer_zero_node, NULL_TREE, NULL_TREE));
1106438fd1498Szrj return t;
1106538fd1498Szrj }
1106638fd1498Szrj
1106738fd1498Szrj
1106838fd1498Szrj
1106938fd1498Szrj /* Return true if T (assumed to be a DECL) must be assigned a memory
1107038fd1498Szrj location. */
1107138fd1498Szrj
1107238fd1498Szrj bool
needs_to_live_in_memory(const_tree t)1107338fd1498Szrj needs_to_live_in_memory (const_tree t)
1107438fd1498Szrj {
1107538fd1498Szrj return (TREE_ADDRESSABLE (t)
1107638fd1498Szrj || is_global_var (t)
1107738fd1498Szrj || (TREE_CODE (t) == RESULT_DECL
1107838fd1498Szrj && !DECL_BY_REFERENCE (t)
1107938fd1498Szrj && aggregate_value_p (t, current_function_decl)));
1108038fd1498Szrj }
1108138fd1498Szrj
1108238fd1498Szrj /* Return value of a constant X and sign-extend it. */
1108338fd1498Szrj
1108438fd1498Szrj HOST_WIDE_INT
int_cst_value(const_tree x)1108538fd1498Szrj int_cst_value (const_tree x)
1108638fd1498Szrj {
1108738fd1498Szrj unsigned bits = TYPE_PRECISION (TREE_TYPE (x));
1108838fd1498Szrj unsigned HOST_WIDE_INT val = TREE_INT_CST_LOW (x);
1108938fd1498Szrj
1109038fd1498Szrj /* Make sure the sign-extended value will fit in a HOST_WIDE_INT. */
1109138fd1498Szrj gcc_assert (cst_and_fits_in_hwi (x));
1109238fd1498Szrj
1109338fd1498Szrj if (bits < HOST_BITS_PER_WIDE_INT)
1109438fd1498Szrj {
1109538fd1498Szrj bool negative = ((val >> (bits - 1)) & 1) != 0;
1109638fd1498Szrj if (negative)
1109738fd1498Szrj val |= HOST_WIDE_INT_M1U << (bits - 1) << 1;
1109838fd1498Szrj else
1109938fd1498Szrj val &= ~(HOST_WIDE_INT_M1U << (bits - 1) << 1);
1110038fd1498Szrj }
1110138fd1498Szrj
1110238fd1498Szrj return val;
1110338fd1498Szrj }
1110438fd1498Szrj
1110538fd1498Szrj /* If TYPE is an integral or pointer type, return an integer type with
1110638fd1498Szrj the same precision which is unsigned iff UNSIGNEDP is true, or itself
1110738fd1498Szrj if TYPE is already an integer type of signedness UNSIGNEDP. */
1110838fd1498Szrj
1110938fd1498Szrj tree
signed_or_unsigned_type_for(int unsignedp,tree type)1111038fd1498Szrj signed_or_unsigned_type_for (int unsignedp, tree type)
1111138fd1498Szrj {
1111238fd1498Szrj if (TREE_CODE (type) == INTEGER_TYPE && TYPE_UNSIGNED (type) == unsignedp)
1111338fd1498Szrj return type;
1111438fd1498Szrj
1111538fd1498Szrj if (TREE_CODE (type) == VECTOR_TYPE)
1111638fd1498Szrj {
1111738fd1498Szrj tree inner = TREE_TYPE (type);
1111838fd1498Szrj tree inner2 = signed_or_unsigned_type_for (unsignedp, inner);
1111938fd1498Szrj if (!inner2)
1112038fd1498Szrj return NULL_TREE;
1112138fd1498Szrj if (inner == inner2)
1112238fd1498Szrj return type;
1112338fd1498Szrj return build_vector_type (inner2, TYPE_VECTOR_SUBPARTS (type));
1112438fd1498Szrj }
1112538fd1498Szrj
1112638fd1498Szrj if (!INTEGRAL_TYPE_P (type)
1112738fd1498Szrj && !POINTER_TYPE_P (type)
1112838fd1498Szrj && TREE_CODE (type) != OFFSET_TYPE)
1112938fd1498Szrj return NULL_TREE;
1113038fd1498Szrj
1113138fd1498Szrj return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
1113238fd1498Szrj }
1113338fd1498Szrj
1113438fd1498Szrj /* If TYPE is an integral or pointer type, return an integer type with
1113538fd1498Szrj the same precision which is unsigned, or itself if TYPE is already an
1113638fd1498Szrj unsigned integer type. */
1113738fd1498Szrj
1113838fd1498Szrj tree
unsigned_type_for(tree type)1113938fd1498Szrj unsigned_type_for (tree type)
1114038fd1498Szrj {
1114138fd1498Szrj return signed_or_unsigned_type_for (1, type);
1114238fd1498Szrj }
1114338fd1498Szrj
1114438fd1498Szrj /* If TYPE is an integral or pointer type, return an integer type with
1114538fd1498Szrj the same precision which is signed, or itself if TYPE is already a
1114638fd1498Szrj signed integer type. */
1114738fd1498Szrj
1114838fd1498Szrj tree
signed_type_for(tree type)1114938fd1498Szrj signed_type_for (tree type)
1115038fd1498Szrj {
1115138fd1498Szrj return signed_or_unsigned_type_for (0, type);
1115238fd1498Szrj }
1115338fd1498Szrj
1115438fd1498Szrj /* If TYPE is a vector type, return a signed integer vector type with the
1115538fd1498Szrj same width and number of subparts. Otherwise return boolean_type_node. */
1115638fd1498Szrj
1115738fd1498Szrj tree
truth_type_for(tree type)1115838fd1498Szrj truth_type_for (tree type)
1115938fd1498Szrj {
1116038fd1498Szrj if (TREE_CODE (type) == VECTOR_TYPE)
1116138fd1498Szrj {
1116238fd1498Szrj if (VECTOR_BOOLEAN_TYPE_P (type))
1116338fd1498Szrj return type;
1116438fd1498Szrj return build_truth_vector_type (TYPE_VECTOR_SUBPARTS (type),
1116538fd1498Szrj GET_MODE_SIZE (TYPE_MODE (type)));
1116638fd1498Szrj }
1116738fd1498Szrj else
1116838fd1498Szrj return boolean_type_node;
1116938fd1498Szrj }
1117038fd1498Szrj
1117138fd1498Szrj /* Returns the largest value obtainable by casting something in INNER type to
1117238fd1498Szrj OUTER type. */
1117338fd1498Szrj
1117438fd1498Szrj tree
upper_bound_in_type(tree outer,tree inner)1117538fd1498Szrj upper_bound_in_type (tree outer, tree inner)
1117638fd1498Szrj {
1117738fd1498Szrj unsigned int det = 0;
1117838fd1498Szrj unsigned oprec = TYPE_PRECISION (outer);
1117938fd1498Szrj unsigned iprec = TYPE_PRECISION (inner);
1118038fd1498Szrj unsigned prec;
1118138fd1498Szrj
1118238fd1498Szrj /* Compute a unique number for every combination. */
1118338fd1498Szrj det |= (oprec > iprec) ? 4 : 0;
1118438fd1498Szrj det |= TYPE_UNSIGNED (outer) ? 2 : 0;
1118538fd1498Szrj det |= TYPE_UNSIGNED (inner) ? 1 : 0;
1118638fd1498Szrj
1118738fd1498Szrj /* Determine the exponent to use. */
1118838fd1498Szrj switch (det)
1118938fd1498Szrj {
1119038fd1498Szrj case 0:
1119138fd1498Szrj case 1:
1119238fd1498Szrj /* oprec <= iprec, outer: signed, inner: don't care. */
1119338fd1498Szrj prec = oprec - 1;
1119438fd1498Szrj break;
1119538fd1498Szrj case 2:
1119638fd1498Szrj case 3:
1119738fd1498Szrj /* oprec <= iprec, outer: unsigned, inner: don't care. */
1119838fd1498Szrj prec = oprec;
1119938fd1498Szrj break;
1120038fd1498Szrj case 4:
1120138fd1498Szrj /* oprec > iprec, outer: signed, inner: signed. */
1120238fd1498Szrj prec = iprec - 1;
1120338fd1498Szrj break;
1120438fd1498Szrj case 5:
1120538fd1498Szrj /* oprec > iprec, outer: signed, inner: unsigned. */
1120638fd1498Szrj prec = iprec;
1120738fd1498Szrj break;
1120838fd1498Szrj case 6:
1120938fd1498Szrj /* oprec > iprec, outer: unsigned, inner: signed. */
1121038fd1498Szrj prec = oprec;
1121138fd1498Szrj break;
1121238fd1498Szrj case 7:
1121338fd1498Szrj /* oprec > iprec, outer: unsigned, inner: unsigned. */
1121438fd1498Szrj prec = iprec;
1121538fd1498Szrj break;
1121638fd1498Szrj default:
1121738fd1498Szrj gcc_unreachable ();
1121838fd1498Szrj }
1121938fd1498Szrj
1122038fd1498Szrj return wide_int_to_tree (outer,
1122138fd1498Szrj wi::mask (prec, false, TYPE_PRECISION (outer)));
1122238fd1498Szrj }
1122338fd1498Szrj
1122438fd1498Szrj /* Returns the smallest value obtainable by casting something in INNER type to
1122538fd1498Szrj OUTER type. */
1122638fd1498Szrj
1122738fd1498Szrj tree
lower_bound_in_type(tree outer,tree inner)1122838fd1498Szrj lower_bound_in_type (tree outer, tree inner)
1122938fd1498Szrj {
1123038fd1498Szrj unsigned oprec = TYPE_PRECISION (outer);
1123138fd1498Szrj unsigned iprec = TYPE_PRECISION (inner);
1123238fd1498Szrj
1123338fd1498Szrj /* If OUTER type is unsigned, we can definitely cast 0 to OUTER type
1123438fd1498Szrj and obtain 0. */
1123538fd1498Szrj if (TYPE_UNSIGNED (outer)
1123638fd1498Szrj /* If we are widening something of an unsigned type, OUTER type
1123738fd1498Szrj contains all values of INNER type. In particular, both INNER
1123838fd1498Szrj and OUTER types have zero in common. */
1123938fd1498Szrj || (oprec > iprec && TYPE_UNSIGNED (inner)))
1124038fd1498Szrj return build_int_cst (outer, 0);
1124138fd1498Szrj else
1124238fd1498Szrj {
1124338fd1498Szrj /* If we are widening a signed type to another signed type, we
1124438fd1498Szrj want to obtain -2^^(iprec-1). If we are keeping the
1124538fd1498Szrj precision or narrowing to a signed type, we want to obtain
1124638fd1498Szrj -2^(oprec-1). */
1124738fd1498Szrj unsigned prec = oprec > iprec ? iprec : oprec;
1124838fd1498Szrj return wide_int_to_tree (outer,
1124938fd1498Szrj wi::mask (prec - 1, true,
1125038fd1498Szrj TYPE_PRECISION (outer)));
1125138fd1498Szrj }
1125238fd1498Szrj }
1125338fd1498Szrj
1125438fd1498Szrj /* Return nonzero if two operands that are suitable for PHI nodes are
1125538fd1498Szrj necessarily equal. Specifically, both ARG0 and ARG1 must be either
1125638fd1498Szrj SSA_NAME or invariant. Note that this is strictly an optimization.
1125738fd1498Szrj That is, callers of this function can directly call operand_equal_p
1125838fd1498Szrj and get the same result, only slower. */
1125938fd1498Szrj
1126038fd1498Szrj int
operand_equal_for_phi_arg_p(const_tree arg0,const_tree arg1)1126138fd1498Szrj operand_equal_for_phi_arg_p (const_tree arg0, const_tree arg1)
1126238fd1498Szrj {
1126338fd1498Szrj if (arg0 == arg1)
1126438fd1498Szrj return 1;
1126538fd1498Szrj if (TREE_CODE (arg0) == SSA_NAME || TREE_CODE (arg1) == SSA_NAME)
1126638fd1498Szrj return 0;
1126738fd1498Szrj return operand_equal_p (arg0, arg1, 0);
1126838fd1498Szrj }
1126938fd1498Szrj
1127038fd1498Szrj /* Returns number of zeros at the end of binary representation of X. */
1127138fd1498Szrj
1127238fd1498Szrj tree
num_ending_zeros(const_tree x)1127338fd1498Szrj num_ending_zeros (const_tree x)
1127438fd1498Szrj {
1127538fd1498Szrj return build_int_cst (TREE_TYPE (x), wi::ctz (wi::to_wide (x)));
1127638fd1498Szrj }
1127738fd1498Szrj
1127838fd1498Szrj
1127938fd1498Szrj #define WALK_SUBTREE(NODE) \
1128038fd1498Szrj do \
1128138fd1498Szrj { \
1128238fd1498Szrj result = walk_tree_1 (&(NODE), func, data, pset, lh); \
1128338fd1498Szrj if (result) \
1128438fd1498Szrj return result; \
1128538fd1498Szrj } \
1128638fd1498Szrj while (0)
1128738fd1498Szrj
1128838fd1498Szrj /* This is a subroutine of walk_tree that walks field of TYPE that are to
1128938fd1498Szrj be walked whenever a type is seen in the tree. Rest of operands and return
1129038fd1498Szrj value are as for walk_tree. */
1129138fd1498Szrj
1129238fd1498Szrj static tree
walk_type_fields(tree type,walk_tree_fn func,void * data,hash_set<tree> * pset,walk_tree_lh lh)1129338fd1498Szrj walk_type_fields (tree type, walk_tree_fn func, void *data,
1129438fd1498Szrj hash_set<tree> *pset, walk_tree_lh lh)
1129538fd1498Szrj {
1129638fd1498Szrj tree result = NULL_TREE;
1129738fd1498Szrj
1129838fd1498Szrj switch (TREE_CODE (type))
1129938fd1498Szrj {
1130038fd1498Szrj case POINTER_TYPE:
1130138fd1498Szrj case REFERENCE_TYPE:
1130238fd1498Szrj case VECTOR_TYPE:
1130338fd1498Szrj /* We have to worry about mutually recursive pointers. These can't
1130438fd1498Szrj be written in C. They can in Ada. It's pathological, but
1130538fd1498Szrj there's an ACATS test (c38102a) that checks it. Deal with this
1130638fd1498Szrj by checking if we're pointing to another pointer, that one
1130738fd1498Szrj points to another pointer, that one does too, and we have no htab.
1130838fd1498Szrj If so, get a hash table. We check three levels deep to avoid
1130938fd1498Szrj the cost of the hash table if we don't need one. */
1131038fd1498Szrj if (POINTER_TYPE_P (TREE_TYPE (type))
1131138fd1498Szrj && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (type)))
1131238fd1498Szrj && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (TREE_TYPE (type))))
1131338fd1498Szrj && !pset)
1131438fd1498Szrj {
1131538fd1498Szrj result = walk_tree_without_duplicates (&TREE_TYPE (type),
1131638fd1498Szrj func, data);
1131738fd1498Szrj if (result)
1131838fd1498Szrj return result;
1131938fd1498Szrj
1132038fd1498Szrj break;
1132138fd1498Szrj }
1132238fd1498Szrj
1132338fd1498Szrj /* fall through */
1132438fd1498Szrj
1132538fd1498Szrj case COMPLEX_TYPE:
1132638fd1498Szrj WALK_SUBTREE (TREE_TYPE (type));
1132738fd1498Szrj break;
1132838fd1498Szrj
1132938fd1498Szrj case METHOD_TYPE:
1133038fd1498Szrj WALK_SUBTREE (TYPE_METHOD_BASETYPE (type));
1133138fd1498Szrj
1133238fd1498Szrj /* Fall through. */
1133338fd1498Szrj
1133438fd1498Szrj case FUNCTION_TYPE:
1133538fd1498Szrj WALK_SUBTREE (TREE_TYPE (type));
1133638fd1498Szrj {
1133738fd1498Szrj tree arg;
1133838fd1498Szrj
1133938fd1498Szrj /* We never want to walk into default arguments. */
1134038fd1498Szrj for (arg = TYPE_ARG_TYPES (type); arg; arg = TREE_CHAIN (arg))
1134138fd1498Szrj WALK_SUBTREE (TREE_VALUE (arg));
1134238fd1498Szrj }
1134338fd1498Szrj break;
1134438fd1498Szrj
1134538fd1498Szrj case ARRAY_TYPE:
1134638fd1498Szrj /* Don't follow this nodes's type if a pointer for fear that
1134738fd1498Szrj we'll have infinite recursion. If we have a PSET, then we
1134838fd1498Szrj need not fear. */
1134938fd1498Szrj if (pset
1135038fd1498Szrj || (!POINTER_TYPE_P (TREE_TYPE (type))
1135138fd1498Szrj && TREE_CODE (TREE_TYPE (type)) != OFFSET_TYPE))
1135238fd1498Szrj WALK_SUBTREE (TREE_TYPE (type));
1135338fd1498Szrj WALK_SUBTREE (TYPE_DOMAIN (type));
1135438fd1498Szrj break;
1135538fd1498Szrj
1135638fd1498Szrj case OFFSET_TYPE:
1135738fd1498Szrj WALK_SUBTREE (TREE_TYPE (type));
1135838fd1498Szrj WALK_SUBTREE (TYPE_OFFSET_BASETYPE (type));
1135938fd1498Szrj break;
1136038fd1498Szrj
1136138fd1498Szrj default:
1136238fd1498Szrj break;
1136338fd1498Szrj }
1136438fd1498Szrj
1136538fd1498Szrj return NULL_TREE;
1136638fd1498Szrj }
1136738fd1498Szrj
1136838fd1498Szrj /* Apply FUNC to all the sub-trees of TP in a pre-order traversal. FUNC is
1136938fd1498Szrj called with the DATA and the address of each sub-tree. If FUNC returns a
1137038fd1498Szrj non-NULL value, the traversal is stopped, and the value returned by FUNC
1137138fd1498Szrj is returned. If PSET is non-NULL it is used to record the nodes visited,
1137238fd1498Szrj and to avoid visiting a node more than once. */
1137338fd1498Szrj
1137438fd1498Szrj tree
walk_tree_1(tree * tp,walk_tree_fn func,void * data,hash_set<tree> * pset,walk_tree_lh lh)1137538fd1498Szrj walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
1137638fd1498Szrj hash_set<tree> *pset, walk_tree_lh lh)
1137738fd1498Szrj {
1137838fd1498Szrj enum tree_code code;
1137938fd1498Szrj int walk_subtrees;
1138038fd1498Szrj tree result;
1138138fd1498Szrj
1138238fd1498Szrj #define WALK_SUBTREE_TAIL(NODE) \
1138338fd1498Szrj do \
1138438fd1498Szrj { \
1138538fd1498Szrj tp = & (NODE); \
1138638fd1498Szrj goto tail_recurse; \
1138738fd1498Szrj } \
1138838fd1498Szrj while (0)
1138938fd1498Szrj
1139038fd1498Szrj tail_recurse:
1139138fd1498Szrj /* Skip empty subtrees. */
1139238fd1498Szrj if (!*tp)
1139338fd1498Szrj return NULL_TREE;
1139438fd1498Szrj
1139538fd1498Szrj /* Don't walk the same tree twice, if the user has requested
1139638fd1498Szrj that we avoid doing so. */
1139738fd1498Szrj if (pset && pset->add (*tp))
1139838fd1498Szrj return NULL_TREE;
1139938fd1498Szrj
1140038fd1498Szrj /* Call the function. */
1140138fd1498Szrj walk_subtrees = 1;
1140238fd1498Szrj result = (*func) (tp, &walk_subtrees, data);
1140338fd1498Szrj
1140438fd1498Szrj /* If we found something, return it. */
1140538fd1498Szrj if (result)
1140638fd1498Szrj return result;
1140738fd1498Szrj
1140838fd1498Szrj code = TREE_CODE (*tp);
1140938fd1498Szrj
1141038fd1498Szrj /* Even if we didn't, FUNC may have decided that there was nothing
1141138fd1498Szrj interesting below this point in the tree. */
1141238fd1498Szrj if (!walk_subtrees)
1141338fd1498Szrj {
1141438fd1498Szrj /* But we still need to check our siblings. */
1141538fd1498Szrj if (code == TREE_LIST)
1141638fd1498Szrj WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
1141738fd1498Szrj else if (code == OMP_CLAUSE)
1141838fd1498Szrj WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
1141938fd1498Szrj else
1142038fd1498Szrj return NULL_TREE;
1142138fd1498Szrj }
1142238fd1498Szrj
1142338fd1498Szrj if (lh)
1142438fd1498Szrj {
1142538fd1498Szrj result = (*lh) (tp, &walk_subtrees, func, data, pset);
1142638fd1498Szrj if (result || !walk_subtrees)
1142738fd1498Szrj return result;
1142838fd1498Szrj }
1142938fd1498Szrj
1143038fd1498Szrj switch (code)
1143138fd1498Szrj {
1143238fd1498Szrj case ERROR_MARK:
1143338fd1498Szrj case IDENTIFIER_NODE:
1143438fd1498Szrj case INTEGER_CST:
1143538fd1498Szrj case REAL_CST:
1143638fd1498Szrj case FIXED_CST:
1143738fd1498Szrj case VECTOR_CST:
1143838fd1498Szrj case STRING_CST:
1143938fd1498Szrj case BLOCK:
1144038fd1498Szrj case PLACEHOLDER_EXPR:
1144138fd1498Szrj case SSA_NAME:
1144238fd1498Szrj case FIELD_DECL:
1144338fd1498Szrj case RESULT_DECL:
1144438fd1498Szrj /* None of these have subtrees other than those already walked
1144538fd1498Szrj above. */
1144638fd1498Szrj break;
1144738fd1498Szrj
1144838fd1498Szrj case TREE_LIST:
1144938fd1498Szrj WALK_SUBTREE (TREE_VALUE (*tp));
1145038fd1498Szrj WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
1145138fd1498Szrj break;
1145238fd1498Szrj
1145338fd1498Szrj case TREE_VEC:
1145438fd1498Szrj {
1145538fd1498Szrj int len = TREE_VEC_LENGTH (*tp);
1145638fd1498Szrj
1145738fd1498Szrj if (len == 0)
1145838fd1498Szrj break;
1145938fd1498Szrj
1146038fd1498Szrj /* Walk all elements but the first. */
1146138fd1498Szrj while (--len)
1146238fd1498Szrj WALK_SUBTREE (TREE_VEC_ELT (*tp, len));
1146338fd1498Szrj
1146438fd1498Szrj /* Now walk the first one as a tail call. */
1146538fd1498Szrj WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0));
1146638fd1498Szrj }
1146738fd1498Szrj
1146838fd1498Szrj case COMPLEX_CST:
1146938fd1498Szrj WALK_SUBTREE (TREE_REALPART (*tp));
1147038fd1498Szrj WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp));
1147138fd1498Szrj
1147238fd1498Szrj case CONSTRUCTOR:
1147338fd1498Szrj {
1147438fd1498Szrj unsigned HOST_WIDE_INT idx;
1147538fd1498Szrj constructor_elt *ce;
1147638fd1498Szrj
1147738fd1498Szrj for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (*tp), idx, &ce);
1147838fd1498Szrj idx++)
1147938fd1498Szrj WALK_SUBTREE (ce->value);
1148038fd1498Szrj }
1148138fd1498Szrj break;
1148238fd1498Szrj
1148338fd1498Szrj case SAVE_EXPR:
1148438fd1498Szrj WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));
1148538fd1498Szrj
1148638fd1498Szrj case BIND_EXPR:
1148738fd1498Szrj {
1148838fd1498Szrj tree decl;
1148938fd1498Szrj for (decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl))
1149038fd1498Szrj {
1149138fd1498Szrj /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk
1149238fd1498Szrj into declarations that are just mentioned, rather than
1149338fd1498Szrj declared; they don't really belong to this part of the tree.
1149438fd1498Szrj And, we can see cycles: the initializer for a declaration
1149538fd1498Szrj can refer to the declaration itself. */
1149638fd1498Szrj WALK_SUBTREE (DECL_INITIAL (decl));
1149738fd1498Szrj WALK_SUBTREE (DECL_SIZE (decl));
1149838fd1498Szrj WALK_SUBTREE (DECL_SIZE_UNIT (decl));
1149938fd1498Szrj }
1150038fd1498Szrj WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp));
1150138fd1498Szrj }
1150238fd1498Szrj
1150338fd1498Szrj case STATEMENT_LIST:
1150438fd1498Szrj {
1150538fd1498Szrj tree_stmt_iterator i;
1150638fd1498Szrj for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i))
1150738fd1498Szrj WALK_SUBTREE (*tsi_stmt_ptr (i));
1150838fd1498Szrj }
1150938fd1498Szrj break;
1151038fd1498Szrj
1151138fd1498Szrj case OMP_CLAUSE:
1151238fd1498Szrj switch (OMP_CLAUSE_CODE (*tp))
1151338fd1498Szrj {
1151438fd1498Szrj case OMP_CLAUSE_GANG:
1151538fd1498Szrj case OMP_CLAUSE__GRIDDIM_:
1151638fd1498Szrj WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 1));
1151738fd1498Szrj /* FALLTHRU */
1151838fd1498Szrj
1151938fd1498Szrj case OMP_CLAUSE_ASYNC:
1152038fd1498Szrj case OMP_CLAUSE_WAIT:
1152138fd1498Szrj case OMP_CLAUSE_WORKER:
1152238fd1498Szrj case OMP_CLAUSE_VECTOR:
1152338fd1498Szrj case OMP_CLAUSE_NUM_GANGS:
1152438fd1498Szrj case OMP_CLAUSE_NUM_WORKERS:
1152538fd1498Szrj case OMP_CLAUSE_VECTOR_LENGTH:
1152638fd1498Szrj case OMP_CLAUSE_PRIVATE:
1152738fd1498Szrj case OMP_CLAUSE_SHARED:
1152838fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
1152938fd1498Szrj case OMP_CLAUSE_COPYIN:
1153038fd1498Szrj case OMP_CLAUSE_COPYPRIVATE:
1153138fd1498Szrj case OMP_CLAUSE_FINAL:
1153238fd1498Szrj case OMP_CLAUSE_IF:
1153338fd1498Szrj case OMP_CLAUSE_NUM_THREADS:
1153438fd1498Szrj case OMP_CLAUSE_SCHEDULE:
1153538fd1498Szrj case OMP_CLAUSE_UNIFORM:
1153638fd1498Szrj case OMP_CLAUSE_DEPEND:
1153738fd1498Szrj case OMP_CLAUSE_NUM_TEAMS:
1153838fd1498Szrj case OMP_CLAUSE_THREAD_LIMIT:
1153938fd1498Szrj case OMP_CLAUSE_DEVICE:
1154038fd1498Szrj case OMP_CLAUSE_DIST_SCHEDULE:
1154138fd1498Szrj case OMP_CLAUSE_SAFELEN:
1154238fd1498Szrj case OMP_CLAUSE_SIMDLEN:
1154338fd1498Szrj case OMP_CLAUSE_ORDERED:
1154438fd1498Szrj case OMP_CLAUSE_PRIORITY:
1154538fd1498Szrj case OMP_CLAUSE_GRAINSIZE:
1154638fd1498Szrj case OMP_CLAUSE_NUM_TASKS:
1154738fd1498Szrj case OMP_CLAUSE_HINT:
1154838fd1498Szrj case OMP_CLAUSE_TO_DECLARE:
1154938fd1498Szrj case OMP_CLAUSE_LINK:
1155038fd1498Szrj case OMP_CLAUSE_USE_DEVICE_PTR:
1155138fd1498Szrj case OMP_CLAUSE_IS_DEVICE_PTR:
1155238fd1498Szrj case OMP_CLAUSE__LOOPTEMP_:
1155338fd1498Szrj case OMP_CLAUSE__SIMDUID_:
1155438fd1498Szrj WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0));
1155538fd1498Szrj /* FALLTHRU */
1155638fd1498Szrj
1155738fd1498Szrj case OMP_CLAUSE_INDEPENDENT:
1155838fd1498Szrj case OMP_CLAUSE_NOWAIT:
1155938fd1498Szrj case OMP_CLAUSE_DEFAULT:
1156038fd1498Szrj case OMP_CLAUSE_UNTIED:
1156138fd1498Szrj case OMP_CLAUSE_MERGEABLE:
1156238fd1498Szrj case OMP_CLAUSE_PROC_BIND:
1156338fd1498Szrj case OMP_CLAUSE_INBRANCH:
1156438fd1498Szrj case OMP_CLAUSE_NOTINBRANCH:
1156538fd1498Szrj case OMP_CLAUSE_FOR:
1156638fd1498Szrj case OMP_CLAUSE_PARALLEL:
1156738fd1498Szrj case OMP_CLAUSE_SECTIONS:
1156838fd1498Szrj case OMP_CLAUSE_TASKGROUP:
1156938fd1498Szrj case OMP_CLAUSE_NOGROUP:
1157038fd1498Szrj case OMP_CLAUSE_THREADS:
1157138fd1498Szrj case OMP_CLAUSE_SIMD:
1157238fd1498Szrj case OMP_CLAUSE_DEFAULTMAP:
1157338fd1498Szrj case OMP_CLAUSE_AUTO:
1157438fd1498Szrj case OMP_CLAUSE_SEQ:
1157538fd1498Szrj case OMP_CLAUSE_TILE:
1157638fd1498Szrj case OMP_CLAUSE__SIMT_:
1157738fd1498Szrj WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
1157838fd1498Szrj
1157938fd1498Szrj case OMP_CLAUSE_LASTPRIVATE:
1158038fd1498Szrj WALK_SUBTREE (OMP_CLAUSE_DECL (*tp));
1158138fd1498Szrj WALK_SUBTREE (OMP_CLAUSE_LASTPRIVATE_STMT (*tp));
1158238fd1498Szrj WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
1158338fd1498Szrj
1158438fd1498Szrj case OMP_CLAUSE_COLLAPSE:
1158538fd1498Szrj {
1158638fd1498Szrj int i;
1158738fd1498Szrj for (i = 0; i < 3; i++)
1158838fd1498Szrj WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i));
1158938fd1498Szrj WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
1159038fd1498Szrj }
1159138fd1498Szrj
1159238fd1498Szrj case OMP_CLAUSE_LINEAR:
1159338fd1498Szrj WALK_SUBTREE (OMP_CLAUSE_DECL (*tp));
1159438fd1498Szrj WALK_SUBTREE (OMP_CLAUSE_LINEAR_STEP (*tp));
1159538fd1498Szrj WALK_SUBTREE (OMP_CLAUSE_LINEAR_STMT (*tp));
1159638fd1498Szrj WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
1159738fd1498Szrj
1159838fd1498Szrj case OMP_CLAUSE_ALIGNED:
1159938fd1498Szrj case OMP_CLAUSE_FROM:
1160038fd1498Szrj case OMP_CLAUSE_TO:
1160138fd1498Szrj case OMP_CLAUSE_MAP:
1160238fd1498Szrj case OMP_CLAUSE__CACHE_:
1160338fd1498Szrj WALK_SUBTREE (OMP_CLAUSE_DECL (*tp));
1160438fd1498Szrj WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 1));
1160538fd1498Szrj WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
1160638fd1498Szrj
1160738fd1498Szrj case OMP_CLAUSE_REDUCTION:
1160838fd1498Szrj {
1160938fd1498Szrj int i;
1161038fd1498Szrj for (i = 0; i < 5; i++)
1161138fd1498Szrj WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i));
1161238fd1498Szrj WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
1161338fd1498Szrj }
1161438fd1498Szrj
1161538fd1498Szrj default:
1161638fd1498Szrj gcc_unreachable ();
1161738fd1498Szrj }
1161838fd1498Szrj break;
1161938fd1498Szrj
1162038fd1498Szrj case TARGET_EXPR:
1162138fd1498Szrj {
1162238fd1498Szrj int i, len;
1162338fd1498Szrj
1162438fd1498Szrj /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same.
1162538fd1498Szrj But, we only want to walk once. */
1162638fd1498Szrj len = (TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) ? 2 : 3;
1162738fd1498Szrj for (i = 0; i < len; ++i)
1162838fd1498Szrj WALK_SUBTREE (TREE_OPERAND (*tp, i));
1162938fd1498Szrj WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len));
1163038fd1498Szrj }
1163138fd1498Szrj
1163238fd1498Szrj case DECL_EXPR:
1163338fd1498Szrj /* If this is a TYPE_DECL, walk into the fields of the type that it's
1163438fd1498Szrj defining. We only want to walk into these fields of a type in this
1163538fd1498Szrj case and not in the general case of a mere reference to the type.
1163638fd1498Szrj
1163738fd1498Szrj The criterion is as follows: if the field can be an expression, it
1163838fd1498Szrj must be walked only here. This should be in keeping with the fields
1163938fd1498Szrj that are directly gimplified in gimplify_type_sizes in order for the
1164038fd1498Szrj mark/copy-if-shared/unmark machinery of the gimplifier to work with
1164138fd1498Szrj variable-sized types.
1164238fd1498Szrj
1164338fd1498Szrj Note that DECLs get walked as part of processing the BIND_EXPR. */
1164438fd1498Szrj if (TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL)
1164538fd1498Szrj {
1164638fd1498Szrj tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp));
1164738fd1498Szrj if (TREE_CODE (*type_p) == ERROR_MARK)
1164838fd1498Szrj return NULL_TREE;
1164938fd1498Szrj
1165038fd1498Szrj /* Call the function for the type. See if it returns anything or
1165138fd1498Szrj doesn't want us to continue. If we are to continue, walk both
1165238fd1498Szrj the normal fields and those for the declaration case. */
1165338fd1498Szrj result = (*func) (type_p, &walk_subtrees, data);
1165438fd1498Szrj if (result || !walk_subtrees)
1165538fd1498Szrj return result;
1165638fd1498Szrj
1165738fd1498Szrj /* But do not walk a pointed-to type since it may itself need to
1165838fd1498Szrj be walked in the declaration case if it isn't anonymous. */
1165938fd1498Szrj if (!POINTER_TYPE_P (*type_p))
1166038fd1498Szrj {
1166138fd1498Szrj result = walk_type_fields (*type_p, func, data, pset, lh);
1166238fd1498Szrj if (result)
1166338fd1498Szrj return result;
1166438fd1498Szrj }
1166538fd1498Szrj
1166638fd1498Szrj /* If this is a record type, also walk the fields. */
1166738fd1498Szrj if (RECORD_OR_UNION_TYPE_P (*type_p))
1166838fd1498Szrj {
1166938fd1498Szrj tree field;
1167038fd1498Szrj
1167138fd1498Szrj for (field = TYPE_FIELDS (*type_p); field;
1167238fd1498Szrj field = DECL_CHAIN (field))
1167338fd1498Szrj {
1167438fd1498Szrj /* We'd like to look at the type of the field, but we can
1167538fd1498Szrj easily get infinite recursion. So assume it's pointed
1167638fd1498Szrj to elsewhere in the tree. Also, ignore things that
1167738fd1498Szrj aren't fields. */
1167838fd1498Szrj if (TREE_CODE (field) != FIELD_DECL)
1167938fd1498Szrj continue;
1168038fd1498Szrj
1168138fd1498Szrj WALK_SUBTREE (DECL_FIELD_OFFSET (field));
1168238fd1498Szrj WALK_SUBTREE (DECL_SIZE (field));
1168338fd1498Szrj WALK_SUBTREE (DECL_SIZE_UNIT (field));
1168438fd1498Szrj if (TREE_CODE (*type_p) == QUAL_UNION_TYPE)
1168538fd1498Szrj WALK_SUBTREE (DECL_QUALIFIER (field));
1168638fd1498Szrj }
1168738fd1498Szrj }
1168838fd1498Szrj
1168938fd1498Szrj /* Same for scalar types. */
1169038fd1498Szrj else if (TREE_CODE (*type_p) == BOOLEAN_TYPE
1169138fd1498Szrj || TREE_CODE (*type_p) == ENUMERAL_TYPE
1169238fd1498Szrj || TREE_CODE (*type_p) == INTEGER_TYPE
1169338fd1498Szrj || TREE_CODE (*type_p) == FIXED_POINT_TYPE
1169438fd1498Szrj || TREE_CODE (*type_p) == REAL_TYPE)
1169538fd1498Szrj {
1169638fd1498Szrj WALK_SUBTREE (TYPE_MIN_VALUE (*type_p));
1169738fd1498Szrj WALK_SUBTREE (TYPE_MAX_VALUE (*type_p));
1169838fd1498Szrj }
1169938fd1498Szrj
1170038fd1498Szrj WALK_SUBTREE (TYPE_SIZE (*type_p));
1170138fd1498Szrj WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (*type_p));
1170238fd1498Szrj }
1170338fd1498Szrj /* FALLTHRU */
1170438fd1498Szrj
1170538fd1498Szrj default:
1170638fd1498Szrj if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
1170738fd1498Szrj {
1170838fd1498Szrj int i, len;
1170938fd1498Szrj
1171038fd1498Szrj /* Walk over all the sub-trees of this operand. */
1171138fd1498Szrj len = TREE_OPERAND_LENGTH (*tp);
1171238fd1498Szrj
1171338fd1498Szrj /* Go through the subtrees. We need to do this in forward order so
1171438fd1498Szrj that the scope of a FOR_EXPR is handled properly. */
1171538fd1498Szrj if (len)
1171638fd1498Szrj {
1171738fd1498Szrj for (i = 0; i < len - 1; ++i)
1171838fd1498Szrj WALK_SUBTREE (TREE_OPERAND (*tp, i));
1171938fd1498Szrj WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1));
1172038fd1498Szrj }
1172138fd1498Szrj }
1172238fd1498Szrj /* If this is a type, walk the needed fields in the type. */
1172338fd1498Szrj else if (TYPE_P (*tp))
1172438fd1498Szrj return walk_type_fields (*tp, func, data, pset, lh);
1172538fd1498Szrj break;
1172638fd1498Szrj }
1172738fd1498Szrj
1172838fd1498Szrj /* We didn't find what we were looking for. */
1172938fd1498Szrj return NULL_TREE;
1173038fd1498Szrj
1173138fd1498Szrj #undef WALK_SUBTREE_TAIL
1173238fd1498Szrj }
1173338fd1498Szrj #undef WALK_SUBTREE
1173438fd1498Szrj
1173538fd1498Szrj /* Like walk_tree, but does not walk duplicate nodes more than once. */
1173638fd1498Szrj
1173738fd1498Szrj tree
walk_tree_without_duplicates_1(tree * tp,walk_tree_fn func,void * data,walk_tree_lh lh)1173838fd1498Szrj walk_tree_without_duplicates_1 (tree *tp, walk_tree_fn func, void *data,
1173938fd1498Szrj walk_tree_lh lh)
1174038fd1498Szrj {
1174138fd1498Szrj tree result;
1174238fd1498Szrj
1174338fd1498Szrj hash_set<tree> pset;
1174438fd1498Szrj result = walk_tree_1 (tp, func, data, &pset, lh);
1174538fd1498Szrj return result;
1174638fd1498Szrj }
1174738fd1498Szrj
1174838fd1498Szrj
1174938fd1498Szrj tree
tree_block(tree t)1175038fd1498Szrj tree_block (tree t)
1175138fd1498Szrj {
1175238fd1498Szrj const enum tree_code_class c = TREE_CODE_CLASS (TREE_CODE (t));
1175338fd1498Szrj
1175438fd1498Szrj if (IS_EXPR_CODE_CLASS (c))
1175538fd1498Szrj return LOCATION_BLOCK (t->exp.locus);
1175638fd1498Szrj gcc_unreachable ();
1175738fd1498Szrj return NULL;
1175838fd1498Szrj }
1175938fd1498Szrj
1176038fd1498Szrj void
tree_set_block(tree t,tree b)1176138fd1498Szrj tree_set_block (tree t, tree b)
1176238fd1498Szrj {
1176338fd1498Szrj const enum tree_code_class c = TREE_CODE_CLASS (TREE_CODE (t));
1176438fd1498Szrj
1176538fd1498Szrj if (IS_EXPR_CODE_CLASS (c))
1176638fd1498Szrj {
1176738fd1498Szrj t->exp.locus = set_block (t->exp.locus, b);
1176838fd1498Szrj }
1176938fd1498Szrj else
1177038fd1498Szrj gcc_unreachable ();
1177138fd1498Szrj }
1177238fd1498Szrj
1177338fd1498Szrj /* Create a nameless artificial label and put it in the current
1177438fd1498Szrj function context. The label has a location of LOC. Returns the
1177538fd1498Szrj newly created label. */
1177638fd1498Szrj
1177738fd1498Szrj tree
create_artificial_label(location_t loc)1177838fd1498Szrj create_artificial_label (location_t loc)
1177938fd1498Szrj {
1178038fd1498Szrj tree lab = build_decl (loc,
1178138fd1498Szrj LABEL_DECL, NULL_TREE, void_type_node);
1178238fd1498Szrj
1178338fd1498Szrj DECL_ARTIFICIAL (lab) = 1;
1178438fd1498Szrj DECL_IGNORED_P (lab) = 1;
1178538fd1498Szrj DECL_CONTEXT (lab) = current_function_decl;
1178638fd1498Szrj return lab;
1178738fd1498Szrj }
1178838fd1498Szrj
1178938fd1498Szrj /* Given a tree, try to return a useful variable name that we can use
1179038fd1498Szrj to prefix a temporary that is being assigned the value of the tree.
1179138fd1498Szrj I.E. given <temp> = &A, return A. */
1179238fd1498Szrj
1179338fd1498Szrj const char *
get_name(tree t)1179438fd1498Szrj get_name (tree t)
1179538fd1498Szrj {
1179638fd1498Szrj tree stripped_decl;
1179738fd1498Szrj
1179838fd1498Szrj stripped_decl = t;
1179938fd1498Szrj STRIP_NOPS (stripped_decl);
1180038fd1498Szrj if (DECL_P (stripped_decl) && DECL_NAME (stripped_decl))
1180138fd1498Szrj return IDENTIFIER_POINTER (DECL_NAME (stripped_decl));
1180238fd1498Szrj else if (TREE_CODE (stripped_decl) == SSA_NAME)
1180338fd1498Szrj {
1180438fd1498Szrj tree name = SSA_NAME_IDENTIFIER (stripped_decl);
1180538fd1498Szrj if (!name)
1180638fd1498Szrj return NULL;
1180738fd1498Szrj return IDENTIFIER_POINTER (name);
1180838fd1498Szrj }
1180938fd1498Szrj else
1181038fd1498Szrj {
1181138fd1498Szrj switch (TREE_CODE (stripped_decl))
1181238fd1498Szrj {
1181338fd1498Szrj case ADDR_EXPR:
1181438fd1498Szrj return get_name (TREE_OPERAND (stripped_decl, 0));
1181538fd1498Szrj default:
1181638fd1498Szrj return NULL;
1181738fd1498Szrj }
1181838fd1498Szrj }
1181938fd1498Szrj }
1182038fd1498Szrj
1182138fd1498Szrj /* Return true if TYPE has a variable argument list. */
1182238fd1498Szrj
1182338fd1498Szrj bool
stdarg_p(const_tree fntype)1182438fd1498Szrj stdarg_p (const_tree fntype)
1182538fd1498Szrj {
1182638fd1498Szrj function_args_iterator args_iter;
1182738fd1498Szrj tree n = NULL_TREE, t;
1182838fd1498Szrj
1182938fd1498Szrj if (!fntype)
1183038fd1498Szrj return false;
1183138fd1498Szrj
1183238fd1498Szrj FOREACH_FUNCTION_ARGS (fntype, t, args_iter)
1183338fd1498Szrj {
1183438fd1498Szrj n = t;
1183538fd1498Szrj }
1183638fd1498Szrj
1183738fd1498Szrj return n != NULL_TREE && n != void_type_node;
1183838fd1498Szrj }
1183938fd1498Szrj
1184038fd1498Szrj /* Return true if TYPE has a prototype. */
1184138fd1498Szrj
1184238fd1498Szrj bool
prototype_p(const_tree fntype)1184338fd1498Szrj prototype_p (const_tree fntype)
1184438fd1498Szrj {
1184538fd1498Szrj tree t;
1184638fd1498Szrj
1184738fd1498Szrj gcc_assert (fntype != NULL_TREE);
1184838fd1498Szrj
1184938fd1498Szrj t = TYPE_ARG_TYPES (fntype);
1185038fd1498Szrj return (t != NULL_TREE);
1185138fd1498Szrj }
1185238fd1498Szrj
1185338fd1498Szrj /* If BLOCK is inlined from an __attribute__((__artificial__))
1185438fd1498Szrj routine, return pointer to location from where it has been
1185538fd1498Szrj called. */
1185638fd1498Szrj location_t *
block_nonartificial_location(tree block)1185738fd1498Szrj block_nonartificial_location (tree block)
1185838fd1498Szrj {
1185938fd1498Szrj location_t *ret = NULL;
1186038fd1498Szrj
1186138fd1498Szrj while (block && TREE_CODE (block) == BLOCK
1186238fd1498Szrj && BLOCK_ABSTRACT_ORIGIN (block))
1186338fd1498Szrj {
1186438fd1498Szrj tree ao = BLOCK_ABSTRACT_ORIGIN (block);
1186538fd1498Szrj
1186638fd1498Szrj while (TREE_CODE (ao) == BLOCK
1186738fd1498Szrj && BLOCK_ABSTRACT_ORIGIN (ao)
1186838fd1498Szrj && BLOCK_ABSTRACT_ORIGIN (ao) != ao)
1186938fd1498Szrj ao = BLOCK_ABSTRACT_ORIGIN (ao);
1187038fd1498Szrj
1187138fd1498Szrj if (TREE_CODE (ao) == FUNCTION_DECL)
1187238fd1498Szrj {
1187338fd1498Szrj /* If AO is an artificial inline, point RET to the
1187438fd1498Szrj call site locus at which it has been inlined and continue
1187538fd1498Szrj the loop, in case AO's caller is also an artificial
1187638fd1498Szrj inline. */
1187738fd1498Szrj if (DECL_DECLARED_INLINE_P (ao)
1187838fd1498Szrj && lookup_attribute ("artificial", DECL_ATTRIBUTES (ao)))
1187938fd1498Szrj ret = &BLOCK_SOURCE_LOCATION (block);
1188038fd1498Szrj else
1188138fd1498Szrj break;
1188238fd1498Szrj }
1188338fd1498Szrj else if (TREE_CODE (ao) != BLOCK)
1188438fd1498Szrj break;
1188538fd1498Szrj
1188638fd1498Szrj block = BLOCK_SUPERCONTEXT (block);
1188738fd1498Szrj }
1188838fd1498Szrj return ret;
1188938fd1498Szrj }
1189038fd1498Szrj
1189138fd1498Szrj
1189238fd1498Szrj /* If EXP is inlined from an __attribute__((__artificial__))
1189338fd1498Szrj function, return the location of the original call expression. */
1189438fd1498Szrj
1189538fd1498Szrj location_t
tree_nonartificial_location(tree exp)1189638fd1498Szrj tree_nonartificial_location (tree exp)
1189738fd1498Szrj {
1189838fd1498Szrj location_t *loc = block_nonartificial_location (TREE_BLOCK (exp));
1189938fd1498Szrj
1190038fd1498Szrj if (loc)
1190138fd1498Szrj return *loc;
1190238fd1498Szrj else
1190338fd1498Szrj return EXPR_LOCATION (exp);
1190438fd1498Szrj }
1190538fd1498Szrj
1190638fd1498Szrj
1190738fd1498Szrj /* These are the hash table functions for the hash table of OPTIMIZATION_NODEq
1190838fd1498Szrj nodes. */
1190938fd1498Szrj
1191038fd1498Szrj /* Return the hash code X, an OPTIMIZATION_NODE or TARGET_OPTION code. */
1191138fd1498Szrj
1191238fd1498Szrj hashval_t
hash(tree x)1191338fd1498Szrj cl_option_hasher::hash (tree x)
1191438fd1498Szrj {
1191538fd1498Szrj const_tree const t = x;
1191638fd1498Szrj const char *p;
1191738fd1498Szrj size_t i;
1191838fd1498Szrj size_t len = 0;
1191938fd1498Szrj hashval_t hash = 0;
1192038fd1498Szrj
1192138fd1498Szrj if (TREE_CODE (t) == OPTIMIZATION_NODE)
1192238fd1498Szrj {
1192338fd1498Szrj p = (const char *)TREE_OPTIMIZATION (t);
1192438fd1498Szrj len = sizeof (struct cl_optimization);
1192538fd1498Szrj }
1192638fd1498Szrj
1192738fd1498Szrj else if (TREE_CODE (t) == TARGET_OPTION_NODE)
1192838fd1498Szrj return cl_target_option_hash (TREE_TARGET_OPTION (t));
1192938fd1498Szrj
1193038fd1498Szrj else
1193138fd1498Szrj gcc_unreachable ();
1193238fd1498Szrj
1193338fd1498Szrj /* assume most opt flags are just 0/1, some are 2-3, and a few might be
1193438fd1498Szrj something else. */
1193538fd1498Szrj for (i = 0; i < len; i++)
1193638fd1498Szrj if (p[i])
1193738fd1498Szrj hash = (hash << 4) ^ ((i << 2) | p[i]);
1193838fd1498Szrj
1193938fd1498Szrj return hash;
1194038fd1498Szrj }
1194138fd1498Szrj
1194238fd1498Szrj /* Return nonzero if the value represented by *X (an OPTIMIZATION or
1194338fd1498Szrj TARGET_OPTION tree node) is the same as that given by *Y, which is the
1194438fd1498Szrj same. */
1194538fd1498Szrj
1194638fd1498Szrj bool
equal(tree x,tree y)1194738fd1498Szrj cl_option_hasher::equal (tree x, tree y)
1194838fd1498Szrj {
1194938fd1498Szrj const_tree const xt = x;
1195038fd1498Szrj const_tree const yt = y;
1195138fd1498Szrj const char *xp;
1195238fd1498Szrj const char *yp;
1195338fd1498Szrj size_t len;
1195438fd1498Szrj
1195538fd1498Szrj if (TREE_CODE (xt) != TREE_CODE (yt))
1195638fd1498Szrj return 0;
1195738fd1498Szrj
1195838fd1498Szrj if (TREE_CODE (xt) == OPTIMIZATION_NODE)
1195938fd1498Szrj {
1196038fd1498Szrj xp = (const char *)TREE_OPTIMIZATION (xt);
1196138fd1498Szrj yp = (const char *)TREE_OPTIMIZATION (yt);
1196238fd1498Szrj len = sizeof (struct cl_optimization);
1196338fd1498Szrj }
1196438fd1498Szrj
1196538fd1498Szrj else if (TREE_CODE (xt) == TARGET_OPTION_NODE)
1196638fd1498Szrj {
1196738fd1498Szrj return cl_target_option_eq (TREE_TARGET_OPTION (xt),
1196838fd1498Szrj TREE_TARGET_OPTION (yt));
1196938fd1498Szrj }
1197038fd1498Szrj
1197138fd1498Szrj else
1197238fd1498Szrj gcc_unreachable ();
1197338fd1498Szrj
1197438fd1498Szrj return (memcmp (xp, yp, len) == 0);
1197538fd1498Szrj }
1197638fd1498Szrj
1197738fd1498Szrj /* Build an OPTIMIZATION_NODE based on the options in OPTS. */
1197838fd1498Szrj
1197938fd1498Szrj tree
build_optimization_node(struct gcc_options * opts)1198038fd1498Szrj build_optimization_node (struct gcc_options *opts)
1198138fd1498Szrj {
1198238fd1498Szrj tree t;
1198338fd1498Szrj
1198438fd1498Szrj /* Use the cache of optimization nodes. */
1198538fd1498Szrj
1198638fd1498Szrj cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node),
1198738fd1498Szrj opts);
1198838fd1498Szrj
1198938fd1498Szrj tree *slot = cl_option_hash_table->find_slot (cl_optimization_node, INSERT);
1199038fd1498Szrj t = *slot;
1199138fd1498Szrj if (!t)
1199238fd1498Szrj {
1199338fd1498Szrj /* Insert this one into the hash table. */
1199438fd1498Szrj t = cl_optimization_node;
1199538fd1498Szrj *slot = t;
1199638fd1498Szrj
1199738fd1498Szrj /* Make a new node for next time round. */
1199838fd1498Szrj cl_optimization_node = make_node (OPTIMIZATION_NODE);
1199938fd1498Szrj }
1200038fd1498Szrj
1200138fd1498Szrj return t;
1200238fd1498Szrj }
1200338fd1498Szrj
1200438fd1498Szrj /* Build a TARGET_OPTION_NODE based on the options in OPTS. */
1200538fd1498Szrj
1200638fd1498Szrj tree
build_target_option_node(struct gcc_options * opts)1200738fd1498Szrj build_target_option_node (struct gcc_options *opts)
1200838fd1498Szrj {
1200938fd1498Szrj tree t;
1201038fd1498Szrj
1201138fd1498Szrj /* Use the cache of optimization nodes. */
1201238fd1498Szrj
1201338fd1498Szrj cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node),
1201438fd1498Szrj opts);
1201538fd1498Szrj
1201638fd1498Szrj tree *slot = cl_option_hash_table->find_slot (cl_target_option_node, INSERT);
1201738fd1498Szrj t = *slot;
1201838fd1498Szrj if (!t)
1201938fd1498Szrj {
1202038fd1498Szrj /* Insert this one into the hash table. */
1202138fd1498Szrj t = cl_target_option_node;
1202238fd1498Szrj *slot = t;
1202338fd1498Szrj
1202438fd1498Szrj /* Make a new node for next time round. */
1202538fd1498Szrj cl_target_option_node = make_node (TARGET_OPTION_NODE);
1202638fd1498Szrj }
1202738fd1498Szrj
1202838fd1498Szrj return t;
1202938fd1498Szrj }
1203038fd1498Szrj
1203138fd1498Szrj /* Clear TREE_TARGET_GLOBALS of all TARGET_OPTION_NODE trees,
1203238fd1498Szrj so that they aren't saved during PCH writing. */
1203338fd1498Szrj
1203438fd1498Szrj void
prepare_target_option_nodes_for_pch(void)1203538fd1498Szrj prepare_target_option_nodes_for_pch (void)
1203638fd1498Szrj {
1203738fd1498Szrj hash_table<cl_option_hasher>::iterator iter = cl_option_hash_table->begin ();
1203838fd1498Szrj for (; iter != cl_option_hash_table->end (); ++iter)
1203938fd1498Szrj if (TREE_CODE (*iter) == TARGET_OPTION_NODE)
1204038fd1498Szrj TREE_TARGET_GLOBALS (*iter) = NULL;
1204138fd1498Szrj }
1204238fd1498Szrj
1204338fd1498Szrj /* Determine the "ultimate origin" of a block. The block may be an inlined
1204438fd1498Szrj instance of an inlined instance of a block which is local to an inline
1204538fd1498Szrj function, so we have to trace all of the way back through the origin chain
1204638fd1498Szrj to find out what sort of node actually served as the original seed for the
1204738fd1498Szrj given block. */
1204838fd1498Szrj
1204938fd1498Szrj tree
block_ultimate_origin(const_tree block)1205038fd1498Szrj block_ultimate_origin (const_tree block)
1205138fd1498Szrj {
1205238fd1498Szrj tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block);
1205338fd1498Szrj
1205438fd1498Szrj /* BLOCK_ABSTRACT_ORIGIN can point to itself; ignore that if
1205538fd1498Szrj we're trying to output the abstract instance of this function. */
1205638fd1498Szrj if (BLOCK_ABSTRACT (block) && immediate_origin == block)
1205738fd1498Szrj return NULL_TREE;
1205838fd1498Szrj
1205938fd1498Szrj if (immediate_origin == NULL_TREE)
1206038fd1498Szrj return NULL_TREE;
1206138fd1498Szrj else
1206238fd1498Szrj {
1206338fd1498Szrj tree ret_val;
1206438fd1498Szrj tree lookahead = immediate_origin;
1206538fd1498Szrj
1206638fd1498Szrj do
1206738fd1498Szrj {
1206838fd1498Szrj ret_val = lookahead;
1206938fd1498Szrj lookahead = (TREE_CODE (ret_val) == BLOCK
1207038fd1498Szrj ? BLOCK_ABSTRACT_ORIGIN (ret_val) : NULL);
1207138fd1498Szrj }
1207238fd1498Szrj while (lookahead != NULL && lookahead != ret_val);
1207338fd1498Szrj
1207438fd1498Szrj /* The block's abstract origin chain may not be the *ultimate* origin of
1207538fd1498Szrj the block. It could lead to a DECL that has an abstract origin set.
1207638fd1498Szrj If so, we want that DECL's abstract origin (which is what DECL_ORIGIN
1207738fd1498Szrj will give us if it has one). Note that DECL's abstract origins are
1207838fd1498Szrj supposed to be the most distant ancestor (or so decl_ultimate_origin
1207938fd1498Szrj claims), so we don't need to loop following the DECL origins. */
1208038fd1498Szrj if (DECL_P (ret_val))
1208138fd1498Szrj return DECL_ORIGIN (ret_val);
1208238fd1498Szrj
1208338fd1498Szrj return ret_val;
1208438fd1498Szrj }
1208538fd1498Szrj }
1208638fd1498Szrj
1208738fd1498Szrj /* Return true iff conversion from INNER_TYPE to OUTER_TYPE generates
1208838fd1498Szrj no instruction. */
1208938fd1498Szrj
1209038fd1498Szrj bool
tree_nop_conversion_p(const_tree outer_type,const_tree inner_type)1209138fd1498Szrj tree_nop_conversion_p (const_tree outer_type, const_tree inner_type)
1209238fd1498Szrj {
1209338fd1498Szrj /* Do not strip casts into or out of differing address spaces. */
1209438fd1498Szrj if (POINTER_TYPE_P (outer_type)
1209538fd1498Szrj && TYPE_ADDR_SPACE (TREE_TYPE (outer_type)) != ADDR_SPACE_GENERIC)
1209638fd1498Szrj {
1209738fd1498Szrj if (!POINTER_TYPE_P (inner_type)
1209838fd1498Szrj || (TYPE_ADDR_SPACE (TREE_TYPE (outer_type))
1209938fd1498Szrj != TYPE_ADDR_SPACE (TREE_TYPE (inner_type))))
1210038fd1498Szrj return false;
1210138fd1498Szrj }
1210238fd1498Szrj else if (POINTER_TYPE_P (inner_type)
1210338fd1498Szrj && TYPE_ADDR_SPACE (TREE_TYPE (inner_type)) != ADDR_SPACE_GENERIC)
1210438fd1498Szrj {
1210538fd1498Szrj /* We already know that outer_type is not a pointer with
1210638fd1498Szrj a non-generic address space. */
1210738fd1498Szrj return false;
1210838fd1498Szrj }
1210938fd1498Szrj
1211038fd1498Szrj /* Use precision rather then machine mode when we can, which gives
1211138fd1498Szrj the correct answer even for submode (bit-field) types. */
1211238fd1498Szrj if ((INTEGRAL_TYPE_P (outer_type)
1211338fd1498Szrj || POINTER_TYPE_P (outer_type)
1211438fd1498Szrj || TREE_CODE (outer_type) == OFFSET_TYPE)
1211538fd1498Szrj && (INTEGRAL_TYPE_P (inner_type)
1211638fd1498Szrj || POINTER_TYPE_P (inner_type)
1211738fd1498Szrj || TREE_CODE (inner_type) == OFFSET_TYPE))
1211838fd1498Szrj return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type);
1211938fd1498Szrj
1212038fd1498Szrj /* Otherwise fall back on comparing machine modes (e.g. for
1212138fd1498Szrj aggregate types, floats). */
1212238fd1498Szrj return TYPE_MODE (outer_type) == TYPE_MODE (inner_type);
1212338fd1498Szrj }
1212438fd1498Szrj
1212538fd1498Szrj /* Return true iff conversion in EXP generates no instruction. Mark
1212638fd1498Szrj it inline so that we fully inline into the stripping functions even
1212738fd1498Szrj though we have two uses of this function. */
1212838fd1498Szrj
1212938fd1498Szrj static inline bool
tree_nop_conversion(const_tree exp)1213038fd1498Szrj tree_nop_conversion (const_tree exp)
1213138fd1498Szrj {
1213238fd1498Szrj tree outer_type, inner_type;
1213338fd1498Szrj
1213438fd1498Szrj if (location_wrapper_p (exp))
1213538fd1498Szrj return true;
1213638fd1498Szrj if (!CONVERT_EXPR_P (exp)
1213738fd1498Szrj && TREE_CODE (exp) != NON_LVALUE_EXPR)
1213838fd1498Szrj return false;
1213938fd1498Szrj if (TREE_OPERAND (exp, 0) == error_mark_node)
1214038fd1498Szrj return false;
1214138fd1498Szrj
1214238fd1498Szrj outer_type = TREE_TYPE (exp);
1214338fd1498Szrj inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
1214438fd1498Szrj
1214538fd1498Szrj if (!inner_type)
1214638fd1498Szrj return false;
1214738fd1498Szrj
1214838fd1498Szrj return tree_nop_conversion_p (outer_type, inner_type);
1214938fd1498Szrj }
1215038fd1498Szrj
1215138fd1498Szrj /* Return true iff conversion in EXP generates no instruction. Don't
1215238fd1498Szrj consider conversions changing the signedness. */
1215338fd1498Szrj
1215438fd1498Szrj static bool
tree_sign_nop_conversion(const_tree exp)1215538fd1498Szrj tree_sign_nop_conversion (const_tree exp)
1215638fd1498Szrj {
1215738fd1498Szrj tree outer_type, inner_type;
1215838fd1498Szrj
1215938fd1498Szrj if (!tree_nop_conversion (exp))
1216038fd1498Szrj return false;
1216138fd1498Szrj
1216238fd1498Szrj outer_type = TREE_TYPE (exp);
1216338fd1498Szrj inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
1216438fd1498Szrj
1216538fd1498Szrj return (TYPE_UNSIGNED (outer_type) == TYPE_UNSIGNED (inner_type)
1216638fd1498Szrj && POINTER_TYPE_P (outer_type) == POINTER_TYPE_P (inner_type));
1216738fd1498Szrj }
1216838fd1498Szrj
1216938fd1498Szrj /* Strip conversions from EXP according to tree_nop_conversion and
1217038fd1498Szrj return the resulting expression. */
1217138fd1498Szrj
1217238fd1498Szrj tree
tree_strip_nop_conversions(tree exp)1217338fd1498Szrj tree_strip_nop_conversions (tree exp)
1217438fd1498Szrj {
1217538fd1498Szrj while (tree_nop_conversion (exp))
1217638fd1498Szrj exp = TREE_OPERAND (exp, 0);
1217738fd1498Szrj return exp;
1217838fd1498Szrj }
1217938fd1498Szrj
1218038fd1498Szrj /* Strip conversions from EXP according to tree_sign_nop_conversion
1218138fd1498Szrj and return the resulting expression. */
1218238fd1498Szrj
1218338fd1498Szrj tree
tree_strip_sign_nop_conversions(tree exp)1218438fd1498Szrj tree_strip_sign_nop_conversions (tree exp)
1218538fd1498Szrj {
1218638fd1498Szrj while (tree_sign_nop_conversion (exp))
1218738fd1498Szrj exp = TREE_OPERAND (exp, 0);
1218838fd1498Szrj return exp;
1218938fd1498Szrj }
1219038fd1498Szrj
1219138fd1498Szrj /* Avoid any floating point extensions from EXP. */
1219238fd1498Szrj tree
strip_float_extensions(tree exp)1219338fd1498Szrj strip_float_extensions (tree exp)
1219438fd1498Szrj {
1219538fd1498Szrj tree sub, expt, subt;
1219638fd1498Szrj
1219738fd1498Szrj /* For floating point constant look up the narrowest type that can hold
1219838fd1498Szrj it properly and handle it like (type)(narrowest_type)constant.
1219938fd1498Szrj This way we can optimize for instance a=a*2.0 where "a" is float
1220038fd1498Szrj but 2.0 is double constant. */
1220138fd1498Szrj if (TREE_CODE (exp) == REAL_CST && !DECIMAL_FLOAT_TYPE_P (TREE_TYPE (exp)))
1220238fd1498Szrj {
1220338fd1498Szrj REAL_VALUE_TYPE orig;
1220438fd1498Szrj tree type = NULL;
1220538fd1498Szrj
1220638fd1498Szrj orig = TREE_REAL_CST (exp);
1220738fd1498Szrj if (TYPE_PRECISION (TREE_TYPE (exp)) > TYPE_PRECISION (float_type_node)
1220838fd1498Szrj && exact_real_truncate (TYPE_MODE (float_type_node), &orig))
1220938fd1498Szrj type = float_type_node;
1221038fd1498Szrj else if (TYPE_PRECISION (TREE_TYPE (exp))
1221138fd1498Szrj > TYPE_PRECISION (double_type_node)
1221238fd1498Szrj && exact_real_truncate (TYPE_MODE (double_type_node), &orig))
1221338fd1498Szrj type = double_type_node;
1221438fd1498Szrj if (type)
1221538fd1498Szrj return build_real_truncate (type, orig);
1221638fd1498Szrj }
1221738fd1498Szrj
1221838fd1498Szrj if (!CONVERT_EXPR_P (exp))
1221938fd1498Szrj return exp;
1222038fd1498Szrj
1222138fd1498Szrj sub = TREE_OPERAND (exp, 0);
1222238fd1498Szrj subt = TREE_TYPE (sub);
1222338fd1498Szrj expt = TREE_TYPE (exp);
1222438fd1498Szrj
1222538fd1498Szrj if (!FLOAT_TYPE_P (subt))
1222638fd1498Szrj return exp;
1222738fd1498Szrj
1222838fd1498Szrj if (DECIMAL_FLOAT_TYPE_P (expt) != DECIMAL_FLOAT_TYPE_P (subt))
1222938fd1498Szrj return exp;
1223038fd1498Szrj
1223138fd1498Szrj if (TYPE_PRECISION (subt) > TYPE_PRECISION (expt))
1223238fd1498Szrj return exp;
1223338fd1498Szrj
1223438fd1498Szrj return strip_float_extensions (sub);
1223538fd1498Szrj }
1223638fd1498Szrj
1223738fd1498Szrj /* Strip out all handled components that produce invariant
1223838fd1498Szrj offsets. */
1223938fd1498Szrj
1224038fd1498Szrj const_tree
strip_invariant_refs(const_tree op)1224138fd1498Szrj strip_invariant_refs (const_tree op)
1224238fd1498Szrj {
1224338fd1498Szrj while (handled_component_p (op))
1224438fd1498Szrj {
1224538fd1498Szrj switch (TREE_CODE (op))
1224638fd1498Szrj {
1224738fd1498Szrj case ARRAY_REF:
1224838fd1498Szrj case ARRAY_RANGE_REF:
1224938fd1498Szrj if (!is_gimple_constant (TREE_OPERAND (op, 1))
1225038fd1498Szrj || TREE_OPERAND (op, 2) != NULL_TREE
1225138fd1498Szrj || TREE_OPERAND (op, 3) != NULL_TREE)
1225238fd1498Szrj return NULL;
1225338fd1498Szrj break;
1225438fd1498Szrj
1225538fd1498Szrj case COMPONENT_REF:
1225638fd1498Szrj if (TREE_OPERAND (op, 2) != NULL_TREE)
1225738fd1498Szrj return NULL;
1225838fd1498Szrj break;
1225938fd1498Szrj
1226038fd1498Szrj default:;
1226138fd1498Szrj }
1226238fd1498Szrj op = TREE_OPERAND (op, 0);
1226338fd1498Szrj }
1226438fd1498Szrj
1226538fd1498Szrj return op;
1226638fd1498Szrj }
1226738fd1498Szrj
1226838fd1498Szrj static GTY(()) tree gcc_eh_personality_decl;
1226938fd1498Szrj
1227038fd1498Szrj /* Return the GCC personality function decl. */
1227138fd1498Szrj
1227238fd1498Szrj tree
lhd_gcc_personality(void)1227338fd1498Szrj lhd_gcc_personality (void)
1227438fd1498Szrj {
1227538fd1498Szrj if (!gcc_eh_personality_decl)
1227638fd1498Szrj gcc_eh_personality_decl = build_personality_function ("gcc");
1227738fd1498Szrj return gcc_eh_personality_decl;
1227838fd1498Szrj }
1227938fd1498Szrj
1228038fd1498Szrj /* TARGET is a call target of GIMPLE call statement
1228138fd1498Szrj (obtained by gimple_call_fn). Return true if it is
1228238fd1498Szrj OBJ_TYPE_REF representing an virtual call of C++ method.
1228338fd1498Szrj (As opposed to OBJ_TYPE_REF representing objc calls
1228438fd1498Szrj through a cast where middle-end devirtualization machinery
1228538fd1498Szrj can't apply.) */
1228638fd1498Szrj
1228738fd1498Szrj bool
virtual_method_call_p(const_tree target)1228838fd1498Szrj virtual_method_call_p (const_tree target)
1228938fd1498Szrj {
1229038fd1498Szrj if (TREE_CODE (target) != OBJ_TYPE_REF)
1229138fd1498Szrj return false;
1229238fd1498Szrj tree t = TREE_TYPE (target);
1229338fd1498Szrj gcc_checking_assert (TREE_CODE (t) == POINTER_TYPE);
1229438fd1498Szrj t = TREE_TYPE (t);
1229538fd1498Szrj if (TREE_CODE (t) == FUNCTION_TYPE)
1229638fd1498Szrj return false;
1229738fd1498Szrj gcc_checking_assert (TREE_CODE (t) == METHOD_TYPE);
1229838fd1498Szrj /* If we do not have BINFO associated, it means that type was built
1229938fd1498Szrj without devirtualization enabled. Do not consider this a virtual
1230038fd1498Szrj call. */
1230138fd1498Szrj if (!TYPE_BINFO (obj_type_ref_class (target)))
1230238fd1498Szrj return false;
1230338fd1498Szrj return true;
1230438fd1498Szrj }
1230538fd1498Szrj
1230638fd1498Szrj /* REF is OBJ_TYPE_REF, return the class the ref corresponds to. */
1230738fd1498Szrj
1230838fd1498Szrj tree
obj_type_ref_class(const_tree ref)1230938fd1498Szrj obj_type_ref_class (const_tree ref)
1231038fd1498Szrj {
1231138fd1498Szrj gcc_checking_assert (TREE_CODE (ref) == OBJ_TYPE_REF);
1231238fd1498Szrj ref = TREE_TYPE (ref);
1231338fd1498Szrj gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
1231438fd1498Szrj ref = TREE_TYPE (ref);
1231538fd1498Szrj /* We look for type THIS points to. ObjC also builds
1231638fd1498Szrj OBJ_TYPE_REF with non-method calls, Their first parameter
1231738fd1498Szrj ID however also corresponds to class type. */
1231838fd1498Szrj gcc_checking_assert (TREE_CODE (ref) == METHOD_TYPE
1231938fd1498Szrj || TREE_CODE (ref) == FUNCTION_TYPE);
1232038fd1498Szrj ref = TREE_VALUE (TYPE_ARG_TYPES (ref));
1232138fd1498Szrj gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
1232238fd1498Szrj return TREE_TYPE (ref);
1232338fd1498Szrj }
1232438fd1498Szrj
1232538fd1498Szrj /* Lookup sub-BINFO of BINFO of TYPE at offset POS. */
1232638fd1498Szrj
1232738fd1498Szrj static tree
lookup_binfo_at_offset(tree binfo,tree type,HOST_WIDE_INT pos)1232838fd1498Szrj lookup_binfo_at_offset (tree binfo, tree type, HOST_WIDE_INT pos)
1232938fd1498Szrj {
1233038fd1498Szrj unsigned int i;
1233138fd1498Szrj tree base_binfo, b;
1233238fd1498Szrj
1233338fd1498Szrj for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
1233438fd1498Szrj if (pos == tree_to_shwi (BINFO_OFFSET (base_binfo))
1233538fd1498Szrj && types_same_for_odr (TREE_TYPE (base_binfo), type))
1233638fd1498Szrj return base_binfo;
1233738fd1498Szrj else if ((b = lookup_binfo_at_offset (base_binfo, type, pos)) != NULL)
1233838fd1498Szrj return b;
1233938fd1498Szrj return NULL;
1234038fd1498Szrj }
1234138fd1498Szrj
1234238fd1498Szrj /* Try to find a base info of BINFO that would have its field decl at offset
1234338fd1498Szrj OFFSET within the BINFO type and which is of EXPECTED_TYPE. If it can be
1234438fd1498Szrj found, return, otherwise return NULL_TREE. */
1234538fd1498Szrj
1234638fd1498Szrj tree
get_binfo_at_offset(tree binfo,poly_int64 offset,tree expected_type)1234738fd1498Szrj get_binfo_at_offset (tree binfo, poly_int64 offset, tree expected_type)
1234838fd1498Szrj {
1234938fd1498Szrj tree type = BINFO_TYPE (binfo);
1235038fd1498Szrj
1235138fd1498Szrj while (true)
1235238fd1498Szrj {
1235338fd1498Szrj HOST_WIDE_INT pos, size;
1235438fd1498Szrj tree fld;
1235538fd1498Szrj int i;
1235638fd1498Szrj
1235738fd1498Szrj if (types_same_for_odr (type, expected_type))
1235838fd1498Szrj return binfo;
1235938fd1498Szrj if (maybe_lt (offset, 0))
1236038fd1498Szrj return NULL_TREE;
1236138fd1498Szrj
1236238fd1498Szrj for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
1236338fd1498Szrj {
1236438fd1498Szrj if (TREE_CODE (fld) != FIELD_DECL || !DECL_ARTIFICIAL (fld))
1236538fd1498Szrj continue;
1236638fd1498Szrj
1236738fd1498Szrj pos = int_bit_position (fld);
1236838fd1498Szrj size = tree_to_uhwi (DECL_SIZE (fld));
1236938fd1498Szrj if (known_in_range_p (offset, pos, size))
1237038fd1498Szrj break;
1237138fd1498Szrj }
1237238fd1498Szrj if (!fld || TREE_CODE (TREE_TYPE (fld)) != RECORD_TYPE)
1237338fd1498Szrj return NULL_TREE;
1237438fd1498Szrj
1237538fd1498Szrj /* Offset 0 indicates the primary base, whose vtable contents are
1237638fd1498Szrj represented in the binfo for the derived class. */
1237738fd1498Szrj else if (maybe_ne (offset, 0))
1237838fd1498Szrj {
1237938fd1498Szrj tree found_binfo = NULL, base_binfo;
1238038fd1498Szrj /* Offsets in BINFO are in bytes relative to the whole structure
1238138fd1498Szrj while POS is in bits relative to the containing field. */
1238238fd1498Szrj int binfo_offset = (tree_to_shwi (BINFO_OFFSET (binfo)) + pos
1238338fd1498Szrj / BITS_PER_UNIT);
1238438fd1498Szrj
1238538fd1498Szrj for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
1238638fd1498Szrj if (tree_to_shwi (BINFO_OFFSET (base_binfo)) == binfo_offset
1238738fd1498Szrj && types_same_for_odr (TREE_TYPE (base_binfo), TREE_TYPE (fld)))
1238838fd1498Szrj {
1238938fd1498Szrj found_binfo = base_binfo;
1239038fd1498Szrj break;
1239138fd1498Szrj }
1239238fd1498Szrj if (found_binfo)
1239338fd1498Szrj binfo = found_binfo;
1239438fd1498Szrj else
1239538fd1498Szrj binfo = lookup_binfo_at_offset (binfo, TREE_TYPE (fld),
1239638fd1498Szrj binfo_offset);
1239738fd1498Szrj }
1239838fd1498Szrj
1239938fd1498Szrj type = TREE_TYPE (fld);
1240038fd1498Szrj offset -= pos;
1240138fd1498Szrj }
1240238fd1498Szrj }
1240338fd1498Szrj
1240438fd1498Szrj /* Returns true if X is a typedef decl. */
1240538fd1498Szrj
1240638fd1498Szrj bool
is_typedef_decl(const_tree x)1240738fd1498Szrj is_typedef_decl (const_tree x)
1240838fd1498Szrj {
1240938fd1498Szrj return (x && TREE_CODE (x) == TYPE_DECL
1241038fd1498Szrj && DECL_ORIGINAL_TYPE (x) != NULL_TREE);
1241138fd1498Szrj }
1241238fd1498Szrj
1241338fd1498Szrj /* Returns true iff TYPE is a type variant created for a typedef. */
1241438fd1498Szrj
1241538fd1498Szrj bool
typedef_variant_p(const_tree type)1241638fd1498Szrj typedef_variant_p (const_tree type)
1241738fd1498Szrj {
1241838fd1498Szrj return is_typedef_decl (TYPE_NAME (type));
1241938fd1498Szrj }
1242038fd1498Szrj
1242138fd1498Szrj /* Warn about a use of an identifier which was marked deprecated. */
1242238fd1498Szrj void
warn_deprecated_use(tree node,tree attr)1242338fd1498Szrj warn_deprecated_use (tree node, tree attr)
1242438fd1498Szrj {
1242538fd1498Szrj const char *msg;
1242638fd1498Szrj
1242738fd1498Szrj if (node == 0 || !warn_deprecated_decl)
1242838fd1498Szrj return;
1242938fd1498Szrj
1243038fd1498Szrj if (!attr)
1243138fd1498Szrj {
1243238fd1498Szrj if (DECL_P (node))
1243338fd1498Szrj attr = DECL_ATTRIBUTES (node);
1243438fd1498Szrj else if (TYPE_P (node))
1243538fd1498Szrj {
1243638fd1498Szrj tree decl = TYPE_STUB_DECL (node);
1243738fd1498Szrj if (decl)
1243838fd1498Szrj attr = lookup_attribute ("deprecated",
1243938fd1498Szrj TYPE_ATTRIBUTES (TREE_TYPE (decl)));
1244038fd1498Szrj }
1244138fd1498Szrj }
1244238fd1498Szrj
1244338fd1498Szrj if (attr)
1244438fd1498Szrj attr = lookup_attribute ("deprecated", attr);
1244538fd1498Szrj
1244638fd1498Szrj if (attr)
1244738fd1498Szrj msg = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)));
1244838fd1498Szrj else
1244938fd1498Szrj msg = NULL;
1245038fd1498Szrj
1245138fd1498Szrj bool w;
1245238fd1498Szrj if (DECL_P (node))
1245338fd1498Szrj {
1245438fd1498Szrj if (msg)
1245538fd1498Szrj w = warning (OPT_Wdeprecated_declarations,
1245638fd1498Szrj "%qD is deprecated: %s", node, msg);
1245738fd1498Szrj else
1245838fd1498Szrj w = warning (OPT_Wdeprecated_declarations,
1245938fd1498Szrj "%qD is deprecated", node);
1246038fd1498Szrj if (w)
1246138fd1498Szrj inform (DECL_SOURCE_LOCATION (node), "declared here");
1246238fd1498Szrj }
1246338fd1498Szrj else if (TYPE_P (node))
1246438fd1498Szrj {
1246538fd1498Szrj tree what = NULL_TREE;
1246638fd1498Szrj tree decl = TYPE_STUB_DECL (node);
1246738fd1498Szrj
1246838fd1498Szrj if (TYPE_NAME (node))
1246938fd1498Szrj {
1247038fd1498Szrj if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
1247138fd1498Szrj what = TYPE_NAME (node);
1247238fd1498Szrj else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
1247338fd1498Szrj && DECL_NAME (TYPE_NAME (node)))
1247438fd1498Szrj what = DECL_NAME (TYPE_NAME (node));
1247538fd1498Szrj }
1247638fd1498Szrj
1247738fd1498Szrj if (decl)
1247838fd1498Szrj {
1247938fd1498Szrj if (what)
1248038fd1498Szrj {
1248138fd1498Szrj if (msg)
1248238fd1498Szrj w = warning (OPT_Wdeprecated_declarations,
1248338fd1498Szrj "%qE is deprecated: %s", what, msg);
1248438fd1498Szrj else
1248538fd1498Szrj w = warning (OPT_Wdeprecated_declarations,
1248638fd1498Szrj "%qE is deprecated", what);
1248738fd1498Szrj }
1248838fd1498Szrj else
1248938fd1498Szrj {
1249038fd1498Szrj if (msg)
1249138fd1498Szrj w = warning (OPT_Wdeprecated_declarations,
1249238fd1498Szrj "type is deprecated: %s", msg);
1249338fd1498Szrj else
1249438fd1498Szrj w = warning (OPT_Wdeprecated_declarations,
1249538fd1498Szrj "type is deprecated");
1249638fd1498Szrj }
1249738fd1498Szrj if (w)
1249838fd1498Szrj inform (DECL_SOURCE_LOCATION (decl), "declared here");
1249938fd1498Szrj }
1250038fd1498Szrj else
1250138fd1498Szrj {
1250238fd1498Szrj if (what)
1250338fd1498Szrj {
1250438fd1498Szrj if (msg)
1250538fd1498Szrj warning (OPT_Wdeprecated_declarations, "%qE is deprecated: %s",
1250638fd1498Szrj what, msg);
1250738fd1498Szrj else
1250838fd1498Szrj warning (OPT_Wdeprecated_declarations, "%qE is deprecated", what);
1250938fd1498Szrj }
1251038fd1498Szrj else
1251138fd1498Szrj {
1251238fd1498Szrj if (msg)
1251338fd1498Szrj warning (OPT_Wdeprecated_declarations, "type is deprecated: %s",
1251438fd1498Szrj msg);
1251538fd1498Szrj else
1251638fd1498Szrj warning (OPT_Wdeprecated_declarations, "type is deprecated");
1251738fd1498Szrj }
1251838fd1498Szrj }
1251938fd1498Szrj }
1252038fd1498Szrj }
1252138fd1498Szrj
1252238fd1498Szrj /* Return true if REF has a COMPONENT_REF with a bit-field field declaration
1252338fd1498Szrj somewhere in it. */
1252438fd1498Szrj
1252538fd1498Szrj bool
contains_bitfld_component_ref_p(const_tree ref)1252638fd1498Szrj contains_bitfld_component_ref_p (const_tree ref)
1252738fd1498Szrj {
1252838fd1498Szrj while (handled_component_p (ref))
1252938fd1498Szrj {
1253038fd1498Szrj if (TREE_CODE (ref) == COMPONENT_REF
1253138fd1498Szrj && DECL_BIT_FIELD (TREE_OPERAND (ref, 1)))
1253238fd1498Szrj return true;
1253338fd1498Szrj ref = TREE_OPERAND (ref, 0);
1253438fd1498Szrj }
1253538fd1498Szrj
1253638fd1498Szrj return false;
1253738fd1498Szrj }
1253838fd1498Szrj
1253938fd1498Szrj /* Try to determine whether a TRY_CATCH expression can fall through.
1254038fd1498Szrj This is a subroutine of block_may_fallthru. */
1254138fd1498Szrj
1254238fd1498Szrj static bool
try_catch_may_fallthru(const_tree stmt)1254338fd1498Szrj try_catch_may_fallthru (const_tree stmt)
1254438fd1498Szrj {
1254538fd1498Szrj tree_stmt_iterator i;
1254638fd1498Szrj
1254738fd1498Szrj /* If the TRY block can fall through, the whole TRY_CATCH can
1254838fd1498Szrj fall through. */
1254938fd1498Szrj if (block_may_fallthru (TREE_OPERAND (stmt, 0)))
1255038fd1498Szrj return true;
1255138fd1498Szrj
1255238fd1498Szrj i = tsi_start (TREE_OPERAND (stmt, 1));
1255338fd1498Szrj switch (TREE_CODE (tsi_stmt (i)))
1255438fd1498Szrj {
1255538fd1498Szrj case CATCH_EXPR:
1255638fd1498Szrj /* We expect to see a sequence of CATCH_EXPR trees, each with a
1255738fd1498Szrj catch expression and a body. The whole TRY_CATCH may fall
1255838fd1498Szrj through iff any of the catch bodies falls through. */
1255938fd1498Szrj for (; !tsi_end_p (i); tsi_next (&i))
1256038fd1498Szrj {
1256138fd1498Szrj if (block_may_fallthru (CATCH_BODY (tsi_stmt (i))))
1256238fd1498Szrj return true;
1256338fd1498Szrj }
1256438fd1498Szrj return false;
1256538fd1498Szrj
1256638fd1498Szrj case EH_FILTER_EXPR:
1256738fd1498Szrj /* The exception filter expression only matters if there is an
1256838fd1498Szrj exception. If the exception does not match EH_FILTER_TYPES,
1256938fd1498Szrj we will execute EH_FILTER_FAILURE, and we will fall through
1257038fd1498Szrj if that falls through. If the exception does match
1257138fd1498Szrj EH_FILTER_TYPES, the stack unwinder will continue up the
1257238fd1498Szrj stack, so we will not fall through. We don't know whether we
1257338fd1498Szrj will throw an exception which matches EH_FILTER_TYPES or not,
1257438fd1498Szrj so we just ignore EH_FILTER_TYPES and assume that we might
1257538fd1498Szrj throw an exception which doesn't match. */
1257638fd1498Szrj return block_may_fallthru (EH_FILTER_FAILURE (tsi_stmt (i)));
1257738fd1498Szrj
1257838fd1498Szrj default:
1257938fd1498Szrj /* This case represents statements to be executed when an
1258038fd1498Szrj exception occurs. Those statements are implicitly followed
1258138fd1498Szrj by a RESX statement to resume execution after the exception.
1258238fd1498Szrj So in this case the TRY_CATCH never falls through. */
1258338fd1498Szrj return false;
1258438fd1498Szrj }
1258538fd1498Szrj }
1258638fd1498Szrj
1258738fd1498Szrj /* Try to determine if we can fall out of the bottom of BLOCK. This guess
1258838fd1498Szrj need not be 100% accurate; simply be conservative and return true if we
1258938fd1498Szrj don't know. This is used only to avoid stupidly generating extra code.
1259038fd1498Szrj If we're wrong, we'll just delete the extra code later. */
1259138fd1498Szrj
1259238fd1498Szrj bool
block_may_fallthru(const_tree block)1259338fd1498Szrj block_may_fallthru (const_tree block)
1259438fd1498Szrj {
1259538fd1498Szrj /* This CONST_CAST is okay because expr_last returns its argument
1259638fd1498Szrj unmodified and we assign it to a const_tree. */
1259738fd1498Szrj const_tree stmt = expr_last (CONST_CAST_TREE (block));
1259838fd1498Szrj
1259938fd1498Szrj switch (stmt ? TREE_CODE (stmt) : ERROR_MARK)
1260038fd1498Szrj {
1260138fd1498Szrj case GOTO_EXPR:
1260238fd1498Szrj case RETURN_EXPR:
1260338fd1498Szrj /* Easy cases. If the last statement of the block implies
1260438fd1498Szrj control transfer, then we can't fall through. */
1260538fd1498Szrj return false;
1260638fd1498Szrj
1260738fd1498Szrj case SWITCH_EXPR:
1260838fd1498Szrj /* If there is a default: label or case labels cover all possible
1260938fd1498Szrj SWITCH_COND values, then the SWITCH_EXPR will transfer control
1261038fd1498Szrj to some case label in all cases and all we care is whether the
1261138fd1498Szrj SWITCH_BODY falls through. */
1261238fd1498Szrj if (SWITCH_ALL_CASES_P (stmt))
1261338fd1498Szrj return block_may_fallthru (SWITCH_BODY (stmt));
1261438fd1498Szrj return true;
1261538fd1498Szrj
1261638fd1498Szrj case COND_EXPR:
1261738fd1498Szrj if (block_may_fallthru (COND_EXPR_THEN (stmt)))
1261838fd1498Szrj return true;
1261938fd1498Szrj return block_may_fallthru (COND_EXPR_ELSE (stmt));
1262038fd1498Szrj
1262138fd1498Szrj case BIND_EXPR:
1262238fd1498Szrj return block_may_fallthru (BIND_EXPR_BODY (stmt));
1262338fd1498Szrj
1262438fd1498Szrj case TRY_CATCH_EXPR:
1262538fd1498Szrj return try_catch_may_fallthru (stmt);
1262638fd1498Szrj
1262738fd1498Szrj case TRY_FINALLY_EXPR:
1262838fd1498Szrj /* The finally clause is always executed after the try clause,
1262938fd1498Szrj so if it does not fall through, then the try-finally will not
1263038fd1498Szrj fall through. Otherwise, if the try clause does not fall
1263138fd1498Szrj through, then when the finally clause falls through it will
1263238fd1498Szrj resume execution wherever the try clause was going. So the
1263338fd1498Szrj whole try-finally will only fall through if both the try
1263438fd1498Szrj clause and the finally clause fall through. */
1263538fd1498Szrj return (block_may_fallthru (TREE_OPERAND (stmt, 0))
1263638fd1498Szrj && block_may_fallthru (TREE_OPERAND (stmt, 1)));
1263738fd1498Szrj
1263838fd1498Szrj case MODIFY_EXPR:
1263938fd1498Szrj if (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR)
1264038fd1498Szrj stmt = TREE_OPERAND (stmt, 1);
1264138fd1498Szrj else
1264238fd1498Szrj return true;
1264338fd1498Szrj /* FALLTHRU */
1264438fd1498Szrj
1264538fd1498Szrj case CALL_EXPR:
1264638fd1498Szrj /* Functions that do not return do not fall through. */
1264738fd1498Szrj return (call_expr_flags (stmt) & ECF_NORETURN) == 0;
1264838fd1498Szrj
1264938fd1498Szrj case CLEANUP_POINT_EXPR:
1265038fd1498Szrj return block_may_fallthru (TREE_OPERAND (stmt, 0));
1265138fd1498Szrj
1265238fd1498Szrj case TARGET_EXPR:
1265338fd1498Szrj return block_may_fallthru (TREE_OPERAND (stmt, 1));
1265438fd1498Szrj
1265538fd1498Szrj case ERROR_MARK:
1265638fd1498Szrj return true;
1265738fd1498Szrj
1265838fd1498Szrj default:
1265938fd1498Szrj return lang_hooks.block_may_fallthru (stmt);
1266038fd1498Szrj }
1266138fd1498Szrj }
1266238fd1498Szrj
1266338fd1498Szrj /* True if we are using EH to handle cleanups. */
1266438fd1498Szrj static bool using_eh_for_cleanups_flag = false;
1266538fd1498Szrj
1266638fd1498Szrj /* This routine is called from front ends to indicate eh should be used for
1266738fd1498Szrj cleanups. */
1266838fd1498Szrj void
using_eh_for_cleanups(void)1266938fd1498Szrj using_eh_for_cleanups (void)
1267038fd1498Szrj {
1267138fd1498Szrj using_eh_for_cleanups_flag = true;
1267238fd1498Szrj }
1267338fd1498Szrj
1267438fd1498Szrj /* Query whether EH is used for cleanups. */
1267538fd1498Szrj bool
using_eh_for_cleanups_p(void)1267638fd1498Szrj using_eh_for_cleanups_p (void)
1267738fd1498Szrj {
1267838fd1498Szrj return using_eh_for_cleanups_flag;
1267938fd1498Szrj }
1268038fd1498Szrj
1268138fd1498Szrj /* Wrapper for tree_code_name to ensure that tree code is valid */
1268238fd1498Szrj const char *
get_tree_code_name(enum tree_code code)1268338fd1498Szrj get_tree_code_name (enum tree_code code)
1268438fd1498Szrj {
1268538fd1498Szrj const char *invalid = "<invalid tree code>";
1268638fd1498Szrj
1268738fd1498Szrj if (code >= MAX_TREE_CODES)
1268838fd1498Szrj return invalid;
1268938fd1498Szrj
1269038fd1498Szrj return tree_code_name[code];
1269138fd1498Szrj }
1269238fd1498Szrj
1269338fd1498Szrj /* Drops the TREE_OVERFLOW flag from T. */
1269438fd1498Szrj
1269538fd1498Szrj tree
drop_tree_overflow(tree t)1269638fd1498Szrj drop_tree_overflow (tree t)
1269738fd1498Szrj {
1269838fd1498Szrj gcc_checking_assert (TREE_OVERFLOW (t));
1269938fd1498Szrj
1270038fd1498Szrj /* For tree codes with a sharing machinery re-build the result. */
1270138fd1498Szrj if (poly_int_tree_p (t))
1270238fd1498Szrj return wide_int_to_tree (TREE_TYPE (t), wi::to_poly_wide (t));
1270338fd1498Szrj
1270438fd1498Szrj /* For VECTOR_CST, remove the overflow bits from the encoded elements
1270538fd1498Szrj and canonicalize the result. */
1270638fd1498Szrj if (TREE_CODE (t) == VECTOR_CST)
1270738fd1498Szrj {
1270838fd1498Szrj tree_vector_builder builder;
1270938fd1498Szrj builder.new_unary_operation (TREE_TYPE (t), t, true);
1271038fd1498Szrj unsigned int count = builder.encoded_nelts ();
1271138fd1498Szrj for (unsigned int i = 0; i < count; ++i)
1271238fd1498Szrj {
1271338fd1498Szrj tree elt = VECTOR_CST_ELT (t, i);
1271438fd1498Szrj if (TREE_OVERFLOW (elt))
1271538fd1498Szrj elt = drop_tree_overflow (elt);
1271638fd1498Szrj builder.quick_push (elt);
1271738fd1498Szrj }
1271838fd1498Szrj return builder.build ();
1271938fd1498Szrj }
1272038fd1498Szrj
1272138fd1498Szrj /* Otherwise, as all tcc_constants are possibly shared, copy the node
1272238fd1498Szrj and drop the flag. */
1272338fd1498Szrj t = copy_node (t);
1272438fd1498Szrj TREE_OVERFLOW (t) = 0;
1272538fd1498Szrj
1272638fd1498Szrj /* For constants that contain nested constants, drop the flag
1272738fd1498Szrj from those as well. */
1272838fd1498Szrj if (TREE_CODE (t) == COMPLEX_CST)
1272938fd1498Szrj {
1273038fd1498Szrj if (TREE_OVERFLOW (TREE_REALPART (t)))
1273138fd1498Szrj TREE_REALPART (t) = drop_tree_overflow (TREE_REALPART (t));
1273238fd1498Szrj if (TREE_OVERFLOW (TREE_IMAGPART (t)))
1273338fd1498Szrj TREE_IMAGPART (t) = drop_tree_overflow (TREE_IMAGPART (t));
1273438fd1498Szrj }
1273538fd1498Szrj
1273638fd1498Szrj return t;
1273738fd1498Szrj }
1273838fd1498Szrj
1273938fd1498Szrj /* Given a memory reference expression T, return its base address.
1274038fd1498Szrj The base address of a memory reference expression is the main
1274138fd1498Szrj object being referenced. For instance, the base address for
1274238fd1498Szrj 'array[i].fld[j]' is 'array'. You can think of this as stripping
1274338fd1498Szrj away the offset part from a memory address.
1274438fd1498Szrj
1274538fd1498Szrj This function calls handled_component_p to strip away all the inner
1274638fd1498Szrj parts of the memory reference until it reaches the base object. */
1274738fd1498Szrj
1274838fd1498Szrj tree
get_base_address(tree t)1274938fd1498Szrj get_base_address (tree t)
1275038fd1498Szrj {
1275138fd1498Szrj while (handled_component_p (t))
1275238fd1498Szrj t = TREE_OPERAND (t, 0);
1275338fd1498Szrj
1275438fd1498Szrj if ((TREE_CODE (t) == MEM_REF
1275538fd1498Szrj || TREE_CODE (t) == TARGET_MEM_REF)
1275638fd1498Szrj && TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
1275738fd1498Szrj t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
1275838fd1498Szrj
1275938fd1498Szrj /* ??? Either the alias oracle or all callers need to properly deal
1276038fd1498Szrj with WITH_SIZE_EXPRs before we can look through those. */
1276138fd1498Szrj if (TREE_CODE (t) == WITH_SIZE_EXPR)
1276238fd1498Szrj return NULL_TREE;
1276338fd1498Szrj
1276438fd1498Szrj return t;
1276538fd1498Szrj }
1276638fd1498Szrj
1276738fd1498Szrj /* Return a tree of sizetype representing the size, in bytes, of the element
1276838fd1498Szrj of EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
1276938fd1498Szrj
1277038fd1498Szrj tree
array_ref_element_size(tree exp)1277138fd1498Szrj array_ref_element_size (tree exp)
1277238fd1498Szrj {
1277338fd1498Szrj tree aligned_size = TREE_OPERAND (exp, 3);
1277438fd1498Szrj tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)));
1277538fd1498Szrj location_t loc = EXPR_LOCATION (exp);
1277638fd1498Szrj
1277738fd1498Szrj /* If a size was specified in the ARRAY_REF, it's the size measured
1277838fd1498Szrj in alignment units of the element type. So multiply by that value. */
1277938fd1498Szrj if (aligned_size)
1278038fd1498Szrj {
1278138fd1498Szrj /* ??? tree_ssa_useless_type_conversion will eliminate casts to
1278238fd1498Szrj sizetype from another type of the same width and signedness. */
1278338fd1498Szrj if (TREE_TYPE (aligned_size) != sizetype)
1278438fd1498Szrj aligned_size = fold_convert_loc (loc, sizetype, aligned_size);
1278538fd1498Szrj return size_binop_loc (loc, MULT_EXPR, aligned_size,
1278638fd1498Szrj size_int (TYPE_ALIGN_UNIT (elmt_type)));
1278738fd1498Szrj }
1278838fd1498Szrj
1278938fd1498Szrj /* Otherwise, take the size from that of the element type. Substitute
1279038fd1498Szrj any PLACEHOLDER_EXPR that we have. */
1279138fd1498Szrj else
1279238fd1498Szrj return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elmt_type), exp);
1279338fd1498Szrj }
1279438fd1498Szrj
1279538fd1498Szrj /* Return a tree representing the lower bound of the array mentioned in
1279638fd1498Szrj EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
1279738fd1498Szrj
1279838fd1498Szrj tree
array_ref_low_bound(tree exp)1279938fd1498Szrj array_ref_low_bound (tree exp)
1280038fd1498Szrj {
1280138fd1498Szrj tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
1280238fd1498Szrj
1280338fd1498Szrj /* If a lower bound is specified in EXP, use it. */
1280438fd1498Szrj if (TREE_OPERAND (exp, 2))
1280538fd1498Szrj return TREE_OPERAND (exp, 2);
1280638fd1498Szrj
1280738fd1498Szrj /* Otherwise, if there is a domain type and it has a lower bound, use it,
1280838fd1498Szrj substituting for a PLACEHOLDER_EXPR as needed. */
1280938fd1498Szrj if (domain_type && TYPE_MIN_VALUE (domain_type))
1281038fd1498Szrj return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MIN_VALUE (domain_type), exp);
1281138fd1498Szrj
1281238fd1498Szrj /* Otherwise, return a zero of the appropriate type. */
1281338fd1498Szrj return build_int_cst (TREE_TYPE (TREE_OPERAND (exp, 1)), 0);
1281438fd1498Szrj }
1281538fd1498Szrj
1281638fd1498Szrj /* Return a tree representing the upper bound of the array mentioned in
1281738fd1498Szrj EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
1281838fd1498Szrj
1281938fd1498Szrj tree
array_ref_up_bound(tree exp)1282038fd1498Szrj array_ref_up_bound (tree exp)
1282138fd1498Szrj {
1282238fd1498Szrj tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
1282338fd1498Szrj
1282438fd1498Szrj /* If there is a domain type and it has an upper bound, use it, substituting
1282538fd1498Szrj for a PLACEHOLDER_EXPR as needed. */
1282638fd1498Szrj if (domain_type && TYPE_MAX_VALUE (domain_type))
1282738fd1498Szrj return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MAX_VALUE (domain_type), exp);
1282838fd1498Szrj
1282938fd1498Szrj /* Otherwise fail. */
1283038fd1498Szrj return NULL_TREE;
1283138fd1498Szrj }
1283238fd1498Szrj
1283338fd1498Szrj /* Returns true if REF is an array reference or a component reference
1283438fd1498Szrj to an array at the end of a structure.
1283538fd1498Szrj If this is the case, the array may be allocated larger
1283638fd1498Szrj than its upper bound implies. */
1283738fd1498Szrj
1283838fd1498Szrj bool
array_at_struct_end_p(tree ref)1283938fd1498Szrj array_at_struct_end_p (tree ref)
1284038fd1498Szrj {
1284138fd1498Szrj tree atype;
1284238fd1498Szrj
1284338fd1498Szrj if (TREE_CODE (ref) == ARRAY_REF
1284438fd1498Szrj || TREE_CODE (ref) == ARRAY_RANGE_REF)
1284538fd1498Szrj {
1284638fd1498Szrj atype = TREE_TYPE (TREE_OPERAND (ref, 0));
1284738fd1498Szrj ref = TREE_OPERAND (ref, 0);
1284838fd1498Szrj }
1284938fd1498Szrj else if (TREE_CODE (ref) == COMPONENT_REF
1285038fd1498Szrj && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 1))) == ARRAY_TYPE)
1285138fd1498Szrj atype = TREE_TYPE (TREE_OPERAND (ref, 1));
1285238fd1498Szrj else
1285338fd1498Szrj return false;
1285438fd1498Szrj
1285538fd1498Szrj if (TREE_CODE (ref) == STRING_CST)
1285638fd1498Szrj return false;
1285738fd1498Szrj
1285838fd1498Szrj tree ref_to_array = ref;
1285938fd1498Szrj while (handled_component_p (ref))
1286038fd1498Szrj {
1286138fd1498Szrj /* If the reference chain contains a component reference to a
1286238fd1498Szrj non-union type and there follows another field the reference
1286338fd1498Szrj is not at the end of a structure. */
1286438fd1498Szrj if (TREE_CODE (ref) == COMPONENT_REF)
1286538fd1498Szrj {
1286638fd1498Szrj if (TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
1286738fd1498Szrj {
1286838fd1498Szrj tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
1286938fd1498Szrj while (nextf && TREE_CODE (nextf) != FIELD_DECL)
1287038fd1498Szrj nextf = DECL_CHAIN (nextf);
1287138fd1498Szrj if (nextf)
1287238fd1498Szrj return false;
1287338fd1498Szrj }
1287438fd1498Szrj }
1287538fd1498Szrj /* If we have a multi-dimensional array we do not consider
1287638fd1498Szrj a non-innermost dimension as flex array if the whole
1287738fd1498Szrj multi-dimensional array is at struct end.
1287838fd1498Szrj Same for an array of aggregates with a trailing array
1287938fd1498Szrj member. */
1288038fd1498Szrj else if (TREE_CODE (ref) == ARRAY_REF)
1288138fd1498Szrj return false;
1288238fd1498Szrj else if (TREE_CODE (ref) == ARRAY_RANGE_REF)
1288338fd1498Szrj ;
1288438fd1498Szrj /* If we view an underlying object as sth else then what we
1288538fd1498Szrj gathered up to now is what we have to rely on. */
1288638fd1498Szrj else if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
1288738fd1498Szrj break;
1288838fd1498Szrj else
1288938fd1498Szrj gcc_unreachable ();
1289038fd1498Szrj
1289138fd1498Szrj ref = TREE_OPERAND (ref, 0);
1289238fd1498Szrj }
1289338fd1498Szrj
1289438fd1498Szrj /* The array now is at struct end. Treat flexible arrays as
1289538fd1498Szrj always subject to extend, even into just padding constrained by
1289638fd1498Szrj an underlying decl. */
1289738fd1498Szrj if (! TYPE_SIZE (atype)
1289838fd1498Szrj || ! TYPE_DOMAIN (atype)
1289938fd1498Szrj || ! TYPE_MAX_VALUE (TYPE_DOMAIN (atype)))
1290038fd1498Szrj return true;
1290138fd1498Szrj
1290238fd1498Szrj if (TREE_CODE (ref) == MEM_REF
1290338fd1498Szrj && TREE_CODE (TREE_OPERAND (ref, 0)) == ADDR_EXPR)
1290438fd1498Szrj ref = TREE_OPERAND (TREE_OPERAND (ref, 0), 0);
1290538fd1498Szrj
1290638fd1498Szrj /* If the reference is based on a declared entity, the size of the array
1290738fd1498Szrj is constrained by its given domain. (Do not trust commons PR/69368). */
1290838fd1498Szrj if (DECL_P (ref)
1290938fd1498Szrj && !(flag_unconstrained_commons
1291038fd1498Szrj && VAR_P (ref) && DECL_COMMON (ref))
1291138fd1498Szrj && DECL_SIZE_UNIT (ref)
1291238fd1498Szrj && TREE_CODE (DECL_SIZE_UNIT (ref)) == INTEGER_CST)
1291338fd1498Szrj {
1291438fd1498Szrj /* Check whether the array domain covers all of the available
1291538fd1498Szrj padding. */
1291638fd1498Szrj poly_int64 offset;
1291738fd1498Szrj if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (atype))) != INTEGER_CST
1291838fd1498Szrj || TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (atype))) != INTEGER_CST
1291938fd1498Szrj || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (atype))) != INTEGER_CST)
1292038fd1498Szrj return true;
1292138fd1498Szrj if (! get_addr_base_and_unit_offset (ref_to_array, &offset))
1292238fd1498Szrj return true;
1292338fd1498Szrj
1292438fd1498Szrj /* If at least one extra element fits it is a flexarray. */
1292538fd1498Szrj if (known_le ((wi::to_offset (TYPE_MAX_VALUE (TYPE_DOMAIN (atype)))
1292638fd1498Szrj - wi::to_offset (TYPE_MIN_VALUE (TYPE_DOMAIN (atype)))
1292738fd1498Szrj + 2)
1292838fd1498Szrj * wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (atype))),
1292938fd1498Szrj wi::to_offset (DECL_SIZE_UNIT (ref)) - offset))
1293038fd1498Szrj return true;
1293138fd1498Szrj
1293238fd1498Szrj return false;
1293338fd1498Szrj }
1293438fd1498Szrj
1293538fd1498Szrj return true;
1293638fd1498Szrj }
1293738fd1498Szrj
1293838fd1498Szrj /* Return a tree representing the offset, in bytes, of the field referenced
1293938fd1498Szrj by EXP. This does not include any offset in DECL_FIELD_BIT_OFFSET. */
1294038fd1498Szrj
1294138fd1498Szrj tree
component_ref_field_offset(tree exp)1294238fd1498Szrj component_ref_field_offset (tree exp)
1294338fd1498Szrj {
1294438fd1498Szrj tree aligned_offset = TREE_OPERAND (exp, 2);
1294538fd1498Szrj tree field = TREE_OPERAND (exp, 1);
1294638fd1498Szrj location_t loc = EXPR_LOCATION (exp);
1294738fd1498Szrj
1294838fd1498Szrj /* If an offset was specified in the COMPONENT_REF, it's the offset measured
1294938fd1498Szrj in units of DECL_OFFSET_ALIGN / BITS_PER_UNIT. So multiply by that
1295038fd1498Szrj value. */
1295138fd1498Szrj if (aligned_offset)
1295238fd1498Szrj {
1295338fd1498Szrj /* ??? tree_ssa_useless_type_conversion will eliminate casts to
1295438fd1498Szrj sizetype from another type of the same width and signedness. */
1295538fd1498Szrj if (TREE_TYPE (aligned_offset) != sizetype)
1295638fd1498Szrj aligned_offset = fold_convert_loc (loc, sizetype, aligned_offset);
1295738fd1498Szrj return size_binop_loc (loc, MULT_EXPR, aligned_offset,
1295838fd1498Szrj size_int (DECL_OFFSET_ALIGN (field)
1295938fd1498Szrj / BITS_PER_UNIT));
1296038fd1498Szrj }
1296138fd1498Szrj
1296238fd1498Szrj /* Otherwise, take the offset from that of the field. Substitute
1296338fd1498Szrj any PLACEHOLDER_EXPR that we have. */
1296438fd1498Szrj else
1296538fd1498Szrj return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp);
1296638fd1498Szrj }
1296738fd1498Szrj
1296838fd1498Szrj /* Return the machine mode of T. For vectors, returns the mode of the
1296938fd1498Szrj inner type. The main use case is to feed the result to HONOR_NANS,
1297038fd1498Szrj avoiding the BLKmode that a direct TYPE_MODE (T) might return. */
1297138fd1498Szrj
1297238fd1498Szrj machine_mode
element_mode(const_tree t)1297338fd1498Szrj element_mode (const_tree t)
1297438fd1498Szrj {
1297538fd1498Szrj if (!TYPE_P (t))
1297638fd1498Szrj t = TREE_TYPE (t);
1297738fd1498Szrj if (VECTOR_TYPE_P (t) || TREE_CODE (t) == COMPLEX_TYPE)
1297838fd1498Szrj t = TREE_TYPE (t);
1297938fd1498Szrj return TYPE_MODE (t);
1298038fd1498Szrj }
1298138fd1498Szrj
1298238fd1498Szrj /* Vector types need to re-check the target flags each time we report
1298338fd1498Szrj the machine mode. We need to do this because attribute target can
1298438fd1498Szrj change the result of vector_mode_supported_p and have_regs_of_mode
1298538fd1498Szrj on a per-function basis. Thus the TYPE_MODE of a VECTOR_TYPE can
1298638fd1498Szrj change on a per-function basis. */
1298738fd1498Szrj /* ??? Possibly a better solution is to run through all the types
1298838fd1498Szrj referenced by a function and re-compute the TYPE_MODE once, rather
1298938fd1498Szrj than make the TYPE_MODE macro call a function. */
1299038fd1498Szrj
1299138fd1498Szrj machine_mode
vector_type_mode(const_tree t)1299238fd1498Szrj vector_type_mode (const_tree t)
1299338fd1498Szrj {
1299438fd1498Szrj machine_mode mode;
1299538fd1498Szrj
1299638fd1498Szrj gcc_assert (TREE_CODE (t) == VECTOR_TYPE);
1299738fd1498Szrj
1299838fd1498Szrj mode = t->type_common.mode;
1299938fd1498Szrj if (VECTOR_MODE_P (mode)
1300038fd1498Szrj && (!targetm.vector_mode_supported_p (mode)
1300138fd1498Szrj || !have_regs_of_mode[mode]))
1300238fd1498Szrj {
1300338fd1498Szrj scalar_int_mode innermode;
1300438fd1498Szrj
1300538fd1498Szrj /* For integers, try mapping it to a same-sized scalar mode. */
1300638fd1498Szrj if (is_int_mode (TREE_TYPE (t)->type_common.mode, &innermode))
1300738fd1498Szrj {
1300838fd1498Szrj poly_int64 size = (TYPE_VECTOR_SUBPARTS (t)
1300938fd1498Szrj * GET_MODE_BITSIZE (innermode));
1301038fd1498Szrj scalar_int_mode mode;
1301138fd1498Szrj if (int_mode_for_size (size, 0).exists (&mode)
1301238fd1498Szrj && have_regs_of_mode[mode])
1301338fd1498Szrj return mode;
1301438fd1498Szrj }
1301538fd1498Szrj
1301638fd1498Szrj return BLKmode;
1301738fd1498Szrj }
1301838fd1498Szrj
1301938fd1498Szrj return mode;
1302038fd1498Szrj }
1302138fd1498Szrj
1302238fd1498Szrj /* Verify that basic properties of T match TV and thus T can be a variant of
1302338fd1498Szrj TV. TV should be the more specified variant (i.e. the main variant). */
1302438fd1498Szrj
1302538fd1498Szrj static bool
verify_type_variant(const_tree t,tree tv)1302638fd1498Szrj verify_type_variant (const_tree t, tree tv)
1302738fd1498Szrj {
1302838fd1498Szrj /* Type variant can differ by:
1302938fd1498Szrj
1303038fd1498Szrj - TYPE_QUALS: TYPE_READONLY, TYPE_VOLATILE, TYPE_ATOMIC, TYPE_RESTRICT,
1303138fd1498Szrj ENCODE_QUAL_ADDR_SPACE.
1303238fd1498Szrj - main variant may be TYPE_COMPLETE_P and variant types !TYPE_COMPLETE_P
1303338fd1498Szrj in this case some values may not be set in the variant types
1303438fd1498Szrj (see TYPE_COMPLETE_P checks).
1303538fd1498Szrj - it is possible to have TYPE_ARTIFICIAL variant of non-artifical type
1303638fd1498Szrj - by TYPE_NAME and attributes (i.e. when variant originate by typedef)
1303738fd1498Szrj - TYPE_CANONICAL (TYPE_ALIAS_SET is the same among variants)
1303838fd1498Szrj - by the alignment: TYPE_ALIGN and TYPE_USER_ALIGN
1303938fd1498Szrj - during LTO by TYPE_CONTEXT if type is TYPE_FILE_SCOPE_P
1304038fd1498Szrj this is necessary to make it possible to merge types form different TUs
1304138fd1498Szrj - arrays, pointers and references may have TREE_TYPE that is a variant
1304238fd1498Szrj of TREE_TYPE of their main variants.
1304338fd1498Szrj - aggregates may have new TYPE_FIELDS list that list variants of
1304438fd1498Szrj the main variant TYPE_FIELDS.
1304538fd1498Szrj - vector types may differ by TYPE_VECTOR_OPAQUE
1304638fd1498Szrj */
1304738fd1498Szrj
1304838fd1498Szrj /* Convenience macro for matching individual fields. */
1304938fd1498Szrj #define verify_variant_match(flag) \
1305038fd1498Szrj do { \
1305138fd1498Szrj if (flag (tv) != flag (t)) \
1305238fd1498Szrj { \
1305338fd1498Szrj error ("type variant differs by %s", #flag); \
1305438fd1498Szrj debug_tree (tv); \
1305538fd1498Szrj return false; \
1305638fd1498Szrj } \
1305738fd1498Szrj } while (false)
1305838fd1498Szrj
1305938fd1498Szrj /* tree_base checks. */
1306038fd1498Szrj
1306138fd1498Szrj verify_variant_match (TREE_CODE);
1306238fd1498Szrj /* FIXME: Ada builds non-artificial variants of artificial types. */
1306338fd1498Szrj if (TYPE_ARTIFICIAL (tv) && 0)
1306438fd1498Szrj verify_variant_match (TYPE_ARTIFICIAL);
1306538fd1498Szrj if (POINTER_TYPE_P (tv))
1306638fd1498Szrj verify_variant_match (TYPE_REF_CAN_ALIAS_ALL);
1306738fd1498Szrj /* FIXME: TYPE_SIZES_GIMPLIFIED may differs for Ada build. */
1306838fd1498Szrj verify_variant_match (TYPE_UNSIGNED);
1306938fd1498Szrj verify_variant_match (TYPE_PACKED);
1307038fd1498Szrj if (TREE_CODE (t) == REFERENCE_TYPE)
1307138fd1498Szrj verify_variant_match (TYPE_REF_IS_RVALUE);
1307238fd1498Szrj if (AGGREGATE_TYPE_P (t))
1307338fd1498Szrj verify_variant_match (TYPE_REVERSE_STORAGE_ORDER);
1307438fd1498Szrj else
1307538fd1498Szrj verify_variant_match (TYPE_SATURATING);
1307638fd1498Szrj /* FIXME: This check trigger during libstdc++ build. */
1307738fd1498Szrj if (RECORD_OR_UNION_TYPE_P (t) && COMPLETE_TYPE_P (t) && 0)
1307838fd1498Szrj verify_variant_match (TYPE_FINAL_P);
1307938fd1498Szrj
1308038fd1498Szrj /* tree_type_common checks. */
1308138fd1498Szrj
1308238fd1498Szrj if (COMPLETE_TYPE_P (t))
1308338fd1498Szrj {
1308438fd1498Szrj verify_variant_match (TYPE_MODE);
1308538fd1498Szrj if (TREE_CODE (TYPE_SIZE (t)) != PLACEHOLDER_EXPR
1308638fd1498Szrj && TREE_CODE (TYPE_SIZE (tv)) != PLACEHOLDER_EXPR)
1308738fd1498Szrj verify_variant_match (TYPE_SIZE);
1308838fd1498Szrj if (TREE_CODE (TYPE_SIZE_UNIT (t)) != PLACEHOLDER_EXPR
1308938fd1498Szrj && TREE_CODE (TYPE_SIZE_UNIT (tv)) != PLACEHOLDER_EXPR
1309038fd1498Szrj && TYPE_SIZE_UNIT (t) != TYPE_SIZE_UNIT (tv))
1309138fd1498Szrj {
1309238fd1498Szrj gcc_assert (!operand_equal_p (TYPE_SIZE_UNIT (t),
1309338fd1498Szrj TYPE_SIZE_UNIT (tv), 0));
1309438fd1498Szrj error ("type variant has different TYPE_SIZE_UNIT");
1309538fd1498Szrj debug_tree (tv);
1309638fd1498Szrj error ("type variant's TYPE_SIZE_UNIT");
1309738fd1498Szrj debug_tree (TYPE_SIZE_UNIT (tv));
1309838fd1498Szrj error ("type's TYPE_SIZE_UNIT");
1309938fd1498Szrj debug_tree (TYPE_SIZE_UNIT (t));
1310038fd1498Szrj return false;
1310138fd1498Szrj }
1310238fd1498Szrj }
1310338fd1498Szrj verify_variant_match (TYPE_PRECISION);
1310438fd1498Szrj verify_variant_match (TYPE_NEEDS_CONSTRUCTING);
1310538fd1498Szrj if (RECORD_OR_UNION_TYPE_P (t))
1310638fd1498Szrj verify_variant_match (TYPE_TRANSPARENT_AGGR);
1310738fd1498Szrj else if (TREE_CODE (t) == ARRAY_TYPE)
1310838fd1498Szrj verify_variant_match (TYPE_NONALIASED_COMPONENT);
1310938fd1498Szrj /* During LTO we merge variant lists from diferent translation units
1311038fd1498Szrj that may differ BY TYPE_CONTEXT that in turn may point
1311138fd1498Szrj to TRANSLATION_UNIT_DECL.
1311238fd1498Szrj Ada also builds variants of types with different TYPE_CONTEXT. */
1311338fd1498Szrj if ((!in_lto_p || !TYPE_FILE_SCOPE_P (t)) && 0)
1311438fd1498Szrj verify_variant_match (TYPE_CONTEXT);
1311538fd1498Szrj verify_variant_match (TYPE_STRING_FLAG);
1311638fd1498Szrj if (TYPE_ALIAS_SET_KNOWN_P (t))
1311738fd1498Szrj {
1311838fd1498Szrj error ("type variant with TYPE_ALIAS_SET_KNOWN_P");
1311938fd1498Szrj debug_tree (tv);
1312038fd1498Szrj return false;
1312138fd1498Szrj }
1312238fd1498Szrj
1312338fd1498Szrj /* tree_type_non_common checks. */
1312438fd1498Szrj
1312538fd1498Szrj /* FIXME: C FE uses TYPE_VFIELD to record C_TYPE_INCOMPLETE_VARS
1312638fd1498Szrj and dangle the pointer from time to time. */
1312738fd1498Szrj if (RECORD_OR_UNION_TYPE_P (t) && TYPE_VFIELD (t) != TYPE_VFIELD (tv)
1312838fd1498Szrj && (in_lto_p || !TYPE_VFIELD (tv)
1312938fd1498Szrj || TREE_CODE (TYPE_VFIELD (tv)) != TREE_LIST))
1313038fd1498Szrj {
1313138fd1498Szrj error ("type variant has different TYPE_VFIELD");
1313238fd1498Szrj debug_tree (tv);
1313338fd1498Szrj return false;
1313438fd1498Szrj }
1313538fd1498Szrj if ((TREE_CODE (t) == ENUMERAL_TYPE && COMPLETE_TYPE_P (t))
1313638fd1498Szrj || TREE_CODE (t) == INTEGER_TYPE
1313738fd1498Szrj || TREE_CODE (t) == BOOLEAN_TYPE
1313838fd1498Szrj || TREE_CODE (t) == REAL_TYPE
1313938fd1498Szrj || TREE_CODE (t) == FIXED_POINT_TYPE)
1314038fd1498Szrj {
1314138fd1498Szrj verify_variant_match (TYPE_MAX_VALUE);
1314238fd1498Szrj verify_variant_match (TYPE_MIN_VALUE);
1314338fd1498Szrj }
1314438fd1498Szrj if (TREE_CODE (t) == METHOD_TYPE)
1314538fd1498Szrj verify_variant_match (TYPE_METHOD_BASETYPE);
1314638fd1498Szrj if (TREE_CODE (t) == OFFSET_TYPE)
1314738fd1498Szrj verify_variant_match (TYPE_OFFSET_BASETYPE);
1314838fd1498Szrj if (TREE_CODE (t) == ARRAY_TYPE)
1314938fd1498Szrj verify_variant_match (TYPE_ARRAY_MAX_SIZE);
1315038fd1498Szrj /* FIXME: Be lax and allow TYPE_BINFO to be missing in variant types
1315138fd1498Szrj or even type's main variant. This is needed to make bootstrap pass
1315238fd1498Szrj and the bug seems new in GCC 5.
1315338fd1498Szrj C++ FE should be updated to make this consistent and we should check
1315438fd1498Szrj that TYPE_BINFO is always NULL for !COMPLETE_TYPE_P and otherwise there
1315538fd1498Szrj is a match with main variant.
1315638fd1498Szrj
1315738fd1498Szrj Also disable the check for Java for now because of parser hack that builds
1315838fd1498Szrj first an dummy BINFO and then sometimes replace it by real BINFO in some
1315938fd1498Szrj of the copies. */
1316038fd1498Szrj if (RECORD_OR_UNION_TYPE_P (t) && TYPE_BINFO (t) && TYPE_BINFO (tv)
1316138fd1498Szrj && TYPE_BINFO (t) != TYPE_BINFO (tv)
1316238fd1498Szrj /* FIXME: Java sometimes keep dump TYPE_BINFOs on variant types.
1316338fd1498Szrj Since there is no cheap way to tell C++/Java type w/o LTO, do checking
1316438fd1498Szrj at LTO time only. */
1316538fd1498Szrj && (in_lto_p && odr_type_p (t)))
1316638fd1498Szrj {
1316738fd1498Szrj error ("type variant has different TYPE_BINFO");
1316838fd1498Szrj debug_tree (tv);
1316938fd1498Szrj error ("type variant's TYPE_BINFO");
1317038fd1498Szrj debug_tree (TYPE_BINFO (tv));
1317138fd1498Szrj error ("type's TYPE_BINFO");
1317238fd1498Szrj debug_tree (TYPE_BINFO (t));
1317338fd1498Szrj return false;
1317438fd1498Szrj }
1317538fd1498Szrj
1317638fd1498Szrj /* Check various uses of TYPE_VALUES_RAW. */
1317738fd1498Szrj if (TREE_CODE (t) == ENUMERAL_TYPE)
1317838fd1498Szrj verify_variant_match (TYPE_VALUES);
1317938fd1498Szrj else if (TREE_CODE (t) == ARRAY_TYPE)
1318038fd1498Szrj verify_variant_match (TYPE_DOMAIN);
1318138fd1498Szrj /* Permit incomplete variants of complete type. While FEs may complete
1318238fd1498Szrj all variants, this does not happen for C++ templates in all cases. */
1318338fd1498Szrj else if (RECORD_OR_UNION_TYPE_P (t)
1318438fd1498Szrj && COMPLETE_TYPE_P (t)
1318538fd1498Szrj && TYPE_FIELDS (t) != TYPE_FIELDS (tv))
1318638fd1498Szrj {
1318738fd1498Szrj tree f1, f2;
1318838fd1498Szrj
1318938fd1498Szrj /* Fortran builds qualified variants as new records with items of
1319038fd1498Szrj qualified type. Verify that they looks same. */
1319138fd1498Szrj for (f1 = TYPE_FIELDS (t), f2 = TYPE_FIELDS (tv);
1319238fd1498Szrj f1 && f2;
1319338fd1498Szrj f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
1319438fd1498Szrj if (TREE_CODE (f1) != FIELD_DECL || TREE_CODE (f2) != FIELD_DECL
1319538fd1498Szrj || (TYPE_MAIN_VARIANT (TREE_TYPE (f1))
1319638fd1498Szrj != TYPE_MAIN_VARIANT (TREE_TYPE (f2))
1319738fd1498Szrj /* FIXME: gfc_nonrestricted_type builds all types as variants
1319838fd1498Szrj with exception of pointer types. It deeply copies the type
1319938fd1498Szrj which means that we may end up with a variant type
1320038fd1498Szrj referring non-variant pointer. We may change it to
1320138fd1498Szrj produce types as variants, too, like
1320238fd1498Szrj objc_get_protocol_qualified_type does. */
1320338fd1498Szrj && !POINTER_TYPE_P (TREE_TYPE (f1)))
1320438fd1498Szrj || DECL_FIELD_OFFSET (f1) != DECL_FIELD_OFFSET (f2)
1320538fd1498Szrj || DECL_FIELD_BIT_OFFSET (f1) != DECL_FIELD_BIT_OFFSET (f2))
1320638fd1498Szrj break;
1320738fd1498Szrj if (f1 || f2)
1320838fd1498Szrj {
1320938fd1498Szrj error ("type variant has different TYPE_FIELDS");
1321038fd1498Szrj debug_tree (tv);
1321138fd1498Szrj error ("first mismatch is field");
1321238fd1498Szrj debug_tree (f1);
1321338fd1498Szrj error ("and field");
1321438fd1498Szrj debug_tree (f2);
1321538fd1498Szrj return false;
1321638fd1498Szrj }
1321738fd1498Szrj }
1321838fd1498Szrj else if ((TREE_CODE (t) == FUNCTION_TYPE || TREE_CODE (t) == METHOD_TYPE))
1321938fd1498Szrj verify_variant_match (TYPE_ARG_TYPES);
1322038fd1498Szrj /* For C++ the qualified variant of array type is really an array type
1322138fd1498Szrj of qualified TREE_TYPE.
1322238fd1498Szrj objc builds variants of pointer where pointer to type is a variant, too
1322338fd1498Szrj in objc_get_protocol_qualified_type. */
1322438fd1498Szrj if (TREE_TYPE (t) != TREE_TYPE (tv)
1322538fd1498Szrj && ((TREE_CODE (t) != ARRAY_TYPE
1322638fd1498Szrj && !POINTER_TYPE_P (t))
1322738fd1498Szrj || TYPE_MAIN_VARIANT (TREE_TYPE (t))
1322838fd1498Szrj != TYPE_MAIN_VARIANT (TREE_TYPE (tv))))
1322938fd1498Szrj {
1323038fd1498Szrj error ("type variant has different TREE_TYPE");
1323138fd1498Szrj debug_tree (tv);
1323238fd1498Szrj error ("type variant's TREE_TYPE");
1323338fd1498Szrj debug_tree (TREE_TYPE (tv));
1323438fd1498Szrj error ("type's TREE_TYPE");
1323538fd1498Szrj debug_tree (TREE_TYPE (t));
1323638fd1498Szrj return false;
1323738fd1498Szrj }
1323838fd1498Szrj if (type_with_alias_set_p (t)
1323938fd1498Szrj && !gimple_canonical_types_compatible_p (t, tv, false))
1324038fd1498Szrj {
1324138fd1498Szrj error ("type is not compatible with its variant");
1324238fd1498Szrj debug_tree (tv);
1324338fd1498Szrj error ("type variant's TREE_TYPE");
1324438fd1498Szrj debug_tree (TREE_TYPE (tv));
1324538fd1498Szrj error ("type's TREE_TYPE");
1324638fd1498Szrj debug_tree (TREE_TYPE (t));
1324738fd1498Szrj return false;
1324838fd1498Szrj }
1324938fd1498Szrj return true;
1325038fd1498Szrj #undef verify_variant_match
1325138fd1498Szrj }
1325238fd1498Szrj
1325338fd1498Szrj
1325438fd1498Szrj /* The TYPE_CANONICAL merging machinery. It should closely resemble
1325538fd1498Szrj the middle-end types_compatible_p function. It needs to avoid
1325638fd1498Szrj claiming types are different for types that should be treated
1325738fd1498Szrj the same with respect to TBAA. Canonical types are also used
1325838fd1498Szrj for IL consistency checks via the useless_type_conversion_p
1325938fd1498Szrj predicate which does not handle all type kinds itself but falls
1326038fd1498Szrj back to pointer-comparison of TYPE_CANONICAL for aggregates
1326138fd1498Szrj for example. */
1326238fd1498Szrj
1326338fd1498Szrj /* Return true if TYPE_UNSIGNED of TYPE should be ignored for canonical
1326438fd1498Szrj type calculation because we need to allow inter-operability between signed
1326538fd1498Szrj and unsigned variants. */
1326638fd1498Szrj
1326738fd1498Szrj bool
type_with_interoperable_signedness(const_tree type)1326838fd1498Szrj type_with_interoperable_signedness (const_tree type)
1326938fd1498Szrj {
1327038fd1498Szrj /* Fortran standard require C_SIGNED_CHAR to be interoperable with both
1327138fd1498Szrj signed char and unsigned char. Similarly fortran FE builds
1327238fd1498Szrj C_SIZE_T as signed type, while C defines it unsigned. */
1327338fd1498Szrj
1327438fd1498Szrj return tree_code_for_canonical_type_merging (TREE_CODE (type))
1327538fd1498Szrj == INTEGER_TYPE
1327638fd1498Szrj && (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node)
1327738fd1498Szrj || TYPE_PRECISION (type) == TYPE_PRECISION (size_type_node));
1327838fd1498Szrj }
1327938fd1498Szrj
1328038fd1498Szrj /* Return true iff T1 and T2 are structurally identical for what
1328138fd1498Szrj TBAA is concerned.
1328238fd1498Szrj This function is used both by lto.c canonical type merging and by the
1328338fd1498Szrj verifier. If TRUST_TYPE_CANONICAL we do not look into structure of types
1328438fd1498Szrj that have TYPE_CANONICAL defined and assume them equivalent. This is useful
1328538fd1498Szrj only for LTO because only in these cases TYPE_CANONICAL equivalence
1328638fd1498Szrj correspond to one defined by gimple_canonical_types_compatible_p. */
1328738fd1498Szrj
1328838fd1498Szrj bool
gimple_canonical_types_compatible_p(const_tree t1,const_tree t2,bool trust_type_canonical)1328938fd1498Szrj gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
1329038fd1498Szrj bool trust_type_canonical)
1329138fd1498Szrj {
1329238fd1498Szrj /* Type variants should be same as the main variant. When not doing sanity
1329338fd1498Szrj checking to verify this fact, go to main variants and save some work. */
1329438fd1498Szrj if (trust_type_canonical)
1329538fd1498Szrj {
1329638fd1498Szrj t1 = TYPE_MAIN_VARIANT (t1);
1329738fd1498Szrj t2 = TYPE_MAIN_VARIANT (t2);
1329838fd1498Szrj }
1329938fd1498Szrj
1330038fd1498Szrj /* Check first for the obvious case of pointer identity. */
1330138fd1498Szrj if (t1 == t2)
1330238fd1498Szrj return true;
1330338fd1498Szrj
1330438fd1498Szrj /* Check that we have two types to compare. */
1330538fd1498Szrj if (t1 == NULL_TREE || t2 == NULL_TREE)
1330638fd1498Szrj return false;
1330738fd1498Szrj
1330838fd1498Szrj /* We consider complete types always compatible with incomplete type.
1330938fd1498Szrj This does not make sense for canonical type calculation and thus we
1331038fd1498Szrj need to ensure that we are never called on it.
1331138fd1498Szrj
1331238fd1498Szrj FIXME: For more correctness the function probably should have three modes
1331338fd1498Szrj 1) mode assuming that types are complete mathcing their structure
1331438fd1498Szrj 2) mode allowing incomplete types but producing equivalence classes
1331538fd1498Szrj and thus ignoring all info from complete types
1331638fd1498Szrj 3) mode allowing incomplete types to match complete but checking
1331738fd1498Szrj compatibility between complete types.
1331838fd1498Szrj
1331938fd1498Szrj 1 and 2 can be used for canonical type calculation. 3 is the real
1332038fd1498Szrj definition of type compatibility that can be used i.e. for warnings during
1332138fd1498Szrj declaration merging. */
1332238fd1498Szrj
1332338fd1498Szrj gcc_assert (!trust_type_canonical
1332438fd1498Szrj || (type_with_alias_set_p (t1) && type_with_alias_set_p (t2)));
1332538fd1498Szrj /* If the types have been previously registered and found equal
1332638fd1498Szrj they still are. */
1332738fd1498Szrj
1332838fd1498Szrj if (TYPE_CANONICAL (t1) && TYPE_CANONICAL (t2)
1332938fd1498Szrj && trust_type_canonical)
1333038fd1498Szrj {
1333138fd1498Szrj /* Do not use TYPE_CANONICAL of pointer types. For LTO streamed types
1333238fd1498Szrj they are always NULL, but they are set to non-NULL for types
1333338fd1498Szrj constructed by build_pointer_type and variants. In this case the
1333438fd1498Szrj TYPE_CANONICAL is more fine grained than the equivalnce we test (where
1333538fd1498Szrj all pointers are considered equal. Be sure to not return false
1333638fd1498Szrj negatives. */
1333738fd1498Szrj gcc_checking_assert (canonical_type_used_p (t1)
1333838fd1498Szrj && canonical_type_used_p (t2));
1333938fd1498Szrj return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
1334038fd1498Szrj }
1334138fd1498Szrj
1334238fd1498Szrj /* Can't be the same type if the types don't have the same code. */
1334338fd1498Szrj enum tree_code code = tree_code_for_canonical_type_merging (TREE_CODE (t1));
1334438fd1498Szrj if (code != tree_code_for_canonical_type_merging (TREE_CODE (t2)))
1334538fd1498Szrj return false;
1334638fd1498Szrj
1334738fd1498Szrj /* Qualifiers do not matter for canonical type comparison purposes. */
1334838fd1498Szrj
1334938fd1498Szrj /* Void types and nullptr types are always the same. */
1335038fd1498Szrj if (TREE_CODE (t1) == VOID_TYPE
1335138fd1498Szrj || TREE_CODE (t1) == NULLPTR_TYPE)
1335238fd1498Szrj return true;
1335338fd1498Szrj
1335438fd1498Szrj /* Can't be the same type if they have different mode. */
1335538fd1498Szrj if (TYPE_MODE (t1) != TYPE_MODE (t2))
1335638fd1498Szrj return false;
1335738fd1498Szrj
1335838fd1498Szrj /* Non-aggregate types can be handled cheaply. */
1335938fd1498Szrj if (INTEGRAL_TYPE_P (t1)
1336038fd1498Szrj || SCALAR_FLOAT_TYPE_P (t1)
1336138fd1498Szrj || FIXED_POINT_TYPE_P (t1)
1336238fd1498Szrj || TREE_CODE (t1) == VECTOR_TYPE
1336338fd1498Szrj || TREE_CODE (t1) == COMPLEX_TYPE
1336438fd1498Szrj || TREE_CODE (t1) == OFFSET_TYPE
1336538fd1498Szrj || POINTER_TYPE_P (t1))
1336638fd1498Szrj {
1336738fd1498Szrj /* Can't be the same type if they have different recision. */
1336838fd1498Szrj if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2))
1336938fd1498Szrj return false;
1337038fd1498Szrj
1337138fd1498Szrj /* In some cases the signed and unsigned types are required to be
1337238fd1498Szrj inter-operable. */
1337338fd1498Szrj if (TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)
1337438fd1498Szrj && !type_with_interoperable_signedness (t1))
1337538fd1498Szrj return false;
1337638fd1498Szrj
1337738fd1498Szrj /* Fortran's C_SIGNED_CHAR is !TYPE_STRING_FLAG but needs to be
1337838fd1498Szrj interoperable with "signed char". Unless all frontends are revisited
1337938fd1498Szrj to agree on these types, we must ignore the flag completely. */
1338038fd1498Szrj
1338138fd1498Szrj /* Fortran standard define C_PTR type that is compatible with every
1338238fd1498Szrj C pointer. For this reason we need to glob all pointers into one.
1338338fd1498Szrj Still pointers in different address spaces are not compatible. */
1338438fd1498Szrj if (POINTER_TYPE_P (t1))
1338538fd1498Szrj {
1338638fd1498Szrj if (TYPE_ADDR_SPACE (TREE_TYPE (t1))
1338738fd1498Szrj != TYPE_ADDR_SPACE (TREE_TYPE (t2)))
1338838fd1498Szrj return false;
1338938fd1498Szrj }
1339038fd1498Szrj
1339138fd1498Szrj /* Tail-recurse to components. */
1339238fd1498Szrj if (TREE_CODE (t1) == VECTOR_TYPE
1339338fd1498Szrj || TREE_CODE (t1) == COMPLEX_TYPE)
1339438fd1498Szrj return gimple_canonical_types_compatible_p (TREE_TYPE (t1),
1339538fd1498Szrj TREE_TYPE (t2),
1339638fd1498Szrj trust_type_canonical);
1339738fd1498Szrj
1339838fd1498Szrj return true;
1339938fd1498Szrj }
1340038fd1498Szrj
1340138fd1498Szrj /* Do type-specific comparisons. */
1340238fd1498Szrj switch (TREE_CODE (t1))
1340338fd1498Szrj {
1340438fd1498Szrj case ARRAY_TYPE:
1340538fd1498Szrj /* Array types are the same if the element types are the same and
1340638fd1498Szrj the number of elements are the same. */
1340738fd1498Szrj if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2),
1340838fd1498Szrj trust_type_canonical)
1340938fd1498Szrj || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
1341038fd1498Szrj || TYPE_REVERSE_STORAGE_ORDER (t1) != TYPE_REVERSE_STORAGE_ORDER (t2)
1341138fd1498Szrj || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
1341238fd1498Szrj return false;
1341338fd1498Szrj else
1341438fd1498Szrj {
1341538fd1498Szrj tree i1 = TYPE_DOMAIN (t1);
1341638fd1498Szrj tree i2 = TYPE_DOMAIN (t2);
1341738fd1498Szrj
1341838fd1498Szrj /* For an incomplete external array, the type domain can be
1341938fd1498Szrj NULL_TREE. Check this condition also. */
1342038fd1498Szrj if (i1 == NULL_TREE && i2 == NULL_TREE)
1342138fd1498Szrj return true;
1342238fd1498Szrj else if (i1 == NULL_TREE || i2 == NULL_TREE)
1342338fd1498Szrj return false;
1342438fd1498Szrj else
1342538fd1498Szrj {
1342638fd1498Szrj tree min1 = TYPE_MIN_VALUE (i1);
1342738fd1498Szrj tree min2 = TYPE_MIN_VALUE (i2);
1342838fd1498Szrj tree max1 = TYPE_MAX_VALUE (i1);
1342938fd1498Szrj tree max2 = TYPE_MAX_VALUE (i2);
1343038fd1498Szrj
1343138fd1498Szrj /* The minimum/maximum values have to be the same. */
1343238fd1498Szrj if ((min1 == min2
1343338fd1498Szrj || (min1 && min2
1343438fd1498Szrj && ((TREE_CODE (min1) == PLACEHOLDER_EXPR
1343538fd1498Szrj && TREE_CODE (min2) == PLACEHOLDER_EXPR)
1343638fd1498Szrj || operand_equal_p (min1, min2, 0))))
1343738fd1498Szrj && (max1 == max2
1343838fd1498Szrj || (max1 && max2
1343938fd1498Szrj && ((TREE_CODE (max1) == PLACEHOLDER_EXPR
1344038fd1498Szrj && TREE_CODE (max2) == PLACEHOLDER_EXPR)
1344138fd1498Szrj || operand_equal_p (max1, max2, 0)))))
1344238fd1498Szrj return true;
1344338fd1498Szrj else
1344438fd1498Szrj return false;
1344538fd1498Szrj }
1344638fd1498Szrj }
1344738fd1498Szrj
1344838fd1498Szrj case METHOD_TYPE:
1344938fd1498Szrj case FUNCTION_TYPE:
1345038fd1498Szrj /* Function types are the same if the return type and arguments types
1345138fd1498Szrj are the same. */
1345238fd1498Szrj if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2),
1345338fd1498Szrj trust_type_canonical))
1345438fd1498Szrj return false;
1345538fd1498Szrj
1345638fd1498Szrj if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
1345738fd1498Szrj return true;
1345838fd1498Szrj else
1345938fd1498Szrj {
1346038fd1498Szrj tree parms1, parms2;
1346138fd1498Szrj
1346238fd1498Szrj for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
1346338fd1498Szrj parms1 && parms2;
1346438fd1498Szrj parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
1346538fd1498Szrj {
1346638fd1498Szrj if (!gimple_canonical_types_compatible_p
1346738fd1498Szrj (TREE_VALUE (parms1), TREE_VALUE (parms2),
1346838fd1498Szrj trust_type_canonical))
1346938fd1498Szrj return false;
1347038fd1498Szrj }
1347138fd1498Szrj
1347238fd1498Szrj if (parms1 || parms2)
1347338fd1498Szrj return false;
1347438fd1498Szrj
1347538fd1498Szrj return true;
1347638fd1498Szrj }
1347738fd1498Szrj
1347838fd1498Szrj case RECORD_TYPE:
1347938fd1498Szrj case UNION_TYPE:
1348038fd1498Szrj case QUAL_UNION_TYPE:
1348138fd1498Szrj {
1348238fd1498Szrj tree f1, f2;
1348338fd1498Szrj
1348438fd1498Szrj /* Don't try to compare variants of an incomplete type, before
1348538fd1498Szrj TYPE_FIELDS has been copied around. */
1348638fd1498Szrj if (!COMPLETE_TYPE_P (t1) && !COMPLETE_TYPE_P (t2))
1348738fd1498Szrj return true;
1348838fd1498Szrj
1348938fd1498Szrj
1349038fd1498Szrj if (TYPE_REVERSE_STORAGE_ORDER (t1) != TYPE_REVERSE_STORAGE_ORDER (t2))
1349138fd1498Szrj return false;
1349238fd1498Szrj
1349338fd1498Szrj /* For aggregate types, all the fields must be the same. */
1349438fd1498Szrj for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
1349538fd1498Szrj f1 || f2;
1349638fd1498Szrj f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
1349738fd1498Szrj {
1349838fd1498Szrj /* Skip non-fields and zero-sized fields. */
1349938fd1498Szrj while (f1 && (TREE_CODE (f1) != FIELD_DECL
1350038fd1498Szrj || (DECL_SIZE (f1)
1350138fd1498Szrj && integer_zerop (DECL_SIZE (f1)))))
1350238fd1498Szrj f1 = TREE_CHAIN (f1);
1350338fd1498Szrj while (f2 && (TREE_CODE (f2) != FIELD_DECL
1350438fd1498Szrj || (DECL_SIZE (f2)
1350538fd1498Szrj && integer_zerop (DECL_SIZE (f2)))))
1350638fd1498Szrj f2 = TREE_CHAIN (f2);
1350738fd1498Szrj if (!f1 || !f2)
1350838fd1498Szrj break;
1350938fd1498Szrj /* The fields must have the same name, offset and type. */
1351038fd1498Szrj if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
1351138fd1498Szrj || !gimple_compare_field_offset (f1, f2)
1351238fd1498Szrj || !gimple_canonical_types_compatible_p
1351338fd1498Szrj (TREE_TYPE (f1), TREE_TYPE (f2),
1351438fd1498Szrj trust_type_canonical))
1351538fd1498Szrj return false;
1351638fd1498Szrj }
1351738fd1498Szrj
1351838fd1498Szrj /* If one aggregate has more fields than the other, they
1351938fd1498Szrj are not the same. */
1352038fd1498Szrj if (f1 || f2)
1352138fd1498Szrj return false;
1352238fd1498Szrj
1352338fd1498Szrj return true;
1352438fd1498Szrj }
1352538fd1498Szrj
1352638fd1498Szrj default:
1352738fd1498Szrj /* Consider all types with language specific trees in them mutually
1352838fd1498Szrj compatible. This is executed only from verify_type and false
1352938fd1498Szrj positives can be tolerated. */
1353038fd1498Szrj gcc_assert (!in_lto_p);
1353138fd1498Szrj return true;
1353238fd1498Szrj }
1353338fd1498Szrj }
1353438fd1498Szrj
1353538fd1498Szrj /* Verify type T. */
1353638fd1498Szrj
1353738fd1498Szrj void
verify_type(const_tree t)1353838fd1498Szrj verify_type (const_tree t)
1353938fd1498Szrj {
1354038fd1498Szrj bool error_found = false;
1354138fd1498Szrj tree mv = TYPE_MAIN_VARIANT (t);
1354238fd1498Szrj if (!mv)
1354338fd1498Szrj {
1354438fd1498Szrj error ("Main variant is not defined");
1354538fd1498Szrj error_found = true;
1354638fd1498Szrj }
1354738fd1498Szrj else if (mv != TYPE_MAIN_VARIANT (mv))
1354838fd1498Szrj {
1354938fd1498Szrj error ("TYPE_MAIN_VARIANT has different TYPE_MAIN_VARIANT");
1355038fd1498Szrj debug_tree (mv);
1355138fd1498Szrj error_found = true;
1355238fd1498Szrj }
1355338fd1498Szrj else if (t != mv && !verify_type_variant (t, mv))
1355438fd1498Szrj error_found = true;
1355538fd1498Szrj
1355638fd1498Szrj tree ct = TYPE_CANONICAL (t);
1355738fd1498Szrj if (!ct)
1355838fd1498Szrj ;
1355938fd1498Szrj else if (TYPE_CANONICAL (t) != ct)
1356038fd1498Szrj {
1356138fd1498Szrj error ("TYPE_CANONICAL has different TYPE_CANONICAL");
1356238fd1498Szrj debug_tree (ct);
1356338fd1498Szrj error_found = true;
1356438fd1498Szrj }
1356538fd1498Szrj /* Method and function types can not be used to address memory and thus
1356638fd1498Szrj TYPE_CANONICAL really matters only for determining useless conversions.
1356738fd1498Szrj
1356838fd1498Szrj FIXME: C++ FE produce declarations of builtin functions that are not
1356938fd1498Szrj compatible with main variants. */
1357038fd1498Szrj else if (TREE_CODE (t) == FUNCTION_TYPE)
1357138fd1498Szrj ;
1357238fd1498Szrj else if (t != ct
1357338fd1498Szrj /* FIXME: gimple_canonical_types_compatible_p can not compare types
1357438fd1498Szrj with variably sized arrays because their sizes possibly
1357538fd1498Szrj gimplified to different variables. */
1357638fd1498Szrj && !variably_modified_type_p (ct, NULL)
1357738fd1498Szrj && !gimple_canonical_types_compatible_p (t, ct, false))
1357838fd1498Szrj {
1357938fd1498Szrj error ("TYPE_CANONICAL is not compatible");
1358038fd1498Szrj debug_tree (ct);
1358138fd1498Szrj error_found = true;
1358238fd1498Szrj }
1358338fd1498Szrj
1358438fd1498Szrj if (COMPLETE_TYPE_P (t) && TYPE_CANONICAL (t)
1358538fd1498Szrj && TYPE_MODE (t) != TYPE_MODE (TYPE_CANONICAL (t)))
1358638fd1498Szrj {
1358738fd1498Szrj error ("TYPE_MODE of TYPE_CANONICAL is not compatible");
1358838fd1498Szrj debug_tree (ct);
1358938fd1498Szrj error_found = true;
1359038fd1498Szrj }
1359138fd1498Szrj if (TYPE_MAIN_VARIANT (t) == t && ct && TYPE_MAIN_VARIANT (ct) != ct)
1359238fd1498Szrj {
1359338fd1498Szrj error ("TYPE_CANONICAL of main variant is not main variant");
1359438fd1498Szrj debug_tree (ct);
1359538fd1498Szrj debug_tree (TYPE_MAIN_VARIANT (ct));
1359638fd1498Szrj error_found = true;
1359738fd1498Szrj }
1359838fd1498Szrj
1359938fd1498Szrj
1360038fd1498Szrj /* Check various uses of TYPE_MIN_VALUE_RAW. */
1360138fd1498Szrj if (RECORD_OR_UNION_TYPE_P (t))
1360238fd1498Szrj {
1360338fd1498Szrj /* FIXME: C FE uses TYPE_VFIELD to record C_TYPE_INCOMPLETE_VARS
1360438fd1498Szrj and danagle the pointer from time to time. */
1360538fd1498Szrj if (TYPE_VFIELD (t)
1360638fd1498Szrj && TREE_CODE (TYPE_VFIELD (t)) != FIELD_DECL
1360738fd1498Szrj && TREE_CODE (TYPE_VFIELD (t)) != TREE_LIST)
1360838fd1498Szrj {
1360938fd1498Szrj error ("TYPE_VFIELD is not FIELD_DECL nor TREE_LIST");
1361038fd1498Szrj debug_tree (TYPE_VFIELD (t));
1361138fd1498Szrj error_found = true;
1361238fd1498Szrj }
1361338fd1498Szrj }
1361438fd1498Szrj else if (TREE_CODE (t) == POINTER_TYPE)
1361538fd1498Szrj {
1361638fd1498Szrj if (TYPE_NEXT_PTR_TO (t)
1361738fd1498Szrj && TREE_CODE (TYPE_NEXT_PTR_TO (t)) != POINTER_TYPE)
1361838fd1498Szrj {
1361938fd1498Szrj error ("TYPE_NEXT_PTR_TO is not POINTER_TYPE");
1362038fd1498Szrj debug_tree (TYPE_NEXT_PTR_TO (t));
1362138fd1498Szrj error_found = true;
1362238fd1498Szrj }
1362338fd1498Szrj }
1362438fd1498Szrj else if (TREE_CODE (t) == REFERENCE_TYPE)
1362538fd1498Szrj {
1362638fd1498Szrj if (TYPE_NEXT_REF_TO (t)
1362738fd1498Szrj && TREE_CODE (TYPE_NEXT_REF_TO (t)) != REFERENCE_TYPE)
1362838fd1498Szrj {
1362938fd1498Szrj error ("TYPE_NEXT_REF_TO is not REFERENCE_TYPE");
1363038fd1498Szrj debug_tree (TYPE_NEXT_REF_TO (t));
1363138fd1498Szrj error_found = true;
1363238fd1498Szrj }
1363338fd1498Szrj }
1363438fd1498Szrj else if (INTEGRAL_TYPE_P (t) || TREE_CODE (t) == REAL_TYPE
1363538fd1498Szrj || TREE_CODE (t) == FIXED_POINT_TYPE)
1363638fd1498Szrj {
1363738fd1498Szrj /* FIXME: The following check should pass:
1363838fd1498Szrj useless_type_conversion_p (const_cast <tree> (t),
1363938fd1498Szrj TREE_TYPE (TYPE_MIN_VALUE (t))
1364038fd1498Szrj but does not for C sizetypes in LTO. */
1364138fd1498Szrj }
1364238fd1498Szrj
1364338fd1498Szrj /* Check various uses of TYPE_MAXVAL_RAW. */
1364438fd1498Szrj if (RECORD_OR_UNION_TYPE_P (t))
1364538fd1498Szrj {
1364638fd1498Szrj if (!TYPE_BINFO (t))
1364738fd1498Szrj ;
1364838fd1498Szrj else if (TREE_CODE (TYPE_BINFO (t)) != TREE_BINFO)
1364938fd1498Szrj {
1365038fd1498Szrj error ("TYPE_BINFO is not TREE_BINFO");
1365138fd1498Szrj debug_tree (TYPE_BINFO (t));
1365238fd1498Szrj error_found = true;
1365338fd1498Szrj }
1365438fd1498Szrj else if (TREE_TYPE (TYPE_BINFO (t)) != TYPE_MAIN_VARIANT (t))
1365538fd1498Szrj {
1365638fd1498Szrj error ("TYPE_BINFO type is not TYPE_MAIN_VARIANT");
1365738fd1498Szrj debug_tree (TREE_TYPE (TYPE_BINFO (t)));
1365838fd1498Szrj error_found = true;
1365938fd1498Szrj }
1366038fd1498Szrj }
1366138fd1498Szrj else if (TREE_CODE (t) == FUNCTION_TYPE || TREE_CODE (t) == METHOD_TYPE)
1366238fd1498Szrj {
1366338fd1498Szrj if (TYPE_METHOD_BASETYPE (t)
1366438fd1498Szrj && TREE_CODE (TYPE_METHOD_BASETYPE (t)) != RECORD_TYPE
1366538fd1498Szrj && TREE_CODE (TYPE_METHOD_BASETYPE (t)) != UNION_TYPE)
1366638fd1498Szrj {
1366738fd1498Szrj error ("TYPE_METHOD_BASETYPE is not record nor union");
1366838fd1498Szrj debug_tree (TYPE_METHOD_BASETYPE (t));
1366938fd1498Szrj error_found = true;
1367038fd1498Szrj }
1367138fd1498Szrj }
1367238fd1498Szrj else if (TREE_CODE (t) == OFFSET_TYPE)
1367338fd1498Szrj {
1367438fd1498Szrj if (TYPE_OFFSET_BASETYPE (t)
1367538fd1498Szrj && TREE_CODE (TYPE_OFFSET_BASETYPE (t)) != RECORD_TYPE
1367638fd1498Szrj && TREE_CODE (TYPE_OFFSET_BASETYPE (t)) != UNION_TYPE)
1367738fd1498Szrj {
1367838fd1498Szrj error ("TYPE_OFFSET_BASETYPE is not record nor union");
1367938fd1498Szrj debug_tree (TYPE_OFFSET_BASETYPE (t));
1368038fd1498Szrj error_found = true;
1368138fd1498Szrj }
1368238fd1498Szrj }
1368338fd1498Szrj else if (INTEGRAL_TYPE_P (t) || TREE_CODE (t) == REAL_TYPE
1368438fd1498Szrj || TREE_CODE (t) == FIXED_POINT_TYPE)
1368538fd1498Szrj {
1368638fd1498Szrj /* FIXME: The following check should pass:
1368738fd1498Szrj useless_type_conversion_p (const_cast <tree> (t),
1368838fd1498Szrj TREE_TYPE (TYPE_MAX_VALUE (t))
1368938fd1498Szrj but does not for C sizetypes in LTO. */
1369038fd1498Szrj }
1369138fd1498Szrj else if (TREE_CODE (t) == ARRAY_TYPE)
1369238fd1498Szrj {
1369338fd1498Szrj if (TYPE_ARRAY_MAX_SIZE (t)
1369438fd1498Szrj && TREE_CODE (TYPE_ARRAY_MAX_SIZE (t)) != INTEGER_CST)
1369538fd1498Szrj {
1369638fd1498Szrj error ("TYPE_ARRAY_MAX_SIZE not INTEGER_CST");
1369738fd1498Szrj debug_tree (TYPE_ARRAY_MAX_SIZE (t));
1369838fd1498Szrj error_found = true;
1369938fd1498Szrj }
1370038fd1498Szrj }
1370138fd1498Szrj else if (TYPE_MAX_VALUE_RAW (t))
1370238fd1498Szrj {
1370338fd1498Szrj error ("TYPE_MAX_VALUE_RAW non-NULL");
1370438fd1498Szrj debug_tree (TYPE_MAX_VALUE_RAW (t));
1370538fd1498Szrj error_found = true;
1370638fd1498Szrj }
1370738fd1498Szrj
1370838fd1498Szrj if (TYPE_LANG_SLOT_1 (t) && in_lto_p)
1370938fd1498Szrj {
1371038fd1498Szrj error ("TYPE_LANG_SLOT_1 (binfo) field is non-NULL");
1371138fd1498Szrj debug_tree (TYPE_LANG_SLOT_1 (t));
1371238fd1498Szrj error_found = true;
1371338fd1498Szrj }
1371438fd1498Szrj
1371538fd1498Szrj /* Check various uses of TYPE_VALUES_RAW. */
1371638fd1498Szrj if (TREE_CODE (t) == ENUMERAL_TYPE)
1371738fd1498Szrj for (tree l = TYPE_VALUES (t); l; l = TREE_CHAIN (l))
1371838fd1498Szrj {
1371938fd1498Szrj tree value = TREE_VALUE (l);
1372038fd1498Szrj tree name = TREE_PURPOSE (l);
1372138fd1498Szrj
1372238fd1498Szrj /* C FE porduce INTEGER_CST of INTEGER_TYPE, while C++ FE uses
1372338fd1498Szrj CONST_DECL of ENUMERAL TYPE. */
1372438fd1498Szrj if (TREE_CODE (value) != INTEGER_CST && TREE_CODE (value) != CONST_DECL)
1372538fd1498Szrj {
1372638fd1498Szrj error ("Enum value is not CONST_DECL or INTEGER_CST");
1372738fd1498Szrj debug_tree (value);
1372838fd1498Szrj debug_tree (name);
1372938fd1498Szrj error_found = true;
1373038fd1498Szrj }
1373138fd1498Szrj if (TREE_CODE (TREE_TYPE (value)) != INTEGER_TYPE
1373238fd1498Szrj && !useless_type_conversion_p (const_cast <tree> (t), TREE_TYPE (value)))
1373338fd1498Szrj {
1373438fd1498Szrj error ("Enum value type is not INTEGER_TYPE nor convertible to the enum");
1373538fd1498Szrj debug_tree (value);
1373638fd1498Szrj debug_tree (name);
1373738fd1498Szrj error_found = true;
1373838fd1498Szrj }
1373938fd1498Szrj if (TREE_CODE (name) != IDENTIFIER_NODE)
1374038fd1498Szrj {
1374138fd1498Szrj error ("Enum value name is not IDENTIFIER_NODE");
1374238fd1498Szrj debug_tree (value);
1374338fd1498Szrj debug_tree (name);
1374438fd1498Szrj error_found = true;
1374538fd1498Szrj }
1374638fd1498Szrj }
1374738fd1498Szrj else if (TREE_CODE (t) == ARRAY_TYPE)
1374838fd1498Szrj {
1374938fd1498Szrj if (TYPE_DOMAIN (t) && TREE_CODE (TYPE_DOMAIN (t)) != INTEGER_TYPE)
1375038fd1498Szrj {
1375138fd1498Szrj error ("Array TYPE_DOMAIN is not integer type");
1375238fd1498Szrj debug_tree (TYPE_DOMAIN (t));
1375338fd1498Szrj error_found = true;
1375438fd1498Szrj }
1375538fd1498Szrj }
1375638fd1498Szrj else if (RECORD_OR_UNION_TYPE_P (t))
1375738fd1498Szrj {
1375838fd1498Szrj if (TYPE_FIELDS (t) && !COMPLETE_TYPE_P (t) && in_lto_p)
1375938fd1498Szrj {
1376038fd1498Szrj error ("TYPE_FIELDS defined in incomplete type");
1376138fd1498Szrj error_found = true;
1376238fd1498Szrj }
1376338fd1498Szrj for (tree fld = TYPE_FIELDS (t); fld; fld = TREE_CHAIN (fld))
1376438fd1498Szrj {
1376538fd1498Szrj /* TODO: verify properties of decls. */
1376638fd1498Szrj if (TREE_CODE (fld) == FIELD_DECL)
1376738fd1498Szrj ;
1376838fd1498Szrj else if (TREE_CODE (fld) == TYPE_DECL)
1376938fd1498Szrj ;
1377038fd1498Szrj else if (TREE_CODE (fld) == CONST_DECL)
1377138fd1498Szrj ;
1377238fd1498Szrj else if (VAR_P (fld))
1377338fd1498Szrj ;
1377438fd1498Szrj else if (TREE_CODE (fld) == TEMPLATE_DECL)
1377538fd1498Szrj ;
1377638fd1498Szrj else if (TREE_CODE (fld) == USING_DECL)
1377738fd1498Szrj ;
1377838fd1498Szrj else if (TREE_CODE (fld) == FUNCTION_DECL)
1377938fd1498Szrj ;
1378038fd1498Szrj else
1378138fd1498Szrj {
1378238fd1498Szrj error ("Wrong tree in TYPE_FIELDS list");
1378338fd1498Szrj debug_tree (fld);
1378438fd1498Szrj error_found = true;
1378538fd1498Szrj }
1378638fd1498Szrj }
1378738fd1498Szrj }
1378838fd1498Szrj else if (TREE_CODE (t) == INTEGER_TYPE
1378938fd1498Szrj || TREE_CODE (t) == BOOLEAN_TYPE
1379038fd1498Szrj || TREE_CODE (t) == OFFSET_TYPE
1379138fd1498Szrj || TREE_CODE (t) == REFERENCE_TYPE
1379238fd1498Szrj || TREE_CODE (t) == NULLPTR_TYPE
1379338fd1498Szrj || TREE_CODE (t) == POINTER_TYPE)
1379438fd1498Szrj {
1379538fd1498Szrj if (TYPE_CACHED_VALUES_P (t) != (TYPE_CACHED_VALUES (t) != NULL))
1379638fd1498Szrj {
1379738fd1498Szrj error ("TYPE_CACHED_VALUES_P is %i while TYPE_CACHED_VALUES is %p",
1379838fd1498Szrj TYPE_CACHED_VALUES_P (t), (void *)TYPE_CACHED_VALUES (t));
1379938fd1498Szrj error_found = true;
1380038fd1498Szrj }
1380138fd1498Szrj else if (TYPE_CACHED_VALUES_P (t) && TREE_CODE (TYPE_CACHED_VALUES (t)) != TREE_VEC)
1380238fd1498Szrj {
1380338fd1498Szrj error ("TYPE_CACHED_VALUES is not TREE_VEC");
1380438fd1498Szrj debug_tree (TYPE_CACHED_VALUES (t));
1380538fd1498Szrj error_found = true;
1380638fd1498Szrj }
1380738fd1498Szrj /* Verify just enough of cache to ensure that no one copied it to new type.
1380838fd1498Szrj All copying should go by copy_node that should clear it. */
1380938fd1498Szrj else if (TYPE_CACHED_VALUES_P (t))
1381038fd1498Szrj {
1381138fd1498Szrj int i;
1381238fd1498Szrj for (i = 0; i < TREE_VEC_LENGTH (TYPE_CACHED_VALUES (t)); i++)
1381338fd1498Szrj if (TREE_VEC_ELT (TYPE_CACHED_VALUES (t), i)
1381438fd1498Szrj && TREE_TYPE (TREE_VEC_ELT (TYPE_CACHED_VALUES (t), i)) != t)
1381538fd1498Szrj {
1381638fd1498Szrj error ("wrong TYPE_CACHED_VALUES entry");
1381738fd1498Szrj debug_tree (TREE_VEC_ELT (TYPE_CACHED_VALUES (t), i));
1381838fd1498Szrj error_found = true;
1381938fd1498Szrj break;
1382038fd1498Szrj }
1382138fd1498Szrj }
1382238fd1498Szrj }
1382338fd1498Szrj else if (TREE_CODE (t) == FUNCTION_TYPE || TREE_CODE (t) == METHOD_TYPE)
1382438fd1498Szrj for (tree l = TYPE_ARG_TYPES (t); l; l = TREE_CHAIN (l))
1382538fd1498Szrj {
1382638fd1498Szrj /* C++ FE uses TREE_PURPOSE to store initial values. */
1382738fd1498Szrj if (TREE_PURPOSE (l) && in_lto_p)
1382838fd1498Szrj {
1382938fd1498Szrj error ("TREE_PURPOSE is non-NULL in TYPE_ARG_TYPES list");
1383038fd1498Szrj debug_tree (l);
1383138fd1498Szrj error_found = true;
1383238fd1498Szrj }
1383338fd1498Szrj if (!TYPE_P (TREE_VALUE (l)))
1383438fd1498Szrj {
1383538fd1498Szrj error ("Wrong entry in TYPE_ARG_TYPES list");
1383638fd1498Szrj debug_tree (l);
1383738fd1498Szrj error_found = true;
1383838fd1498Szrj }
1383938fd1498Szrj }
1384038fd1498Szrj else if (!is_lang_specific (t) && TYPE_VALUES_RAW (t))
1384138fd1498Szrj {
1384238fd1498Szrj error ("TYPE_VALUES_RAW field is non-NULL");
1384338fd1498Szrj debug_tree (TYPE_VALUES_RAW (t));
1384438fd1498Szrj error_found = true;
1384538fd1498Szrj }
1384638fd1498Szrj if (TREE_CODE (t) != INTEGER_TYPE
1384738fd1498Szrj && TREE_CODE (t) != BOOLEAN_TYPE
1384838fd1498Szrj && TREE_CODE (t) != OFFSET_TYPE
1384938fd1498Szrj && TREE_CODE (t) != REFERENCE_TYPE
1385038fd1498Szrj && TREE_CODE (t) != NULLPTR_TYPE
1385138fd1498Szrj && TREE_CODE (t) != POINTER_TYPE
1385238fd1498Szrj && TYPE_CACHED_VALUES_P (t))
1385338fd1498Szrj {
1385438fd1498Szrj error ("TYPE_CACHED_VALUES_P is set while it should not");
1385538fd1498Szrj error_found = true;
1385638fd1498Szrj }
1385738fd1498Szrj if (TYPE_STRING_FLAG (t)
1385838fd1498Szrj && TREE_CODE (t) != ARRAY_TYPE && TREE_CODE (t) != INTEGER_TYPE)
1385938fd1498Szrj {
1386038fd1498Szrj error ("TYPE_STRING_FLAG is set on wrong type code");
1386138fd1498Szrj error_found = true;
1386238fd1498Szrj }
1386338fd1498Szrj
1386438fd1498Szrj /* ipa-devirt makes an assumption that TYPE_METHOD_BASETYPE is always
1386538fd1498Szrj TYPE_MAIN_VARIANT and it would be odd to add methods only to variatns
1386638fd1498Szrj of a type. */
1386738fd1498Szrj if (TREE_CODE (t) == METHOD_TYPE
1386838fd1498Szrj && TYPE_MAIN_VARIANT (TYPE_METHOD_BASETYPE (t)) != TYPE_METHOD_BASETYPE (t))
1386938fd1498Szrj {
1387038fd1498Szrj error ("TYPE_METHOD_BASETYPE is not main variant");
1387138fd1498Szrj error_found = true;
1387238fd1498Szrj }
1387338fd1498Szrj
1387438fd1498Szrj if (error_found)
1387538fd1498Szrj {
1387638fd1498Szrj debug_tree (const_cast <tree> (t));
1387738fd1498Szrj internal_error ("verify_type failed");
1387838fd1498Szrj }
1387938fd1498Szrj }
1388038fd1498Szrj
1388138fd1498Szrj
1388238fd1498Szrj /* Return 1 if ARG interpreted as signed in its precision is known to be
1388338fd1498Szrj always positive or 2 if ARG is known to be always negative, or 3 if
1388438fd1498Szrj ARG may be positive or negative. */
1388538fd1498Szrj
1388638fd1498Szrj int
get_range_pos_neg(tree arg)1388738fd1498Szrj get_range_pos_neg (tree arg)
1388838fd1498Szrj {
1388938fd1498Szrj if (arg == error_mark_node)
1389038fd1498Szrj return 3;
1389138fd1498Szrj
1389238fd1498Szrj int prec = TYPE_PRECISION (TREE_TYPE (arg));
1389338fd1498Szrj int cnt = 0;
1389438fd1498Szrj if (TREE_CODE (arg) == INTEGER_CST)
1389538fd1498Szrj {
1389638fd1498Szrj wide_int w = wi::sext (wi::to_wide (arg), prec);
1389738fd1498Szrj if (wi::neg_p (w))
1389838fd1498Szrj return 2;
1389938fd1498Szrj else
1390038fd1498Szrj return 1;
1390138fd1498Szrj }
1390238fd1498Szrj while (CONVERT_EXPR_P (arg)
1390338fd1498Szrj && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
1390438fd1498Szrj && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
1390538fd1498Szrj {
1390638fd1498Szrj arg = TREE_OPERAND (arg, 0);
1390738fd1498Szrj /* Narrower value zero extended into wider type
1390838fd1498Szrj will always result in positive values. */
1390938fd1498Szrj if (TYPE_UNSIGNED (TREE_TYPE (arg))
1391038fd1498Szrj && TYPE_PRECISION (TREE_TYPE (arg)) < prec)
1391138fd1498Szrj return 1;
1391238fd1498Szrj prec = TYPE_PRECISION (TREE_TYPE (arg));
1391338fd1498Szrj if (++cnt > 30)
1391438fd1498Szrj return 3;
1391538fd1498Szrj }
1391638fd1498Szrj
1391738fd1498Szrj if (TREE_CODE (arg) != SSA_NAME)
1391838fd1498Szrj return 3;
1391938fd1498Szrj wide_int arg_min, arg_max;
1392038fd1498Szrj while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
1392138fd1498Szrj {
1392238fd1498Szrj gimple *g = SSA_NAME_DEF_STMT (arg);
1392338fd1498Szrj if (is_gimple_assign (g)
1392438fd1498Szrj && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
1392538fd1498Szrj {
1392638fd1498Szrj tree t = gimple_assign_rhs1 (g);
1392738fd1498Szrj if (INTEGRAL_TYPE_P (TREE_TYPE (t))
1392838fd1498Szrj && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
1392938fd1498Szrj {
1393038fd1498Szrj if (TYPE_UNSIGNED (TREE_TYPE (t))
1393138fd1498Szrj && TYPE_PRECISION (TREE_TYPE (t)) < prec)
1393238fd1498Szrj return 1;
1393338fd1498Szrj prec = TYPE_PRECISION (TREE_TYPE (t));
1393438fd1498Szrj arg = t;
1393538fd1498Szrj if (++cnt > 30)
1393638fd1498Szrj return 3;
1393738fd1498Szrj continue;
1393838fd1498Szrj }
1393938fd1498Szrj }
1394038fd1498Szrj return 3;
1394138fd1498Szrj }
1394238fd1498Szrj if (TYPE_UNSIGNED (TREE_TYPE (arg)))
1394338fd1498Szrj {
1394438fd1498Szrj /* For unsigned values, the "positive" range comes
1394538fd1498Szrj below the "negative" range. */
1394638fd1498Szrj if (!wi::neg_p (wi::sext (arg_max, prec), SIGNED))
1394738fd1498Szrj return 1;
1394838fd1498Szrj if (wi::neg_p (wi::sext (arg_min, prec), SIGNED))
1394938fd1498Szrj return 2;
1395038fd1498Szrj }
1395138fd1498Szrj else
1395238fd1498Szrj {
1395338fd1498Szrj if (!wi::neg_p (wi::sext (arg_min, prec), SIGNED))
1395438fd1498Szrj return 1;
1395538fd1498Szrj if (wi::neg_p (wi::sext (arg_max, prec), SIGNED))
1395638fd1498Szrj return 2;
1395738fd1498Szrj }
1395838fd1498Szrj return 3;
1395938fd1498Szrj }
1396038fd1498Szrj
1396138fd1498Szrj
1396238fd1498Szrj
1396338fd1498Szrj
1396438fd1498Szrj /* Return true if ARG is marked with the nonnull attribute in the
1396538fd1498Szrj current function signature. */
1396638fd1498Szrj
1396738fd1498Szrj bool
nonnull_arg_p(const_tree arg)1396838fd1498Szrj nonnull_arg_p (const_tree arg)
1396938fd1498Szrj {
1397038fd1498Szrj tree t, attrs, fntype;
1397138fd1498Szrj unsigned HOST_WIDE_INT arg_num;
1397238fd1498Szrj
1397338fd1498Szrj gcc_assert (TREE_CODE (arg) == PARM_DECL
1397438fd1498Szrj && (POINTER_TYPE_P (TREE_TYPE (arg))
1397538fd1498Szrj || TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE));
1397638fd1498Szrj
1397738fd1498Szrj /* The static chain decl is always non null. */
1397838fd1498Szrj if (arg == cfun->static_chain_decl)
1397938fd1498Szrj return true;
1398038fd1498Szrj
1398138fd1498Szrj /* THIS argument of method is always non-NULL. */
1398238fd1498Szrj if (TREE_CODE (TREE_TYPE (cfun->decl)) == METHOD_TYPE
1398338fd1498Szrj && arg == DECL_ARGUMENTS (cfun->decl)
1398438fd1498Szrj && flag_delete_null_pointer_checks)
1398538fd1498Szrj return true;
1398638fd1498Szrj
1398738fd1498Szrj /* Values passed by reference are always non-NULL. */
1398838fd1498Szrj if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE
1398938fd1498Szrj && flag_delete_null_pointer_checks)
1399038fd1498Szrj return true;
1399138fd1498Szrj
1399238fd1498Szrj fntype = TREE_TYPE (cfun->decl);
1399338fd1498Szrj for (attrs = TYPE_ATTRIBUTES (fntype); attrs; attrs = TREE_CHAIN (attrs))
1399438fd1498Szrj {
1399538fd1498Szrj attrs = lookup_attribute ("nonnull", attrs);
1399638fd1498Szrj
1399738fd1498Szrj /* If "nonnull" wasn't specified, we know nothing about the argument. */
1399838fd1498Szrj if (attrs == NULL_TREE)
1399938fd1498Szrj return false;
1400038fd1498Szrj
1400138fd1498Szrj /* If "nonnull" applies to all the arguments, then ARG is non-null. */
1400238fd1498Szrj if (TREE_VALUE (attrs) == NULL_TREE)
1400338fd1498Szrj return true;
1400438fd1498Szrj
1400538fd1498Szrj /* Get the position number for ARG in the function signature. */
1400638fd1498Szrj for (arg_num = 1, t = DECL_ARGUMENTS (cfun->decl);
1400738fd1498Szrj t;
1400838fd1498Szrj t = DECL_CHAIN (t), arg_num++)
1400938fd1498Szrj {
1401038fd1498Szrj if (t == arg)
1401138fd1498Szrj break;
1401238fd1498Szrj }
1401338fd1498Szrj
1401438fd1498Szrj gcc_assert (t == arg);
1401538fd1498Szrj
1401638fd1498Szrj /* Now see if ARG_NUM is mentioned in the nonnull list. */
1401738fd1498Szrj for (t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
1401838fd1498Szrj {
1401938fd1498Szrj if (compare_tree_int (TREE_VALUE (t), arg_num) == 0)
1402038fd1498Szrj return true;
1402138fd1498Szrj }
1402238fd1498Szrj }
1402338fd1498Szrj
1402438fd1498Szrj return false;
1402538fd1498Szrj }
1402638fd1498Szrj
1402738fd1498Szrj /* Combine LOC and BLOCK to a combined adhoc loc, retaining any range
1402838fd1498Szrj information. */
1402938fd1498Szrj
1403038fd1498Szrj location_t
set_block(location_t loc,tree block)1403138fd1498Szrj set_block (location_t loc, tree block)
1403238fd1498Szrj {
1403338fd1498Szrj location_t pure_loc = get_pure_location (loc);
1403438fd1498Szrj source_range src_range = get_range_from_loc (line_table, loc);
1403538fd1498Szrj return COMBINE_LOCATION_DATA (line_table, pure_loc, src_range, block);
1403638fd1498Szrj }
1403738fd1498Szrj
1403838fd1498Szrj location_t
set_source_range(tree expr,location_t start,location_t finish)1403938fd1498Szrj set_source_range (tree expr, location_t start, location_t finish)
1404038fd1498Szrj {
1404138fd1498Szrj source_range src_range;
1404238fd1498Szrj src_range.m_start = start;
1404338fd1498Szrj src_range.m_finish = finish;
1404438fd1498Szrj return set_source_range (expr, src_range);
1404538fd1498Szrj }
1404638fd1498Szrj
1404738fd1498Szrj location_t
set_source_range(tree expr,source_range src_range)1404838fd1498Szrj set_source_range (tree expr, source_range src_range)
1404938fd1498Szrj {
1405038fd1498Szrj if (!EXPR_P (expr))
1405138fd1498Szrj return UNKNOWN_LOCATION;
1405238fd1498Szrj
1405338fd1498Szrj location_t pure_loc = get_pure_location (EXPR_LOCATION (expr));
1405438fd1498Szrj location_t adhoc = COMBINE_LOCATION_DATA (line_table,
1405538fd1498Szrj pure_loc,
1405638fd1498Szrj src_range,
1405738fd1498Szrj NULL);
1405838fd1498Szrj SET_EXPR_LOCATION (expr, adhoc);
1405938fd1498Szrj return adhoc;
1406038fd1498Szrj }
1406138fd1498Szrj
1406238fd1498Szrj /* Return EXPR, potentially wrapped with a node expression LOC,
1406338fd1498Szrj if !CAN_HAVE_LOCATION_P (expr).
1406438fd1498Szrj
1406538fd1498Szrj NON_LVALUE_EXPR is used for wrapping constants, apart from STRING_CST.
1406638fd1498Szrj VIEW_CONVERT_EXPR is used for wrapping non-constants and STRING_CST.
1406738fd1498Szrj
1406838fd1498Szrj Wrapper nodes can be identified using location_wrapper_p. */
1406938fd1498Szrj
1407038fd1498Szrj tree
maybe_wrap_with_location(tree expr,location_t loc)1407138fd1498Szrj maybe_wrap_with_location (tree expr, location_t loc)
1407238fd1498Szrj {
1407338fd1498Szrj if (expr == NULL)
1407438fd1498Szrj return NULL;
1407538fd1498Szrj if (loc == UNKNOWN_LOCATION)
1407638fd1498Szrj return expr;
1407738fd1498Szrj if (CAN_HAVE_LOCATION_P (expr))
1407838fd1498Szrj return expr;
1407938fd1498Szrj /* We should only be adding wrappers for constants and for decls,
1408038fd1498Szrj or for some exceptional tree nodes (e.g. BASELINK in the C++ FE). */
1408138fd1498Szrj gcc_assert (CONSTANT_CLASS_P (expr)
1408238fd1498Szrj || DECL_P (expr)
1408338fd1498Szrj || EXCEPTIONAL_CLASS_P (expr));
1408438fd1498Szrj
1408538fd1498Szrj /* For now, don't add wrappers to exceptional tree nodes, to minimize
1408638fd1498Szrj any impact of the wrapper nodes. */
1408738fd1498Szrj if (EXCEPTIONAL_CLASS_P (expr))
1408838fd1498Szrj return expr;
1408938fd1498Szrj
1409038fd1498Szrj tree_code code
1409138fd1498Szrj = (((CONSTANT_CLASS_P (expr) && TREE_CODE (expr) != STRING_CST)
1409238fd1498Szrj || (TREE_CODE (expr) == CONST_DECL && !TREE_STATIC (expr)))
1409338fd1498Szrj ? NON_LVALUE_EXPR : VIEW_CONVERT_EXPR);
1409438fd1498Szrj tree wrapper = build1_loc (loc, code, TREE_TYPE (expr), expr);
1409538fd1498Szrj /* Mark this node as being a wrapper. */
1409638fd1498Szrj EXPR_LOCATION_WRAPPER_P (wrapper) = 1;
1409738fd1498Szrj return wrapper;
1409838fd1498Szrj }
1409938fd1498Szrj
1410038fd1498Szrj /* Return the name of combined function FN, for debugging purposes. */
1410138fd1498Szrj
1410238fd1498Szrj const char *
combined_fn_name(combined_fn fn)1410338fd1498Szrj combined_fn_name (combined_fn fn)
1410438fd1498Szrj {
1410538fd1498Szrj if (builtin_fn_p (fn))
1410638fd1498Szrj {
1410738fd1498Szrj tree fndecl = builtin_decl_explicit (as_builtin_fn (fn));
1410838fd1498Szrj return IDENTIFIER_POINTER (DECL_NAME (fndecl));
1410938fd1498Szrj }
1411038fd1498Szrj else
1411138fd1498Szrj return internal_fn_name (as_internal_fn (fn));
1411238fd1498Szrj }
1411338fd1498Szrj
1411438fd1498Szrj /* Return a bitmap with a bit set corresponding to each argument in
1411538fd1498Szrj a function call type FNTYPE declared with attribute nonnull,
1411638fd1498Szrj or null if none of the function's argument are nonnull. The caller
1411738fd1498Szrj must free the bitmap. */
1411838fd1498Szrj
1411938fd1498Szrj bitmap
get_nonnull_args(const_tree fntype)1412038fd1498Szrj get_nonnull_args (const_tree fntype)
1412138fd1498Szrj {
1412238fd1498Szrj if (fntype == NULL_TREE)
1412338fd1498Szrj return NULL;
1412438fd1498Szrj
1412538fd1498Szrj tree attrs = TYPE_ATTRIBUTES (fntype);
1412638fd1498Szrj if (!attrs)
1412738fd1498Szrj return NULL;
1412838fd1498Szrj
1412938fd1498Szrj bitmap argmap = NULL;
1413038fd1498Szrj
1413138fd1498Szrj /* A function declaration can specify multiple attribute nonnull,
1413238fd1498Szrj each with zero or more arguments. The loop below creates a bitmap
1413338fd1498Szrj representing a union of all the arguments. An empty (but non-null)
1413438fd1498Szrj bitmap means that all arguments have been declaraed nonnull. */
1413538fd1498Szrj for ( ; attrs; attrs = TREE_CHAIN (attrs))
1413638fd1498Szrj {
1413738fd1498Szrj attrs = lookup_attribute ("nonnull", attrs);
1413838fd1498Szrj if (!attrs)
1413938fd1498Szrj break;
1414038fd1498Szrj
1414138fd1498Szrj if (!argmap)
1414238fd1498Szrj argmap = BITMAP_ALLOC (NULL);
1414338fd1498Szrj
1414438fd1498Szrj if (!TREE_VALUE (attrs))
1414538fd1498Szrj {
1414638fd1498Szrj /* Clear the bitmap in case a previous attribute nonnull
1414738fd1498Szrj set it and this one overrides it for all arguments. */
1414838fd1498Szrj bitmap_clear (argmap);
1414938fd1498Szrj return argmap;
1415038fd1498Szrj }
1415138fd1498Szrj
1415238fd1498Szrj /* Iterate over the indices of the format arguments declared nonnull
1415338fd1498Szrj and set a bit for each. */
1415438fd1498Szrj for (tree idx = TREE_VALUE (attrs); idx; idx = TREE_CHAIN (idx))
1415538fd1498Szrj {
1415638fd1498Szrj unsigned int val = TREE_INT_CST_LOW (TREE_VALUE (idx)) - 1;
1415738fd1498Szrj bitmap_set_bit (argmap, val);
1415838fd1498Szrj }
1415938fd1498Szrj }
1416038fd1498Szrj
1416138fd1498Szrj return argmap;
1416238fd1498Szrj }
1416338fd1498Szrj
1416438fd1498Szrj /* Returns true if TYPE is a type where it and all of its subobjects
1416538fd1498Szrj (recursively) are of structure, union, or array type. */
1416638fd1498Szrj
1416738fd1498Szrj static bool
default_is_empty_type(tree type)1416838fd1498Szrj default_is_empty_type (tree type)
1416938fd1498Szrj {
1417038fd1498Szrj if (RECORD_OR_UNION_TYPE_P (type))
1417138fd1498Szrj {
1417238fd1498Szrj for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
1417338fd1498Szrj if (TREE_CODE (field) == FIELD_DECL
1417438fd1498Szrj && !DECL_PADDING_P (field)
1417538fd1498Szrj && !default_is_empty_type (TREE_TYPE (field)))
1417638fd1498Szrj return false;
1417738fd1498Szrj return true;
1417838fd1498Szrj }
1417938fd1498Szrj else if (TREE_CODE (type) == ARRAY_TYPE)
1418038fd1498Szrj return (integer_minus_onep (array_type_nelts (type))
1418138fd1498Szrj || TYPE_DOMAIN (type) == NULL_TREE
1418238fd1498Szrj || default_is_empty_type (TREE_TYPE (type)));
1418338fd1498Szrj return false;
1418438fd1498Szrj }
1418538fd1498Szrj
1418638fd1498Szrj /* Implement TARGET_EMPTY_RECORD_P. Return true if TYPE is an empty type
1418738fd1498Szrj that shouldn't be passed via stack. */
1418838fd1498Szrj
1418938fd1498Szrj bool
default_is_empty_record(const_tree type)1419038fd1498Szrj default_is_empty_record (const_tree type)
1419138fd1498Szrj {
1419238fd1498Szrj if (!abi_version_at_least (12))
1419338fd1498Szrj return false;
1419438fd1498Szrj
1419538fd1498Szrj if (type == error_mark_node)
1419638fd1498Szrj return false;
1419738fd1498Szrj
1419838fd1498Szrj if (TREE_ADDRESSABLE (type))
1419938fd1498Szrj return false;
1420038fd1498Szrj
1420138fd1498Szrj return default_is_empty_type (TYPE_MAIN_VARIANT (type));
1420238fd1498Szrj }
1420338fd1498Szrj
1420438fd1498Szrj /* Like int_size_in_bytes, but handle empty records specially. */
1420538fd1498Szrj
1420638fd1498Szrj HOST_WIDE_INT
arg_int_size_in_bytes(const_tree type)1420738fd1498Szrj arg_int_size_in_bytes (const_tree type)
1420838fd1498Szrj {
1420938fd1498Szrj return TYPE_EMPTY_P (type) ? 0 : int_size_in_bytes (type);
1421038fd1498Szrj }
1421138fd1498Szrj
1421238fd1498Szrj /* Like size_in_bytes, but handle empty records specially. */
1421338fd1498Szrj
1421438fd1498Szrj tree
arg_size_in_bytes(const_tree type)1421538fd1498Szrj arg_size_in_bytes (const_tree type)
1421638fd1498Szrj {
1421738fd1498Szrj return TYPE_EMPTY_P (type) ? size_zero_node : size_in_bytes (type);
1421838fd1498Szrj }
1421938fd1498Szrj
1422038fd1498Szrj /* Return true if an expression with CODE has to have the same result type as
1422138fd1498Szrj its first operand. */
1422238fd1498Szrj
1422338fd1498Szrj bool
expr_type_first_operand_type_p(tree_code code)1422438fd1498Szrj expr_type_first_operand_type_p (tree_code code)
1422538fd1498Szrj {
1422638fd1498Szrj switch (code)
1422738fd1498Szrj {
1422838fd1498Szrj case NEGATE_EXPR:
1422938fd1498Szrj case ABS_EXPR:
1423038fd1498Szrj case BIT_NOT_EXPR:
1423138fd1498Szrj case PAREN_EXPR:
1423238fd1498Szrj case CONJ_EXPR:
1423338fd1498Szrj
1423438fd1498Szrj case PLUS_EXPR:
1423538fd1498Szrj case MINUS_EXPR:
1423638fd1498Szrj case MULT_EXPR:
1423738fd1498Szrj case TRUNC_DIV_EXPR:
1423838fd1498Szrj case CEIL_DIV_EXPR:
1423938fd1498Szrj case FLOOR_DIV_EXPR:
1424038fd1498Szrj case ROUND_DIV_EXPR:
1424138fd1498Szrj case TRUNC_MOD_EXPR:
1424238fd1498Szrj case CEIL_MOD_EXPR:
1424338fd1498Szrj case FLOOR_MOD_EXPR:
1424438fd1498Szrj case ROUND_MOD_EXPR:
1424538fd1498Szrj case RDIV_EXPR:
1424638fd1498Szrj case EXACT_DIV_EXPR:
1424738fd1498Szrj case MIN_EXPR:
1424838fd1498Szrj case MAX_EXPR:
1424938fd1498Szrj case BIT_IOR_EXPR:
1425038fd1498Szrj case BIT_XOR_EXPR:
1425138fd1498Szrj case BIT_AND_EXPR:
1425238fd1498Szrj
1425338fd1498Szrj case LSHIFT_EXPR:
1425438fd1498Szrj case RSHIFT_EXPR:
1425538fd1498Szrj case LROTATE_EXPR:
1425638fd1498Szrj case RROTATE_EXPR:
1425738fd1498Szrj return true;
1425838fd1498Szrj
1425938fd1498Szrj default:
1426038fd1498Szrj return false;
1426138fd1498Szrj }
1426238fd1498Szrj }
1426338fd1498Szrj
1426438fd1498Szrj /* List of pointer types used to declare builtins before we have seen their
1426538fd1498Szrj real declaration.
1426638fd1498Szrj
1426738fd1498Szrj Keep the size up to date in tree.h ! */
1426838fd1498Szrj const builtin_structptr_type builtin_structptr_types[6] =
1426938fd1498Szrj {
1427038fd1498Szrj { fileptr_type_node, ptr_type_node, "FILE" },
1427138fd1498Szrj { const_tm_ptr_type_node, const_ptr_type_node, "tm" },
1427238fd1498Szrj { fenv_t_ptr_type_node, ptr_type_node, "fenv_t" },
1427338fd1498Szrj { const_fenv_t_ptr_type_node, const_ptr_type_node, "fenv_t" },
1427438fd1498Szrj { fexcept_t_ptr_type_node, ptr_type_node, "fexcept_t" },
1427538fd1498Szrj { const_fexcept_t_ptr_type_node, const_ptr_type_node, "fexcept_t" }
1427638fd1498Szrj };
1427738fd1498Szrj
1427838fd1498Szrj #if CHECKING_P
1427938fd1498Szrj
1428038fd1498Szrj namespace selftest {
1428138fd1498Szrj
1428238fd1498Szrj /* Selftests for tree. */
1428338fd1498Szrj
1428438fd1498Szrj /* Verify that integer constants are sane. */
1428538fd1498Szrj
1428638fd1498Szrj static void
test_integer_constants()1428738fd1498Szrj test_integer_constants ()
1428838fd1498Szrj {
1428938fd1498Szrj ASSERT_TRUE (integer_type_node != NULL);
1429038fd1498Szrj ASSERT_TRUE (build_int_cst (integer_type_node, 0) != NULL);
1429138fd1498Szrj
1429238fd1498Szrj tree type = integer_type_node;
1429338fd1498Szrj
1429438fd1498Szrj tree zero = build_zero_cst (type);
1429538fd1498Szrj ASSERT_EQ (INTEGER_CST, TREE_CODE (zero));
1429638fd1498Szrj ASSERT_EQ (type, TREE_TYPE (zero));
1429738fd1498Szrj
1429838fd1498Szrj tree one = build_int_cst (type, 1);
1429938fd1498Szrj ASSERT_EQ (INTEGER_CST, TREE_CODE (one));
1430038fd1498Szrj ASSERT_EQ (type, TREE_TYPE (zero));
1430138fd1498Szrj }
1430238fd1498Szrj
1430338fd1498Szrj /* Verify identifiers. */
1430438fd1498Szrj
1430538fd1498Szrj static void
test_identifiers()1430638fd1498Szrj test_identifiers ()
1430738fd1498Szrj {
1430838fd1498Szrj tree identifier = get_identifier ("foo");
1430938fd1498Szrj ASSERT_EQ (3, IDENTIFIER_LENGTH (identifier));
1431038fd1498Szrj ASSERT_STREQ ("foo", IDENTIFIER_POINTER (identifier));
1431138fd1498Szrj }
1431238fd1498Szrj
1431338fd1498Szrj /* Verify LABEL_DECL. */
1431438fd1498Szrj
1431538fd1498Szrj static void
test_labels()1431638fd1498Szrj test_labels ()
1431738fd1498Szrj {
1431838fd1498Szrj tree identifier = get_identifier ("err");
1431938fd1498Szrj tree label_decl = build_decl (UNKNOWN_LOCATION, LABEL_DECL,
1432038fd1498Szrj identifier, void_type_node);
1432138fd1498Szrj ASSERT_EQ (-1, LABEL_DECL_UID (label_decl));
1432238fd1498Szrj ASSERT_FALSE (FORCED_LABEL (label_decl));
1432338fd1498Szrj }
1432438fd1498Szrj
1432538fd1498Szrj /* Return a new VECTOR_CST node whose type is TYPE and whose values
1432638fd1498Szrj are given by VALS. */
1432738fd1498Szrj
1432838fd1498Szrj static tree
build_vector(tree type,vec<tree> vals MEM_STAT_DECL)1432938fd1498Szrj build_vector (tree type, vec<tree> vals MEM_STAT_DECL)
1433038fd1498Szrj {
1433138fd1498Szrj gcc_assert (known_eq (vals.length (), TYPE_VECTOR_SUBPARTS (type)));
1433238fd1498Szrj tree_vector_builder builder (type, vals.length (), 1);
1433338fd1498Szrj builder.splice (vals);
1433438fd1498Szrj return builder.build ();
1433538fd1498Szrj }
1433638fd1498Szrj
1433738fd1498Szrj /* Check that VECTOR_CST ACTUAL contains the elements in EXPECTED. */
1433838fd1498Szrj
1433938fd1498Szrj static void
check_vector_cst(vec<tree> expected,tree actual)1434038fd1498Szrj check_vector_cst (vec<tree> expected, tree actual)
1434138fd1498Szrj {
1434238fd1498Szrj ASSERT_KNOWN_EQ (expected.length (),
1434338fd1498Szrj TYPE_VECTOR_SUBPARTS (TREE_TYPE (actual)));
1434438fd1498Szrj for (unsigned int i = 0; i < expected.length (); ++i)
1434538fd1498Szrj ASSERT_EQ (wi::to_wide (expected[i]),
1434638fd1498Szrj wi::to_wide (vector_cst_elt (actual, i)));
1434738fd1498Szrj }
1434838fd1498Szrj
1434938fd1498Szrj /* Check that VECTOR_CST ACTUAL contains NPATTERNS duplicated elements,
1435038fd1498Szrj and that its elements match EXPECTED. */
1435138fd1498Szrj
1435238fd1498Szrj static void
check_vector_cst_duplicate(vec<tree> expected,tree actual,unsigned int npatterns)1435338fd1498Szrj check_vector_cst_duplicate (vec<tree> expected, tree actual,
1435438fd1498Szrj unsigned int npatterns)
1435538fd1498Szrj {
1435638fd1498Szrj ASSERT_EQ (npatterns, VECTOR_CST_NPATTERNS (actual));
1435738fd1498Szrj ASSERT_EQ (1, VECTOR_CST_NELTS_PER_PATTERN (actual));
1435838fd1498Szrj ASSERT_EQ (npatterns, vector_cst_encoded_nelts (actual));
1435938fd1498Szrj ASSERT_TRUE (VECTOR_CST_DUPLICATE_P (actual));
1436038fd1498Szrj ASSERT_FALSE (VECTOR_CST_STEPPED_P (actual));
1436138fd1498Szrj check_vector_cst (expected, actual);
1436238fd1498Szrj }
1436338fd1498Szrj
1436438fd1498Szrj /* Check that VECTOR_CST ACTUAL contains NPATTERNS foreground elements
1436538fd1498Szrj and NPATTERNS background elements, and that its elements match
1436638fd1498Szrj EXPECTED. */
1436738fd1498Szrj
1436838fd1498Szrj static void
check_vector_cst_fill(vec<tree> expected,tree actual,unsigned int npatterns)1436938fd1498Szrj check_vector_cst_fill (vec<tree> expected, tree actual,
1437038fd1498Szrj unsigned int npatterns)
1437138fd1498Szrj {
1437238fd1498Szrj ASSERT_EQ (npatterns, VECTOR_CST_NPATTERNS (actual));
1437338fd1498Szrj ASSERT_EQ (2, VECTOR_CST_NELTS_PER_PATTERN (actual));
1437438fd1498Szrj ASSERT_EQ (2 * npatterns, vector_cst_encoded_nelts (actual));
1437538fd1498Szrj ASSERT_FALSE (VECTOR_CST_DUPLICATE_P (actual));
1437638fd1498Szrj ASSERT_FALSE (VECTOR_CST_STEPPED_P (actual));
1437738fd1498Szrj check_vector_cst (expected, actual);
1437838fd1498Szrj }
1437938fd1498Szrj
1438038fd1498Szrj /* Check that VECTOR_CST ACTUAL contains NPATTERNS stepped patterns,
1438138fd1498Szrj and that its elements match EXPECTED. */
1438238fd1498Szrj
1438338fd1498Szrj static void
check_vector_cst_stepped(vec<tree> expected,tree actual,unsigned int npatterns)1438438fd1498Szrj check_vector_cst_stepped (vec<tree> expected, tree actual,
1438538fd1498Szrj unsigned int npatterns)
1438638fd1498Szrj {
1438738fd1498Szrj ASSERT_EQ (npatterns, VECTOR_CST_NPATTERNS (actual));
1438838fd1498Szrj ASSERT_EQ (3, VECTOR_CST_NELTS_PER_PATTERN (actual));
1438938fd1498Szrj ASSERT_EQ (3 * npatterns, vector_cst_encoded_nelts (actual));
1439038fd1498Szrj ASSERT_FALSE (VECTOR_CST_DUPLICATE_P (actual));
1439138fd1498Szrj ASSERT_TRUE (VECTOR_CST_STEPPED_P (actual));
1439238fd1498Szrj check_vector_cst (expected, actual);
1439338fd1498Szrj }
1439438fd1498Szrj
1439538fd1498Szrj /* Test the creation of VECTOR_CSTs. */
1439638fd1498Szrj
1439738fd1498Szrj static void
test_vector_cst_patterns(ALONE_CXX_MEM_STAT_INFO)1439838fd1498Szrj test_vector_cst_patterns (ALONE_CXX_MEM_STAT_INFO)
1439938fd1498Szrj {
1440038fd1498Szrj auto_vec<tree, 8> elements (8);
1440138fd1498Szrj elements.quick_grow (8);
1440238fd1498Szrj tree element_type = build_nonstandard_integer_type (16, true);
1440338fd1498Szrj tree vector_type = build_vector_type (element_type, 8);
1440438fd1498Szrj
1440538fd1498Szrj /* Test a simple linear series with a base of 0 and a step of 1:
1440638fd1498Szrj { 0, 1, 2, 3, 4, 5, 6, 7 }. */
1440738fd1498Szrj for (unsigned int i = 0; i < 8; ++i)
1440838fd1498Szrj elements[i] = build_int_cst (element_type, i);
1440938fd1498Szrj tree vector = build_vector (vector_type, elements PASS_MEM_STAT);
1441038fd1498Szrj check_vector_cst_stepped (elements, vector, 1);
1441138fd1498Szrj
1441238fd1498Szrj /* Try the same with the first element replaced by 100:
1441338fd1498Szrj { 100, 1, 2, 3, 4, 5, 6, 7 }. */
1441438fd1498Szrj elements[0] = build_int_cst (element_type, 100);
1441538fd1498Szrj vector = build_vector (vector_type, elements PASS_MEM_STAT);
1441638fd1498Szrj check_vector_cst_stepped (elements, vector, 1);
1441738fd1498Szrj
1441838fd1498Szrj /* Try a series that wraps around.
1441938fd1498Szrj { 100, 65531, 65532, 65533, 65534, 65535, 0, 1 }. */
1442038fd1498Szrj for (unsigned int i = 1; i < 8; ++i)
1442138fd1498Szrj elements[i] = build_int_cst (element_type, (65530 + i) & 0xffff);
1442238fd1498Szrj vector = build_vector (vector_type, elements PASS_MEM_STAT);
1442338fd1498Szrj check_vector_cst_stepped (elements, vector, 1);
1442438fd1498Szrj
1442538fd1498Szrj /* Try a downward series:
1442638fd1498Szrj { 100, 79, 78, 77, 76, 75, 75, 73 }. */
1442738fd1498Szrj for (unsigned int i = 1; i < 8; ++i)
1442838fd1498Szrj elements[i] = build_int_cst (element_type, 80 - i);
1442938fd1498Szrj vector = build_vector (vector_type, elements PASS_MEM_STAT);
1443038fd1498Szrj check_vector_cst_stepped (elements, vector, 1);
1443138fd1498Szrj
1443238fd1498Szrj /* Try two interleaved series with different bases and steps:
1443338fd1498Szrj { 100, 53, 66, 206, 62, 212, 58, 218 }. */
1443438fd1498Szrj elements[1] = build_int_cst (element_type, 53);
1443538fd1498Szrj for (unsigned int i = 2; i < 8; i += 2)
1443638fd1498Szrj {
1443738fd1498Szrj elements[i] = build_int_cst (element_type, 70 - i * 2);
1443838fd1498Szrj elements[i + 1] = build_int_cst (element_type, 200 + i * 3);
1443938fd1498Szrj }
1444038fd1498Szrj vector = build_vector (vector_type, elements PASS_MEM_STAT);
1444138fd1498Szrj check_vector_cst_stepped (elements, vector, 2);
1444238fd1498Szrj
1444338fd1498Szrj /* Try a duplicated value:
1444438fd1498Szrj { 100, 100, 100, 100, 100, 100, 100, 100 }. */
1444538fd1498Szrj for (unsigned int i = 1; i < 8; ++i)
1444638fd1498Szrj elements[i] = elements[0];
1444738fd1498Szrj vector = build_vector (vector_type, elements PASS_MEM_STAT);
1444838fd1498Szrj check_vector_cst_duplicate (elements, vector, 1);
1444938fd1498Szrj
1445038fd1498Szrj /* Try an interleaved duplicated value:
1445138fd1498Szrj { 100, 55, 100, 55, 100, 55, 100, 55 }. */
1445238fd1498Szrj elements[1] = build_int_cst (element_type, 55);
1445338fd1498Szrj for (unsigned int i = 2; i < 8; ++i)
1445438fd1498Szrj elements[i] = elements[i - 2];
1445538fd1498Szrj vector = build_vector (vector_type, elements PASS_MEM_STAT);
1445638fd1498Szrj check_vector_cst_duplicate (elements, vector, 2);
1445738fd1498Szrj
1445838fd1498Szrj /* Try a duplicated value with 2 exceptions
1445938fd1498Szrj { 41, 97, 100, 55, 100, 55, 100, 55 }. */
1446038fd1498Szrj elements[0] = build_int_cst (element_type, 41);
1446138fd1498Szrj elements[1] = build_int_cst (element_type, 97);
1446238fd1498Szrj vector = build_vector (vector_type, elements PASS_MEM_STAT);
1446338fd1498Szrj check_vector_cst_fill (elements, vector, 2);
1446438fd1498Szrj
1446538fd1498Szrj /* Try with and without a step
1446638fd1498Szrj { 41, 97, 100, 21, 100, 35, 100, 49 }. */
1446738fd1498Szrj for (unsigned int i = 3; i < 8; i += 2)
1446838fd1498Szrj elements[i] = build_int_cst (element_type, i * 7);
1446938fd1498Szrj vector = build_vector (vector_type, elements PASS_MEM_STAT);
1447038fd1498Szrj check_vector_cst_stepped (elements, vector, 2);
1447138fd1498Szrj
1447238fd1498Szrj /* Try a fully-general constant:
1447338fd1498Szrj { 41, 97, 100, 21, 100, 9990, 100, 49 }. */
1447438fd1498Szrj elements[5] = build_int_cst (element_type, 9990);
1447538fd1498Szrj vector = build_vector (vector_type, elements PASS_MEM_STAT);
1447638fd1498Szrj check_vector_cst_fill (elements, vector, 4);
1447738fd1498Szrj }
1447838fd1498Szrj
1447938fd1498Szrj /* Verify that STRIP_NOPS (NODE) is EXPECTED.
1448038fd1498Szrj Helper function for test_location_wrappers, to deal with STRIP_NOPS
1448138fd1498Szrj modifying its argument in-place. */
1448238fd1498Szrj
1448338fd1498Szrj static void
check_strip_nops(tree node,tree expected)1448438fd1498Szrj check_strip_nops (tree node, tree expected)
1448538fd1498Szrj {
1448638fd1498Szrj STRIP_NOPS (node);
1448738fd1498Szrj ASSERT_EQ (expected, node);
1448838fd1498Szrj }
1448938fd1498Szrj
1449038fd1498Szrj /* Verify location wrappers. */
1449138fd1498Szrj
1449238fd1498Szrj static void
test_location_wrappers()1449338fd1498Szrj test_location_wrappers ()
1449438fd1498Szrj {
1449538fd1498Szrj location_t loc = BUILTINS_LOCATION;
1449638fd1498Szrj
1449738fd1498Szrj ASSERT_EQ (NULL_TREE, maybe_wrap_with_location (NULL_TREE, loc));
1449838fd1498Szrj
1449938fd1498Szrj /* Wrapping a constant. */
1450038fd1498Szrj tree int_cst = build_int_cst (integer_type_node, 42);
1450138fd1498Szrj ASSERT_FALSE (CAN_HAVE_LOCATION_P (int_cst));
1450238fd1498Szrj ASSERT_FALSE (location_wrapper_p (int_cst));
1450338fd1498Szrj
1450438fd1498Szrj tree wrapped_int_cst = maybe_wrap_with_location (int_cst, loc);
1450538fd1498Szrj ASSERT_TRUE (location_wrapper_p (wrapped_int_cst));
1450638fd1498Szrj ASSERT_EQ (loc, EXPR_LOCATION (wrapped_int_cst));
1450738fd1498Szrj ASSERT_EQ (int_cst, tree_strip_any_location_wrapper (wrapped_int_cst));
1450838fd1498Szrj
1450938fd1498Szrj /* We shouldn't add wrapper nodes for UNKNOWN_LOCATION. */
1451038fd1498Szrj ASSERT_EQ (int_cst, maybe_wrap_with_location (int_cst, UNKNOWN_LOCATION));
1451138fd1498Szrj
1451238fd1498Szrj /* We shouldn't add wrapper nodes for nodes that CAN_HAVE_LOCATION_P. */
1451338fd1498Szrj tree cast = build1 (NOP_EXPR, char_type_node, int_cst);
1451438fd1498Szrj ASSERT_TRUE (CAN_HAVE_LOCATION_P (cast));
1451538fd1498Szrj ASSERT_EQ (cast, maybe_wrap_with_location (cast, loc));
1451638fd1498Szrj
1451738fd1498Szrj /* Wrapping a STRING_CST. */
1451838fd1498Szrj tree string_cst = build_string (4, "foo");
1451938fd1498Szrj ASSERT_FALSE (CAN_HAVE_LOCATION_P (string_cst));
1452038fd1498Szrj ASSERT_FALSE (location_wrapper_p (string_cst));
1452138fd1498Szrj
1452238fd1498Szrj tree wrapped_string_cst = maybe_wrap_with_location (string_cst, loc);
1452338fd1498Szrj ASSERT_TRUE (location_wrapper_p (wrapped_string_cst));
1452438fd1498Szrj ASSERT_EQ (VIEW_CONVERT_EXPR, TREE_CODE (wrapped_string_cst));
1452538fd1498Szrj ASSERT_EQ (loc, EXPR_LOCATION (wrapped_string_cst));
1452638fd1498Szrj ASSERT_EQ (string_cst, tree_strip_any_location_wrapper (wrapped_string_cst));
1452738fd1498Szrj
1452838fd1498Szrj
1452938fd1498Szrj /* Wrapping a variable. */
1453038fd1498Szrj tree int_var = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1453138fd1498Szrj get_identifier ("some_int_var"),
1453238fd1498Szrj integer_type_node);
1453338fd1498Szrj ASSERT_FALSE (CAN_HAVE_LOCATION_P (int_var));
1453438fd1498Szrj ASSERT_FALSE (location_wrapper_p (int_var));
1453538fd1498Szrj
1453638fd1498Szrj tree wrapped_int_var = maybe_wrap_with_location (int_var, loc);
1453738fd1498Szrj ASSERT_TRUE (location_wrapper_p (wrapped_int_var));
1453838fd1498Szrj ASSERT_EQ (loc, EXPR_LOCATION (wrapped_int_var));
1453938fd1498Szrj ASSERT_EQ (int_var, tree_strip_any_location_wrapper (wrapped_int_var));
1454038fd1498Szrj
1454138fd1498Szrj /* Verify that "reinterpret_cast<int>(some_int_var)" is not a location
1454238fd1498Szrj wrapper. */
1454338fd1498Szrj tree r_cast = build1 (NON_LVALUE_EXPR, integer_type_node, int_var);
1454438fd1498Szrj ASSERT_FALSE (location_wrapper_p (r_cast));
1454538fd1498Szrj ASSERT_EQ (r_cast, tree_strip_any_location_wrapper (r_cast));
1454638fd1498Szrj
1454738fd1498Szrj /* Verify that STRIP_NOPS removes wrappers. */
1454838fd1498Szrj check_strip_nops (wrapped_int_cst, int_cst);
1454938fd1498Szrj check_strip_nops (wrapped_string_cst, string_cst);
1455038fd1498Szrj check_strip_nops (wrapped_int_var, int_var);
1455138fd1498Szrj }
1455238fd1498Szrj
1455338fd1498Szrj /* Run all of the selftests within this file. */
1455438fd1498Szrj
1455538fd1498Szrj void
tree_c_tests()1455638fd1498Szrj tree_c_tests ()
1455738fd1498Szrj {
1455838fd1498Szrj test_integer_constants ();
1455938fd1498Szrj test_identifiers ();
1456038fd1498Szrj test_labels ();
1456138fd1498Szrj test_vector_cst_patterns ();
1456238fd1498Szrj test_location_wrappers ();
1456338fd1498Szrj }
1456438fd1498Szrj
1456538fd1498Szrj } // namespace selftest
1456638fd1498Szrj
1456738fd1498Szrj #endif /* CHECKING_P */
1456838fd1498Szrj
1456938fd1498Szrj #include "gt-tree.h"
14570