blob: 83ef506a9e95df0e91783d6dc8a105b189b4f395 [file] [log] [blame]
/* Language-independent node constructors for parse phase of GNU compiler.
Copyright (C) 1987-2018 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
/* This file contains the low level primitives for operating on tree nodes,
including allocation, list operations, interning of identifiers,
construction of data type nodes and statement nodes,
and construction of type conversion nodes. It also contains
tables index by tree code that describe how to take apart
nodes of that code.
It is intended to be language-independent but can occasionally
calls language-dependent routines. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "target.h"
#include "tree.h"
#include "gimple.h"
#include "tree-pass.h"
#include "ssa.h"
#include "cgraph.h"
#include "diagnostic.h"
#include "flags.h"
#include "alias.h"
#include "fold-const.h"
#include "stor-layout.h"
#include "calls.h"
#include "attribs.h"
#include "toplev.h" /* get_random_seed */
#include "output.h"
#include "common/common-target.h"
#include "langhooks.h"
#include "tree-inline.h"
#include "tree-iterator.h"
#include "internal-fn.h"
#include "gimple-iterator.h"
#include "gimplify.h"
#include "tree-dfa.h"
#include "params.h"
#include "langhooks-def.h"
#include "tree-diagnostic.h"
#include "except.h"
#include "builtins.h"
#include "print-tree.h"
#include "ipa-utils.h"
#include "selftest.h"
#include "stringpool.h"
#include "attribs.h"
#include "rtl.h"
#include "regs.h"
#include "tree-vector-builder.h"
/* Tree code classes. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
#define END_OF_BASE_TREE_CODES tcc_exceptional,
const enum tree_code_class tree_code_type[] = {
#include "all-tree.def"
};
#undef DEFTREECODE
#undef END_OF_BASE_TREE_CODES
/* Table indexed by tree code giving number of expression
operands beyond the fixed part of the node structure.
Not used for types or decls. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
#define END_OF_BASE_TREE_CODES 0,
const unsigned char tree_code_length[] = {
#include "all-tree.def"
};
#undef DEFTREECODE
#undef END_OF_BASE_TREE_CODES
/* Names of tree components.
Used for printing out the tree and error messages. */
#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
#define END_OF_BASE_TREE_CODES "@dummy",
static const char *const tree_code_name[] = {
#include "all-tree.def"
};
#undef DEFTREECODE
#undef END_OF_BASE_TREE_CODES
/* Each tree code class has an associated string representation.
These must correspond to the tree_code_class entries. */
const char *const tree_code_class_strings[] =
{
"exceptional",
"constant",
"type",
"declaration",
"reference",
"comparison",
"unary",
"binary",
"statement",
"vl_exp",
"expression"
};
/* obstack.[ch] explicitly declined to prototype this. */
extern int _obstack_allocated_p (struct obstack *h, void *obj);
/* Statistics-gathering stuff. */
static uint64_t tree_code_counts[MAX_TREE_CODES];
uint64_t tree_node_counts[(int) all_kinds];
uint64_t tree_node_sizes[(int) all_kinds];
/* Keep in sync with tree.h:enum tree_node_kind. */
static const char * const tree_node_kind_names[] = {
"decls",
"types",
"blocks",
"stmts",
"refs",
"exprs",
"constants",
"identifiers",
"vecs",
"binfos",
"ssa names",
"constructors",
"random kinds",
"lang_decl kinds",
"lang_type kinds",
"omp clauses",
};
/* Unique id for next decl created. */
static GTY(()) int next_decl_uid;
/* Unique id for next type created. */
static GTY(()) unsigned next_type_uid = 1;
/* Unique id for next debug decl created. Use negative numbers,
to catch erroneous uses. */
static GTY(()) int next_debug_decl_uid;
/* Since we cannot rehash a type after it is in the table, we have to
keep the hash code. */
struct GTY((for_user)) type_hash {
unsigned long hash;
tree type;
};
/* Initial size of the hash table (rounded to next prime). */
#define TYPE_HASH_INITIAL_SIZE 1000
struct type_cache_hasher : ggc_cache_ptr_hash<type_hash>
{
static hashval_t hash (type_hash *t) { return t->hash; }
static bool equal (type_hash *a, type_hash *b);
static int
keep_cache_entry (type_hash *&t)
{
return ggc_marked_p (t->type);
}
};
/* Now here is the hash table. When recording a type, it is added to
the slot whose index is the hash code. Note that the hash table is
used for several kinds of types (function types, array types and
array index range types, for now). While all these live in the
same table, they are completely independent, and the hash code is
computed differently for each of these. */
static GTY ((cache)) hash_table<type_cache_hasher> *type_hash_table;
/* Hash table and temporary node for larger integer const values. */
static GTY (()) tree int_cst_node;
struct int_cst_hasher : ggc_cache_ptr_hash<tree_node>
{
static hashval_t hash (tree t);
static bool equal (tree x, tree y);
};
static GTY ((cache)) hash_table<int_cst_hasher> *int_cst_hash_table;
/* Class and variable for making sure that there is a single POLY_INT_CST
for a given value. */
struct poly_int_cst_hasher : ggc_cache_ptr_hash<tree_node>
{
typedef std::pair<tree, const poly_wide_int *> compare_type;
static hashval_t hash (tree t);
static bool equal (tree x, const compare_type &y);
};
static GTY ((cache)) hash_table<poly_int_cst_hasher> *poly_int_cst_hash_table;
/* Hash table for optimization flags and target option flags. Use the same
hash table for both sets of options. Nodes for building the current
optimization and target option nodes. The assumption is most of the time
the options created will already be in the hash table, so we avoid
allocating and freeing up a node repeatably. */
static GTY (()) tree cl_optimization_node;
static GTY (()) tree cl_target_option_node;
struct cl_option_hasher : ggc_cache_ptr_hash<tree_node>
{
static hashval_t hash (tree t);
static bool equal (tree x, tree y);
};
static GTY ((cache)) hash_table<cl_option_hasher> *cl_option_hash_table;
/* General tree->tree mapping structure for use in hash tables. */
static GTY ((cache))
hash_table<tree_decl_map_cache_hasher> *debug_expr_for_decl;
static GTY ((cache))
hash_table<tree_decl_map_cache_hasher> *value_expr_for_decl;
struct tree_vec_map_cache_hasher : ggc_cache_ptr_hash<tree_vec_map>
{
static hashval_t hash (tree_vec_map *m) { return DECL_UID (m->base.from); }
static bool
equal (tree_vec_map *a, tree_vec_map *b)
{
return a->base.from == b->base.from;
}
static int
keep_cache_entry (tree_vec_map *&m)
{
return ggc_marked_p (m->base.from);
}
};
static GTY ((cache))
hash_table<tree_vec_map_cache_hasher> *debug_args_for_decl;
static void set_type_quals (tree, int);
static void print_type_hash_statistics (void);
static void print_debug_expr_statistics (void);
static void print_value_expr_statistics (void);
tree global_trees[TI_MAX];
tree integer_types[itk_none];
bool int_n_enabled_p[NUM_INT_N_ENTS];
struct int_n_trees_t int_n_trees [NUM_INT_N_ENTS];
bool tree_contains_struct[MAX_TREE_CODES][64];
/* Number of operands for each OpenMP clause. */
unsigned const char omp_clause_num_ops[] =
{
0, /* OMP_CLAUSE_ERROR */
1, /* OMP_CLAUSE_PRIVATE */
1, /* OMP_CLAUSE_SHARED */
1, /* OMP_CLAUSE_FIRSTPRIVATE */
2, /* OMP_CLAUSE_LASTPRIVATE */
5, /* OMP_CLAUSE_REDUCTION */
1, /* OMP_CLAUSE_COPYIN */
1, /* OMP_CLAUSE_COPYPRIVATE */
3, /* OMP_CLAUSE_LINEAR */
2, /* OMP_CLAUSE_ALIGNED */
1, /* OMP_CLAUSE_DEPEND */
1, /* OMP_CLAUSE_UNIFORM */
1, /* OMP_CLAUSE_TO_DECLARE */
1, /* OMP_CLAUSE_LINK */
2, /* OMP_CLAUSE_FROM */
2, /* OMP_CLAUSE_TO */
2, /* OMP_CLAUSE_MAP */
1, /* OMP_CLAUSE_USE_DEVICE_PTR */
1, /* OMP_CLAUSE_IS_DEVICE_PTR */
2, /* OMP_CLAUSE__CACHE_ */
2, /* OMP_CLAUSE_GANG */
1, /* OMP_CLAUSE_ASYNC */
1, /* OMP_CLAUSE_WAIT */
0, /* OMP_CLAUSE_AUTO */
0, /* OMP_CLAUSE_SEQ */
1, /* OMP_CLAUSE__LOOPTEMP_ */
1, /* OMP_CLAUSE_IF */
1, /* OMP_CLAUSE_NUM_THREADS */
1, /* OMP_CLAUSE_SCHEDULE */
0, /* OMP_CLAUSE_NOWAIT */
1, /* OMP_CLAUSE_ORDERED */
0, /* OMP_CLAUSE_DEFAULT */
3, /* OMP_CLAUSE_COLLAPSE */
0, /* OMP_CLAUSE_UNTIED */
1, /* OMP_CLAUSE_FINAL */
0, /* OMP_CLAUSE_MERGEABLE */
1, /* OMP_CLAUSE_DEVICE */
1, /* OMP_CLAUSE_DIST_SCHEDULE */
0, /* OMP_CLAUSE_INBRANCH */
0, /* OMP_CLAUSE_NOTINBRANCH */
1, /* OMP_CLAUSE_NUM_TEAMS */
1, /* OMP_CLAUSE_THREAD_LIMIT */
0, /* OMP_CLAUSE_PROC_BIND */
1, /* OMP_CLAUSE_SAFELEN */
1, /* OMP_CLAUSE_SIMDLEN */
0, /* OMP_CLAUSE_FOR */
0, /* OMP_CLAUSE_PARALLEL */
0, /* OMP_CLAUSE_SECTIONS */
0, /* OMP_CLAUSE_TASKGROUP */
1, /* OMP_CLAUSE_PRIORITY */
1, /* OMP_CLAUSE_GRAINSIZE */
1, /* OMP_CLAUSE_NUM_TASKS */
0, /* OMP_CLAUSE_NOGROUP */
0, /* OMP_CLAUSE_THREADS */
0, /* OMP_CLAUSE_SIMD */
1, /* OMP_CLAUSE_HINT */
0, /* OMP_CLAUSE_DEFALTMAP */
1, /* OMP_CLAUSE__SIMDUID_ */
0, /* OMP_CLAUSE__SIMT_ */
0, /* OMP_CLAUSE_INDEPENDENT */
1, /* OMP_CLAUSE_WORKER */
1, /* OMP_CLAUSE_VECTOR */
1, /* OMP_CLAUSE_NUM_GANGS */
1, /* OMP_CLAUSE_NUM_WORKERS */
1, /* OMP_CLAUSE_VECTOR_LENGTH */
3, /* OMP_CLAUSE_TILE */
2, /* OMP_CLAUSE__GRIDDIM_ */
};
const char * const omp_clause_code_name[] =
{
"error_clause",
"private",
"shared",
"firstprivate",
"lastprivate",
"reduction",
"copyin",
"copyprivate",
"linear",
"aligned",
"depend",
"uniform",
"to",
"link",
"from",
"to",
"map",
"use_device_ptr",
"is_device_ptr",
"_cache_",
"gang",
"async",
"wait",
"auto",
"seq",
"_looptemp_",
"if",
"num_threads",
"schedule",
"nowait",
"ordered",
"default",
"collapse",
"untied",
"final",
"mergeable",
"device",
"dist_schedule",
"inbranch",
"notinbranch",
"num_teams",
"thread_limit",
"proc_bind",
"safelen",
"simdlen",
"for",
"parallel",
"sections",
"taskgroup",
"priority",
"grainsize",
"num_tasks",
"nogroup",
"threads",
"simd",
"hint",
"defaultmap",
"_simduid_",
"_simt_",
"independent",
"worker",
"vector",
"num_gangs",
"num_workers",
"vector_length",
"tile",
"_griddim_"
};
/* Return the tree node structure used by tree code CODE. */
static inline enum tree_node_structure_enum
tree_node_structure_for_code (enum tree_code code)
{
switch (TREE_CODE_CLASS (code))
{
case tcc_declaration:
{
switch (code)
{
case FIELD_DECL:
return TS_FIELD_DECL;
case PARM_DECL:
return TS_PARM_DECL;
case VAR_DECL:
return TS_VAR_DECL;
case LABEL_DECL:
return TS_LABEL_DECL;
case RESULT_DECL:
return TS_RESULT_DECL;
case DEBUG_EXPR_DECL:
return TS_DECL_WRTL;
case CONST_DECL:
return TS_CONST_DECL;
case TYPE_DECL:
return TS_TYPE_DECL;
case FUNCTION_DECL:
return TS_FUNCTION_DECL;
case TRANSLATION_UNIT_DECL:
return TS_TRANSLATION_UNIT_DECL;
default:
return TS_DECL_NON_COMMON;
}
}
case tcc_type:
return TS_TYPE_NON_COMMON;
case tcc_reference:
case tcc_comparison:
case tcc_unary:
case tcc_binary:
case tcc_expression:
case tcc_statement:
case tcc_vl_exp:
return TS_EXP;
default: /* tcc_constant and tcc_exceptional */
break;
}
switch (code)
{
/* tcc_constant cases. */
case VOID_CST: return TS_TYPED;
case INTEGER_CST: return TS_INT_CST;
case POLY_INT_CST: return TS_POLY_INT_CST;
case REAL_CST: return TS_REAL_CST;
case FIXED_CST: return TS_FIXED_CST;
case COMPLEX_CST: return TS_COMPLEX;
case VECTOR_CST: return TS_VECTOR;
case STRING_CST: return TS_STRING;
/* tcc_exceptional cases. */
case ERROR_MARK: return TS_COMMON;
case IDENTIFIER_NODE: return TS_IDENTIFIER;
case TREE_LIST: return TS_LIST;
case TREE_VEC: return TS_VEC;
case SSA_NAME: return TS_SSA_NAME;
case PLACEHOLDER_EXPR: return TS_COMMON;
case STATEMENT_LIST: return TS_STATEMENT_LIST;
case BLOCK: return TS_BLOCK;
case CONSTRUCTOR: return TS_CONSTRUCTOR;
case TREE_BINFO: return TS_BINFO;
case OMP_CLAUSE: return TS_OMP_CLAUSE;
case OPTIMIZATION_NODE: return TS_OPTIMIZATION;
case TARGET_OPTION_NODE: return TS_TARGET_OPTION;
default:
gcc_unreachable ();
}
}
/* Initialize tree_contains_struct to describe the hierarchy of tree
nodes. */
static void
initialize_tree_contains_struct (void)
{
unsigned i;
for (i = ERROR_MARK; i < LAST_AND_UNUSED_TREE_CODE; i++)
{
enum tree_code code;
enum tree_node_structure_enum ts_code;
code = (enum tree_code) i;
ts_code = tree_node_structure_for_code (code);
/* Mark the TS structure itself. */
tree_contains_struct[code][ts_code] = 1;
/* Mark all the structures that TS is derived from. */
switch (ts_code)
{
case TS_TYPED:
case TS_BLOCK:
case TS_OPTIMIZATION:
case TS_TARGET_OPTION:
MARK_TS_BASE (code);
break;
case TS_COMMON:
case TS_INT_CST:
case TS_POLY_INT_CST:
case TS_REAL_CST:
case TS_FIXED_CST:
case TS_VECTOR:
case TS_STRING:
case TS_COMPLEX:
case TS_SSA_NAME:
case TS_CONSTRUCTOR:
case TS_EXP:
case TS_STATEMENT_LIST:
MARK_TS_TYPED (code);
break;
case TS_IDENTIFIER:
case TS_DECL_MINIMAL:
case TS_TYPE_COMMON:
case TS_LIST:
case TS_VEC:
case TS_BINFO:
case TS_OMP_CLAUSE:
MARK_TS_COMMON (code);
break;
case TS_TYPE_WITH_LANG_SPECIFIC:
MARK_TS_TYPE_COMMON (code);
break;
case TS_TYPE_NON_COMMON:
MARK_TS_TYPE_WITH_LANG_SPECIFIC (code);
break;
case TS_DECL_COMMON:
MARK_TS_DECL_MINIMAL (code);
break;
case TS_DECL_WRTL:
case TS_CONST_DECL:
MARK_TS_DECL_COMMON (code);
break;
case TS_DECL_NON_COMMON:
MARK_TS_DECL_WITH_VIS (code);
break;
case TS_DECL_WITH_VIS:
case TS_PARM_DECL:
case TS_LABEL_DECL:
case TS_RESULT_DECL:
MARK_TS_DECL_WRTL (code);
break;
case TS_FIELD_DECL:
MARK_TS_DECL_COMMON (code);
break;
case TS_VAR_DECL:
MARK_TS_DECL_WITH_VIS (code);
break;
case TS_TYPE_DECL:
case TS_FUNCTION_DECL:
MARK_TS_DECL_NON_COMMON (code);
break;
case TS_TRANSLATION_UNIT_DECL:
MARK_TS_DECL_COMMON (code);
break;
default:
gcc_unreachable ();
}
}
/* Basic consistency checks for attributes used in fold. */
gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON]);
gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON]);
gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_COMMON]);
gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_COMMON]);
gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_COMMON]);
gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_COMMON]);
gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_COMMON]);
gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_COMMON]);
gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_COMMON]);
gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_COMMON]);
gcc_assert (tree_contains_struct[FIELD_DECL][TS_DECL_COMMON]);
gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_WRTL]);
gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_WRTL]);
gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_WRTL]);
gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_WRTL]);
gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_WRTL]);
gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_MINIMAL]);
gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_MINIMAL]);
gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_MINIMAL]);
gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_MINIMAL]);
gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_MINIMAL]);
gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_MINIMAL]);
gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_MINIMAL]);
gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_MINIMAL]);
gcc_assert (tree_contains_struct[FIELD_DECL][TS_DECL_MINIMAL]);
gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS]);
gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS]);
gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_WITH_VIS]);
gcc_assert (tree_contains_struct[VAR_DECL][TS_VAR_DECL]);
gcc_assert (tree_contains_struct[FIELD_DECL][TS_FIELD_DECL]);
gcc_assert (tree_contains_struct[PARM_DECL][TS_PARM_DECL]);
gcc_assert (tree_contains_struct[LABEL_DECL][TS_LABEL_DECL]);
gcc_assert (tree_contains_struct[RESULT_DECL][TS_RESULT_DECL]);
gcc_assert (tree_contains_struct[CONST_DECL][TS_CONST_DECL]);
gcc_assert (tree_contains_struct[TYPE_DECL][TS_TYPE_DECL]);
gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL]);
gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL]);
gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON]);
gcc_assert (tree_contains_struct[NAMELIST_DECL][TS_DECL_MINIMAL]);
gcc_assert (tree_contains_struct[NAMELIST_DECL][TS_DECL_COMMON]);
}
/* Init tree.c. */
void
init_ttree (void)
{
/* Initialize the hash table of types. */
type_hash_table
= hash_table<type_cache_hasher>::create_ggc (TYPE_HASH_INITIAL_SIZE);
debug_expr_for_decl
= hash_table<tree_decl_map_cache_hasher>::create_ggc (512);
value_expr_for_decl
= hash_table<tree_decl_map_cache_hasher>::create_ggc (512);
int_cst_hash_table = hash_table<int_cst_hasher>::create_ggc (1024);
poly_int_cst_hash_table = hash_table<poly_int_cst_hasher>::create_ggc (64);
int_cst_node = make_int_cst (1, 1);
cl_option_hash_table = hash_table<cl_option_hasher>::create_ggc (64);
cl_optimization_node = make_node (OPTIMIZATION_NODE);
cl_target_option_node = make_node (TARGET_OPTION_NODE);
/* Initialize the tree_contains_struct array. */
initialize_tree_contains_struct ();
lang_hooks.init_ts ();
}
/* The name of the object as the assembler will see it (but before any
translations made by ASM_OUTPUT_LABELREF). Often this is the same
as DECL_NAME. It is an IDENTIFIER_NODE. */
tree
decl_assembler_name (tree decl)
{
if (!DECL_ASSEMBLER_NAME_SET_P (decl))
lang_hooks.set_decl_assembler_name (decl);
return DECL_ASSEMBLER_NAME_RAW (decl);
}
/* The DECL_ASSEMBLER_NAME_RAW of DECL is being explicitly set to NAME
(either of which may be NULL). Inform the FE, if this changes the
name. */
void
overwrite_decl_assembler_name (tree decl, tree name)
{
if (DECL_ASSEMBLER_NAME_RAW (decl) != name)
lang_hooks.overwrite_decl_assembler_name (decl, name);
}
/* When the target supports COMDAT groups, this indicates which group the
DECL is associated with. This can be either an IDENTIFIER_NODE or a
decl, in which case its DECL_ASSEMBLER_NAME identifies the group. */
tree
decl_comdat_group (const_tree node)
{
struct symtab_node *snode = symtab_node::get (node);
if (!snode)
return NULL;
return snode->get_comdat_group ();
}
/* Likewise, but make sure it's been reduced to an IDENTIFIER_NODE. */
tree
decl_comdat_group_id (const_tree node)
{
struct symtab_node *snode = symtab_node::get (node);
if (!snode)
return NULL;
return snode->get_comdat_group_id ();
}
/* When the target supports named section, return its name as IDENTIFIER_NODE
or NULL if it is in no section. */
const char *
decl_section_name (const_tree node)
{
struct symtab_node *snode = symtab_node::get (node);
if (!snode)
return NULL;
return snode->get_section ();
}
/* Set section name of NODE to VALUE (that is expected to be
identifier node) */
void
set_decl_section_name (tree node, const char *value)
{
struct symtab_node *snode;
if (value == NULL)
{
snode = symtab_node::get (node);
if (!snode)
return;
}
else if (VAR_P (node))
snode = varpool_node::get_create (node);
else
snode = cgraph_node::get_create (node);
snode->set_section (value);
}
/* Return TLS model of a variable NODE. */
enum tls_model
decl_tls_model (const_tree node)
{
struct varpool_node *snode = varpool_node::get (node);
if (!snode)
return TLS_MODEL_NONE;
return snode->tls_model;
}
/* Set TLS model of variable NODE to MODEL. */
void
set_decl_tls_model (tree node, enum tls_model model)
{
struct varpool_node *vnode;
if (model == TLS_MODEL_NONE)
{
vnode = varpool_node::get (node);
if (!vnode)
return;
}
else
vnode = varpool_node::get_create (node);
vnode->tls_model = model;
}
/* Compute the number of bytes occupied by a tree with code CODE.
This function cannot be used for nodes that have variable sizes,
including TREE_VEC, INTEGER_CST, STRING_CST, and CALL_EXPR. */
size_t
tree_code_size (enum tree_code code)
{
switch (TREE_CODE_CLASS (code))
{
case tcc_declaration: /* A decl node */
switch (code)
{
case FIELD_DECL: return sizeof (tree_field_decl);
case PARM_DECL: return sizeof (tree_parm_decl);
case VAR_DECL: return sizeof (tree_var_decl);
case LABEL_DECL: return sizeof (tree_label_decl);
case RESULT_DECL: return sizeof (tree_result_decl);
case CONST_DECL: return sizeof (tree_const_decl);
case TYPE_DECL: return sizeof (tree_type_decl);
case FUNCTION_DECL: return sizeof (tree_function_decl);
case DEBUG_EXPR_DECL: return sizeof (tree_decl_with_rtl);
case TRANSLATION_UNIT_DECL: return sizeof (tree_translation_unit_decl);
case NAMESPACE_DECL:
case IMPORTED_DECL:
case NAMELIST_DECL: return sizeof (tree_decl_non_common);
default:
gcc_checking_assert (code >= NUM_TREE_CODES);
return lang_hooks.tree_size (code);
}
case tcc_type: /* a type node */
switch (code)
{
case OFFSET_TYPE:
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
case INTEGER_TYPE:
case REAL_TYPE:
case POINTER_TYPE:
case REFERENCE_TYPE:
case NULLPTR_TYPE:
case FIXED_POINT_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
case ARRAY_TYPE:
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
case VOID_TYPE:
case POINTER_BOUNDS_TYPE:
case FUNCTION_TYPE:
case METHOD_TYPE:
case LANG_TYPE: return sizeof (tree_type_non_common);
default:
gcc_checking_assert (code >= NUM_TREE_CODES);
return lang_hooks.tree_size (code);
}
case tcc_reference: /* a reference */
case tcc_expression: /* an expression */
case tcc_statement: /* an expression with side effects */
case tcc_comparison: /* a comparison expression */
case tcc_unary: /* a unary arithmetic expression */
case tcc_binary: /* a binary arithmetic expression */
return (sizeof (struct tree_exp)
+ (TREE_CODE_LENGTH (code) - 1) * sizeof (tree));
case tcc_constant: /* a constant */
switch (code)
{
case VOID_CST: return sizeof (tree_typed);
case INTEGER_CST: gcc_unreachable ();
case POLY_INT_CST: return sizeof (tree_poly_int_cst);
case REAL_CST: return sizeof (tree_real_cst);
case FIXED_CST: return sizeof (tree_fixed_cst);
case COMPLEX_CST: return sizeof (tree_complex);
case VECTOR_CST: gcc_unreachable ();
case STRING_CST: gcc_unreachable ();
default:
gcc_checking_assert (code >= NUM_TREE_CODES);
return lang_hooks.tree_size (code);
}
case tcc_exceptional: /* something random, like an identifier. */
switch (code)
{
case IDENTIFIER_NODE: return lang_hooks.identifier_size;
case TREE_LIST: return sizeof (tree_list);
case ERROR_MARK:
case PLACEHOLDER_EXPR: return sizeof (tree_common);
case TREE_VEC: gcc_unreachable ();
case OMP_CLAUSE: gcc_unreachable ();
case SSA_NAME: return sizeof (tree_ssa_name);
case STATEMENT_LIST: return sizeof (tree_statement_list);
case BLOCK: return sizeof (struct tree_block);
case CONSTRUCTOR: return sizeof (tree_constructor);
case OPTIMIZATION_NODE: return sizeof (tree_optimization_option);
case TARGET_OPTION_NODE: return sizeof (tree_target_option);
default:
gcc_checking_assert (code >= NUM_TREE_CODES);
return lang_hooks.tree_size (code);
}
default:
gcc_unreachable ();
}
}
/* Compute the number of bytes occupied by NODE. This routine only
looks at TREE_CODE, except for those nodes that have variable sizes. */
size_t
tree_size (const_tree node)
{
const enum tree_code code = TREE_CODE (node);
switch (code)
{
case INTEGER_CST:
return (sizeof (struct tree_int_cst)
+ (TREE_INT_CST_EXT_NUNITS (node) - 1) * sizeof (HOST_WIDE_INT));
case TREE_BINFO:
return (offsetof (struct tree_binfo, base_binfos)
+ vec<tree, va_gc>
::embedded_size (BINFO_N_BASE_BINFOS (node)));
case TREE_VEC:
return (sizeof (struct tree_vec)
+ (TREE_VEC_LENGTH (node) - 1) * sizeof (tree));
case VECTOR_CST:
return (sizeof (struct tree_vector)
+ (vector_cst_encoded_nelts (node) - 1) * sizeof (tree));
case STRING_CST:
return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1;
case OMP_CLAUSE:
return (sizeof (struct tree_omp_clause)
+ (omp_clause_num_ops[OMP_CLAUSE_CODE (node)] - 1)
* sizeof (tree));
default:
if (TREE_CODE_CLASS (code) == tcc_vl_exp)
return (sizeof (struct tree_exp)
+ (VL_EXP_OPERAND_LENGTH (node) - 1) * sizeof (tree));
else
return tree_code_size (code);
}
}
/* Return tree node kind based on tree CODE. */
static tree_node_kind
get_stats_node_kind (enum tree_code code)
{
enum tree_code_class type = TREE_CODE_CLASS (code);
switch (type)
{
case tcc_declaration: /* A decl node */
return d_kind;
case tcc_type: /* a type node */
return t_kind;
case tcc_statement: /* an expression with side effects */
return s_kind;
case tcc_reference: /* a reference */
return r_kind;
case tcc_expression: /* an expression */
case tcc_comparison: /* a comparison expression */
case tcc_unary: /* a unary arithmetic expression */
case tcc_binary: /* a binary arithmetic expression */
return e_kind;
case tcc_constant: /* a constant */
return c_kind;
case tcc_exceptional: /* something random, like an identifier. */
switch (code)
{
case IDENTIFIER_NODE:
return id_kind;
case TREE_VEC:
return vec_kind;
case TREE_BINFO:
return binfo_kind;
case SSA_NAME:
return ssa_name_kind;
case BLOCK:
return b_kind;
case CONSTRUCTOR:
return constr_kind;
case OMP_CLAUSE:
return omp_clause_kind;
default:
return x_kind;
}
break;
case tcc_vl_exp:
return e_kind;
default:
gcc_unreachable ();
}
}
/* Record interesting allocation statistics for a tree node with CODE
and LENGTH. */
static void
record_node_allocation_statistics (enum tree_code code, size_t length)
{
if (!GATHER_STATISTICS)
return;
tree_node_kind kind = get_stats_node_kind (code);
tree_code_counts[(int) code]++;
tree_node_counts[(int) kind]++;
tree_node_sizes[(int) kind] += length;
}
/* Allocate and return a new UID from the DECL_UID namespace. */
int
allocate_decl_uid (void)
{
return next_decl_uid++;
}
/* Return a newly allocated node of code CODE. For decl and type
nodes, some other fields are initialized. The rest of the node is
initialized to zero. This function cannot be used for TREE_VEC,
INTEGER_CST or OMP_CLAUSE nodes, which is enforced by asserts in
tree_code_size.
Achoo! I got a code in the node. */
tree
make_node (enum tree_code code MEM_STAT_DECL)
{
tree t;
enum tree_code_class type = TREE_CODE_CLASS (code);
size_t length = tree_code_size (code);
record_node_allocation_statistics (code, length);
t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT);
TREE_SET_CODE (t, code);
switch (type)
{
case tcc_statement:
if (code != DEBUG_BEGIN_STMT)
TREE_SIDE_EFFECTS (t) = 1;
break;
case tcc_declaration:
if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
{
if (code == FUNCTION_DECL)
{
SET_DECL_ALIGN (t, FUNCTION_ALIGNMENT (FUNCTION_BOUNDARY));
SET_DECL_MODE (t, FUNCTION_MODE);
}
else
SET_DECL_ALIGN (t, 1);
}
DECL_SOURCE_LOCATION (t) = input_location;
if (TREE_CODE (t) == DEBUG_EXPR_DECL)
DECL_UID (t) = --next_debug_decl_uid;
else
{
DECL_UID (t) = allocate_decl_uid ();
SET_DECL_PT_UID (t, -1);
}
if (TREE_CODE (t) == LABEL_DECL)
LABEL_DECL_UID (t) = -1;
break;
case tcc_type:
TYPE_UID (t) = next_type_uid++;
SET_TYPE_ALIGN (t, BITS_PER_UNIT);
TYPE_USER_ALIGN (t) = 0;
TYPE_MAIN_VARIANT (t) = t;
TYPE_CANONICAL (t) = t;
/* Default to no attributes for type, but let target change that. */
TYPE_ATTRIBUTES (t) = NULL_TREE;
targetm.set_default_type_attributes (t);
/* We have not yet computed the alias set for this type. */
TYPE_ALIAS_SET (t) = -1;
break;
case tcc_constant:
TREE_CONSTANT (t) = 1;
break;
case tcc_expression:
switch (code)
{
case INIT_EXPR:
case MODIFY_EXPR:
case VA_ARG_EXPR:
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
/* All of these have side-effects, no matter what their
operands are. */
TREE_SIDE_EFFECTS (t) = 1;
break;
default:
break;
}
break;
case tcc_exceptional:
switch (code)
{
case TARGET_OPTION_NODE:
TREE_TARGET_OPTION(t)
= ggc_cleared_alloc<struct cl_target_option> ();
break;
case OPTIMIZATION_NODE:
TREE_OPTIMIZATION (t)
= ggc_cleared_alloc<struct cl_optimization> ();
break;
default:
break;
}
break;
default:
/* Other classes need no special treatment. */
break;
}
return t;
}
/* Free tree node. */
void
free_node (tree node)
{
enum tree_code code = TREE_CODE (node);
if (GATHER_STATISTICS)
{
enum tree_node_kind kind = get_stats_node_kind (code);
gcc_checking_assert (tree_code_counts[(int) TREE_CODE (node)] != 0);
gcc_checking_assert (tree_node_counts[(int) kind] != 0);
gcc_checking_assert (tree_node_sizes[(int) kind] >= tree_size (node));
tree_code_counts[(int) TREE_CODE (node)]--;
tree_node_counts[(int) kind]--;
tree_node_sizes[(int) kind] -= tree_size (node);
}
if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
vec_free (CONSTRUCTOR_ELTS (node));
else if (code == BLOCK)
vec_free (BLOCK_NONLOCALIZED_VARS (node));
else if (code == TREE_BINFO)
vec_free (BINFO_BASE_ACCESSES (node));
ggc_free (node);
}
/* Return a new node with the same contents as NODE except that its
TREE_CHAIN, if it has one, is zero and it has a fresh uid. */
tree
copy_node (tree node MEM_STAT_DECL)
{
tree t;
enum tree_code code = TREE_CODE (node);
size_t length;
gcc_assert (code != STATEMENT_LIST);
length = tree_size (node);
record_node_allocation_statistics (code, length);
t = ggc_alloc_tree_node_stat (length PASS_MEM_STAT);
memcpy (t, node, length);
if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
TREE_CHAIN (t) = 0;
TREE_ASM_WRITTEN (t) = 0;
TREE_VISITED (t) = 0;
if (TREE_CODE_CLASS (code) == tcc_declaration)
{
if (code == DEBUG_EXPR_DECL)
DECL_UID (t) = --next_debug_decl_uid;
else
{
DECL_UID (t) = allocate_decl_uid ();
if (DECL_PT_UID_SET_P (node))
SET_DECL_PT_UID (t, DECL_PT_UID (node));
}
if ((TREE_CODE (node) == PARM_DECL || VAR_P (node))
&& DECL_HAS_VALUE_EXPR_P (node))
{
SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (node));
DECL_HAS_VALUE_EXPR_P (t) = 1;
}
/* DECL_DEBUG_EXPR is copied explicitely by callers. */
if (VAR_P (node))
{
DECL_HAS_DEBUG_EXPR_P (t) = 0;
t->decl_with_vis.symtab_node = NULL;
}
if (VAR_P (node) && DECL_HAS_INIT_PRIORITY_P (node))
{
SET_DECL_INIT_PRIORITY (t, DECL_INIT_PRIORITY (node));
DECL_HAS_INIT_PRIORITY_P (t) = 1;
}
if (TREE_CODE (node) == FUNCTION_DECL)
{
DECL_STRUCT_FUNCTION (t) = NULL;
t->decl_with_vis.symtab_node = NULL;
}
}
else if (TREE_CODE_CLASS (code) == tcc_type)
{
TYPE_UID (t) = next_type_uid++;
/* The following is so that the debug code for
the copy is different from the original type.
The two statements usually duplicate each other
(because they clear fields of the same union),
but the optimizer should catch that. */
TYPE_SYMTAB_ADDRESS (t) = 0;
TYPE_SYMTAB_DIE (t) = 0;
/* Do not copy the values cache. */
if (TYPE_CACHED_VALUES_P (t))
{
TYPE_CACHED_VALUES_P (t) = 0;
TYPE_CACHED_VALUES (t) = NULL_TREE;
}
}
else if (code == TARGET_OPTION_NODE)
{
TREE_TARGET_OPTION (t) = ggc_alloc<struct cl_target_option>();
memcpy (TREE_TARGET_OPTION (t), TREE_TARGET_OPTION (node),
sizeof (struct cl_target_option));
}
else if (code == OPTIMIZATION_NODE)
{
TREE_OPTIMIZATION (t) = ggc_alloc<struct cl_optimization>();
memcpy (TREE_OPTIMIZATION (t), TREE_OPTIMIZATION (node),
sizeof (struct cl_optimization));
}
return t;
}
/* Return a copy of a chain of nodes, chained through the TREE_CHAIN field.
For example, this can copy a list made of TREE_LIST nodes. */
tree
copy_list (tree list)
{
tree head;
tree prev, next;
if (list == 0)
return 0;
head = prev = copy_node (list);
next = TREE_CHAIN (list);
while (next)
{
TREE_CHAIN (prev) = copy_node (next);
prev = TREE_CHAIN (prev);
next = TREE_CHAIN (next);
}
return head;
}
/* Return the value that TREE_INT_CST_EXT_NUNITS should have for an
INTEGER_CST with value CST and type TYPE. */
static unsigned int
get_int_cst_ext_nunits (tree type, const wide_int &cst)
{
gcc_checking_assert (cst.get_precision () == TYPE_PRECISION (type));
/* We need extra HWIs if CST is an unsigned integer with its
upper bit set. */
if (TYPE_UNSIGNED (type) && wi::neg_p (cst))
return cst.get_precision () / HOST_BITS_PER_WIDE_INT + 1;
return cst.get_len ();
}
/* Return a new INTEGER_CST with value CST and type TYPE. */
static tree
build_new_int_cst (tree type, const wide_int &cst)
{
unsigned int len = cst.get_len ();
unsigned int ext_len = get_int_cst_ext_nunits (type, cst);
tree nt = make_int_cst (len, ext_len);
if (len < ext_len)
{
--ext_len;
TREE_INT_CST_ELT (nt, ext_len)
= zext_hwi (-1, cst.get_precision () % HOST_BITS_PER_WIDE_INT);
for (unsigned int i = len; i < ext_len; ++i)
TREE_INT_CST_ELT (nt, i) = -1;
}
else if (TYPE_UNSIGNED (type)
&& cst.get_precision () < len * HOST_BITS_PER_WIDE_INT)
{
len--;
TREE_INT_CST_ELT (nt, len)
= zext_hwi (cst.elt (len),
cst.get_precision () % HOST_BITS_PER_WIDE_INT);
}
for (unsigned int i = 0; i < len; i++)
TREE_INT_CST_ELT (nt, i) = cst.elt (i);
TREE_TYPE (nt) = type;
return nt;
}
/* Return a new POLY_INT_CST with coefficients COEFFS and type TYPE. */
static tree
build_new_poly_int_cst (tree type, tree (&coeffs)[NUM_POLY_INT_COEFFS]
CXX_MEM_STAT_INFO)
{
size_t length = sizeof (struct tree_poly_int_cst);
record_node_allocation_statistics (POLY_INT_CST, length);
tree t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT);
TREE_SET_CODE (t, POLY_INT_CST);
TREE_CONSTANT (t) = 1;
TREE_TYPE (t) = type;
for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
POLY_INT_CST_COEFF (t, i) = coeffs[i];
return t;
}
/* Create a constant tree that contains CST sign-extended to TYPE. */
tree
build_int_cst (tree type, poly_int64 cst)
{
/* Support legacy code. */
if (!type)
type = integer_type_node;
return wide_int_to_tree (type, wi::shwi (cst, TYPE_PRECISION (type)));
}
/* Create a constant tree that contains CST zero-extended to TYPE. */
tree
build_int_cstu (tree type, poly_uint64 cst)
{
return wide_int_to_tree (type, wi::uhwi (cst, TYPE_PRECISION (type)));
}
/* Create a constant tree that contains CST sign-extended to TYPE. */
tree
build_int_cst_type (tree type, poly_int64 cst)
{
gcc_assert (type);
return wide_int_to_tree (type, wi::shwi (cst, TYPE_PRECISION (type)));
}
/* Constructs tree in type TYPE from with value given by CST. Signedness
of CST is assumed to be the same as the signedness of TYPE. */
tree
double_int_to_tree (tree type, double_int cst)
{
return wide_int_to_tree (type, widest_int::from (cst, TYPE_SIGN (type)));
}
/* We force the wide_int CST to the range of the type TYPE by sign or
zero extending it. OVERFLOWABLE indicates if we are interested in
overflow of the value, when >0 we are only interested in signed
overflow, for <0 we are interested in any overflow. OVERFLOWED
indicates whether overflow has already occurred. CONST_OVERFLOWED
indicates whether constant overflow has already occurred. We force
T's value to be within range of T's type (by setting to 0 or 1 all
the bits outside the type's range). We set TREE_OVERFLOWED if,
OVERFLOWED is nonzero,
or OVERFLOWABLE is >0 and signed overflow occurs
or OVERFLOWABLE is <0 and any overflow occurs
We return a new tree node for the extended wide_int. The node
is shared if no overflow flags are set. */
tree
force_fit_type (tree type, const poly_wide_int_ref &cst,
int overflowable, bool overflowed)
{
signop sign = TYPE_SIGN (type);
/* If we need to set overflow flags, return a new unshared node. */
if (overflowed || !wi::fits_to_tree_p (cst, type))
{
if (overflowed
|| overflowable < 0
|| (overflowable > 0 && sign == SIGNED))
{
poly_wide_int tmp = poly_wide_int::from (cst, TYPE_PRECISION (type),
sign);
tree t;
if (tmp.is_constant ())
t = build_new_int_cst (type, tmp.coeffs[0]);
else
{
tree coeffs[NUM_POLY_INT_COEFFS];
for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
{
coeffs[i] = build_new_int_cst (type, tmp.coeffs[i]);
TREE_OVERFLOW (coeffs[i]) = 1;
}
t = build_new_poly_int_cst (type, coeffs);
}
TREE_OVERFLOW (t) = 1;
return t;
}
}
/* Else build a shared node. */
return wide_int_to_tree (type, cst);
}
/* These are the hash table functions for the hash table of INTEGER_CST
nodes of a sizetype. */
/* Return the hash code X, an INTEGER_CST. */
hashval_t
int_cst_hasher::hash (tree x)
{
const_tree const t = x;
hashval_t code = TYPE_UID (TREE_TYPE (t));
int i;
for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
code = iterative_hash_host_wide_int (TREE_INT_CST_ELT(t, i), code);
return code;
}
/* Return nonzero if the value represented by *X (an INTEGER_CST tree node)
is the same as that given by *Y, which is the same. */
bool
int_cst_hasher::equal (tree x, tree y)
{
const_tree const xt = x;
const_tree const yt = y;
if (TREE_TYPE (xt) != TREE_TYPE (yt)
|| TREE_INT_CST_NUNITS (xt) != TREE_INT_CST_NUNITS (yt)
|| TREE_INT_CST_EXT_NUNITS (xt) != TREE_INT_CST_EXT_NUNITS (yt))
return false;
for (int i = 0; i < TREE_INT_CST_NUNITS (xt); i++)
if (TREE_INT_CST_ELT (xt, i) != TREE_INT_CST_ELT (yt, i))
return false;
return true;
}
/* Create an INT_CST node of TYPE and value CST.
The returned node is always shared. For small integers we use a
per-type vector cache, for larger ones we use a single hash table.
The value is extended from its precision according to the sign of
the type to be a multiple of HOST_BITS_PER_WIDE_INT. This defines
the upper bits and ensures that hashing and value equality based
upon the underlying HOST_WIDE_INTs works without masking. */
static tree
wide_int_to_tree_1 (tree type, const wide_int_ref &pcst)
{
tree t;
int ix = -1;
int limit = 0;
gcc_assert (type);
unsigned int prec = TYPE_PRECISION (type);
signop sgn = TYPE_SIGN (type);
/* Verify that everything is canonical. */
int l = pcst.get_len ();
if (l > 1)
{
if (pcst.elt (l - 1) == 0)
gcc_checking_assert (pcst.elt (l - 2) < 0);
if (pcst.elt (l - 1) == HOST_WIDE_INT_M1)
gcc_checking_assert (pcst.elt (l - 2) >= 0);
}
wide_int cst = wide_int::from (pcst, prec, sgn);
unsigned int ext_len = get_int_cst_ext_nunits (type, cst);
if (ext_len == 1)
{
/* We just need to store a single HOST_WIDE_INT. */
HOST_WIDE_INT hwi;
if (TYPE_UNSIGNED (type))
hwi = cst.to_uhwi ();
else
hwi = cst.to_shwi ();
switch (TREE_CODE (type))
{
case NULLPTR_TYPE:
gcc_assert (hwi == 0);
/* Fallthru. */
case POINTER_TYPE:
case REFERENCE_TYPE:
case POINTER_BOUNDS_TYPE:
/* Cache NULL pointer and zero bounds. */
if (hwi == 0)
{
limit = 1;
ix = 0;
}
break;
case BOOLEAN_TYPE:
/* Cache false or true. */
limit = 2;
if (IN_RANGE (hwi, 0, 1))
ix = hwi;
break;
case INTEGER_TYPE:
case OFFSET_TYPE:
if (TYPE_SIGN (type) == UNSIGNED)
{
/* Cache [0, N). */
limit = INTEGER_SHARE_LIMIT;
if (IN_RANGE (hwi, 0, INTEGER_SHARE_LIMIT - 1))
ix = hwi;
}
else
{
/* Cache [-1, N). */
limit = INTEGER_SHARE_LIMIT + 1;
if (IN_RANGE (hwi, -1, INTEGER_SHARE_LIMIT - 1))
ix = hwi + 1;
}
break;
case ENUMERAL_TYPE:
break;
default:
gcc_unreachable ();
}
if (ix >= 0)
{
/* Look for it in the type's vector of small shared ints. */
if (!TYPE_CACHED_VALUES_P (type))
{
TYPE_CACHED_VALUES_P (type) = 1;
TYPE_CACHED_VALUES (type) = make_tree_vec (limit);
}
t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix);
if (t)
/* Make sure no one is clobbering the shared constant. */
gcc_checking_assert (TREE_TYPE (t) == type
&& TREE_INT_CST_NUNITS (t) == 1
&& TREE_INT_CST_OFFSET_NUNITS (t) == 1
&& TREE_INT_CST_EXT_NUNITS (t) == 1
&& TREE_INT_CST_ELT (t, 0) == hwi);
else
{
/* Create a new shared int. */
t = build_new_int_cst (type, cst);
TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
}
}
else
{
/* Use the cache of larger shared ints, using int_cst_node as
a temporary. */
TREE_INT_CST_ELT (int_cst_node, 0) = hwi;
TREE_TYPE (int_cst_node) = type;
tree *slot = int_cst_hash_table->find_slot (int_cst_node, INSERT);
t = *slot;
if (!t)
{
/* Insert this one into the hash table. */
t = int_cst_node;
*slot = t;
/* Make a new node for next time round. */
int_cst_node = make_int_cst (1, 1);
}
}
}
else
{
/* The value either hashes properly or we drop it on the floor
for the gc to take care of. There will not be enough of them
to worry about. */
tree nt = build_new_int_cst (type, cst);
tree *slot = int_cst_hash_table->find_slot (nt, INSERT);
t = *slot;
if (!t)
{
/* Insert this one into the hash table. */
t = nt;
*slot = t;
}
else
ggc_free (nt);
}
return t;
}
hashval_t
poly_int_cst_hasher::hash (tree t)
{
inchash::hash hstate;
hstate.add_int (TYPE_UID (TREE_TYPE (t)));
for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
hstate.add_wide_int (wi::to_wide (POLY_INT_CST_COEFF (t, i)));
return hstate.end ();
}
bool
poly_int_cst_hasher::equal (tree x, const compare_type &y)
{
if (TREE_TYPE (x) != y.first)
return false;
for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
if (wi::to_wide (POLY_INT_CST_COEFF (x, i)) != y.second->coeffs[i])
return false;
return true;
}
/* Build a POLY_INT_CST node with type TYPE and with the elements in VALUES.
The elements must also have type TYPE. */
tree
build_poly_int_cst (tree type, const poly_wide_int_ref &values)
{
unsigned int prec = TYPE_PRECISION (type);
gcc_assert (prec <= values.coeffs[0].get_precision ());
poly_wide_int c = poly_wide_int::from (values, prec, SIGNED);
inchash::hash h;
h.add_int (TYPE_UID (type));
for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
h.add_wide_int (c.coeffs[i]);
poly_int_cst_hasher::compare_type comp (type, &c);
tree *slot = poly_int_cst_hash_table->find_slot_with_hash (comp, h.end (),
INSERT);
if (*slot == NULL_TREE)
{
tree coeffs[NUM_POLY_INT_COEFFS];
for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
coeffs[i] = wide_int_to_tree_1 (type, c.coeffs[i]);
*slot = build_new_poly_int_cst (type, coeffs);
}
return *slot;
}
/* Create a constant tree with value VALUE in type TYPE. */
tree
wide_int_to_tree (tree type, const poly_wide_int_ref &value)
{
if (value.is_constant ())
return wide_int_to_tree_1 (type, value.coeffs[0]);
return build_poly_int_cst (type, value);
}
void
cache_integer_cst (tree t)
{
tree type = TREE_TYPE (t);
int ix = -1;
int limit = 0;
int prec = TYPE_PRECISION (type);
gcc_assert (!TREE_OVERFLOW (t));
switch (TREE_CODE (type))
{
case NULLPTR_TYPE:
gcc_assert (integer_zerop (t));
/* Fallthru. */
case POINTER_TYPE:
case REFERENCE_TYPE:
/* Cache NULL pointer. */
if (integer_zerop (t))
{
limit = 1;
ix = 0;
}
break;
case BOOLEAN_TYPE:
/* Cache false or true. */
limit = 2;
if (wi::ltu_p (wi::to_wide (t), 2))
ix = TREE_INT_CST_ELT (t, 0);
break;
case INTEGER_TYPE:
case OFFSET_TYPE:
if (TYPE_UNSIGNED (type))
{
/* Cache 0..N */
limit = INTEGER_SHARE_LIMIT;
/* This is a little hokie, but if the prec is smaller than
what is necessary to hold INTEGER_SHARE_LIMIT, then the
obvious test will not get the correct answer. */
if (prec < HOST_BITS_PER_WIDE_INT)
{
if (tree_to_uhwi (t) < (unsigned HOST_WIDE_INT) INTEGER_SHARE_LIMIT)
ix = tree_to_uhwi (t);
}
else if (wi::ltu_p (wi::to_wide (t), INTEGER_SHARE_LIMIT))
ix = tree_to_uhwi (t);
}
else
{
/* Cache -1..N */
limit = INTEGER_SHARE_LIMIT + 1;
if (integer_minus_onep (t))
ix = 0;
else if (!wi::neg_p (wi::to_wide (t)))
{
if (prec < HOST_BITS_PER_WIDE_INT)
{
if (tree_to_shwi (t) < INTEGER_SHARE_LIMIT)
ix = tree_to_shwi (t) + 1;
}
else if (wi::ltu_p (wi::to_wide (t), INTEGER_SHARE_LIMIT))
ix = tree_to_shwi (t) + 1;
}
}
break;
case ENUMERAL_TYPE:
break;
default:
gcc_unreachable ();
}
if (ix >= 0)
{
/* Look for it in the type's vector of small shared ints. */
if (!TYPE_CACHED_VALUES_P (type))
{
TYPE_CACHED_VALUES_P (type) = 1;
TYPE_CACHED_VALUES (type) = make_tree_vec (limit);
}
gcc_assert (TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) == NULL_TREE);
TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
}
else
{
/* Use the cache of larger shared ints. */
tree *slot = int_cst_hash_table->find_slot (t, INSERT);
/* If there is already an entry for the number verify it's the
same. */
if (*slot)
gcc_assert (wi::to_wide (tree (*slot)) == wi::to_wide (t));
else
/* Otherwise insert this one into the hash table. */
*slot = t;
}
}
/* Builds an integer constant in TYPE such that lowest BITS bits are ones
and the rest are zeros. */
tree
build_low_bits_mask (tree type, unsigned bits)
{
gcc_assert (bits <= TYPE_PRECISION (type));
return wide_int_to_tree (type, wi::mask (bits, false,
TYPE_PRECISION (type)));
}
/* Checks that X is integer constant that can be expressed in (unsigned)
HOST_WIDE_INT without loss of precision. */
bool
cst_and_fits_in_hwi (const_tree x)
{
return (TREE_CODE (x) == INTEGER_CST
&& (tree_fits_shwi_p (x) || tree_fits_uhwi_p (x)));
}
/* Build a newly constructed VECTOR_CST with the given values of
(VECTOR_CST_)LOG2_NPATTERNS and (VECTOR_CST_)NELTS_PER_PATTERN. */
tree
make_vector (unsigned log2_npatterns,
unsigned int nelts_per_pattern MEM_STAT_DECL)
{
gcc_assert (IN_RANGE (nelts_per_pattern, 1, 3));
tree t;
unsigned npatterns = 1 << log2_npatterns;
unsigned encoded_nelts = npatterns * nelts_per_pattern;
unsigned length = (sizeof (struct tree_vector)
+ (encoded_nelts - 1) * sizeof (tree));
record_node_allocation_statistics (VECTOR_CST, length);
t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT);
TREE_SET_CODE (t, VECTOR_CST);
TREE_CONSTANT (t) = 1;
VECTOR_CST_LOG2_NPATTERNS (t) = log2_npatterns;
VECTOR_CST_NELTS_PER_PATTERN (t) = nelts_per_pattern;
return t;
}
/* Return a new VECTOR_CST node whose type is TYPE and whose values
are extracted from V, a vector of CONSTRUCTOR_ELT. */
tree
build_vector_from_ctor (tree type, vec<constructor_elt, va_gc> *v)
{
unsigned HOST_WIDE_INT idx, nelts;
tree value;
/* We can't construct a VECTOR_CST for a variable number of elements. */
nelts = TYPE_VECTOR_SUBPARTS (type).to_constant ();
tree_vector_builder vec (type, nelts, 1);
FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
{
if (TREE_CODE (value) == VECTOR_CST)
{
/* If NELTS is constant then this must be too. */
unsigned int sub_nelts = VECTOR_CST_NELTS (value).to_constant ();
for (unsigned i = 0; i < sub_nelts; ++i)
vec.quick_push (VECTOR_CST_ELT (value, i));
}
else
vec.quick_push (value);
}
while (vec.length () < nelts)
vec.quick_push (build_zero_cst (TREE_TYPE (type)));
return vec.build ();
}
/* Build a vector of type VECTYPE where all the elements are SCs. */
tree
build_vector_from_val (tree vectype, tree sc)
{
unsigned HOST_WIDE_INT i, nunits;
if (sc == error_mark_node)
return sc;
/* Verify that the vector type is suitable for SC. Note that there
is some inconsistency in the type-system with respect to restrict
qualifications of pointers. Vector types always have a main-variant
element type and the qualification is applied to the vector-type.
So TREE_TYPE (vector-type) does not return a properly qualified
vector element-type. */
gcc_checking_assert (types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (sc)),
TREE_TYPE (vectype)));
if (CONSTANT_CLASS_P (sc))
{
tree_vector_builder v (vectype, 1, 1);
v.quick_push (sc);
return v.build ();
}
else if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant (&nunits))
return fold_build1 (VEC_DUPLICATE_EXPR, vectype, sc);
else
{
vec<constructor_elt, va_gc> *v;
vec_alloc (v, nunits);
for (i = 0; i < nunits; ++i)
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, sc);
return build_constructor (vectype, v);
}
}
/* Build a vector series of type TYPE in which element I has the value
BASE + I * STEP. The result is a constant if BASE and STEP are constant
and a VEC_SERIES_EXPR otherwise. */
tree
build_vec_series (tree type, tree base, tree step)
{
if (integer_zerop (step))
return build_vector_from_val (type, base);
if (TREE_CODE (base) == INTEGER_CST && TREE_CODE (step) == INTEGER_CST)
{
tree_vector_builder builder (type, 1, 3);
tree elt1 = wide_int_to_tree (TREE_TYPE (base),
wi::to_wide (base) + wi::to_wide (step));
tree elt2 = wide_int_to_tree (TREE_TYPE (base),
wi::to_wide (elt1) + wi::to_wide (step));
builder.quick_push (base);
builder.quick_push (elt1);
builder.quick_push (elt2);
return builder.build ();
}
return build2 (VEC_SERIES_EXPR, type, base, step);
}
/* Return a vector with the same number of units and number of bits
as VEC_TYPE, but in which the elements are a linear series of unsigned
integers { BASE, BASE + STEP, BASE + STEP * 2, ... }. */
tree
build_index_vector (tree vec_type, poly_uint64 base, poly_uint64 step)
{
tree index_vec_type = vec_type;
tree index_elt_type = TREE_TYPE (vec_type);
poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vec_type);
if (!INTEGRAL_TYPE_P (index_elt_type) || !TYPE_UNSIGNED (index_elt_type))
{
index_elt_type = build_nonstandard_integer_type
(GET_MODE_BITSIZE (SCALAR_TYPE_MODE (index_elt_type)), true);
index_vec_type = build_vector_type (index_elt_type, nunits);
}
tree_vector_builder v (index_vec_type, 1, 3);
for (unsigned int i = 0; i < 3; ++i)
v.quick_push (build_int_cstu (index_elt_type, base + i * step));
return v.build ();
}
/* Something has messed with the elements of CONSTRUCTOR C after it was built;
calculate TREE_CONSTANT and TREE_SIDE_EFFECTS. */
void
recompute_constructor_flags (tree c)
{
unsigned int i;
tree val;
bool constant_p = true;
bool side_effects_p = false;
vec<constructor_elt, va_gc> *vals = CONSTRUCTOR_ELTS (c);
FOR_EACH_CONSTRUCTOR_VALUE (vals, i, val)
{
/* Mostly ctors will have elts that don't have side-effects, so
the usual case is to scan all the elements. Hence a single
loop for both const and side effects, rather than one loop
each (with early outs). */
if (!TREE_CONSTANT (val))
constant_p = false;
if (TREE_SIDE_EFFECTS (val))
side_effects_p = true;
}
TREE_SIDE_EFFECTS (c) = side_effects_p;
TREE_CONSTANT (c) = constant_p;
}
/* Make sure that TREE_CONSTANT and TREE_SIDE_EFFECTS are correct for
CONSTRUCTOR C. */
void
verify_constructor_flags (tree c)
{
unsigned int i;
tree val;
bool constant_p = TREE_CONSTANT (c);
bool side_effects_p = TREE_SIDE_EFFECTS (c);
vec<constructor_elt, va_gc> *vals = CONSTRUCTOR_ELTS (c);
FOR_EACH_CONSTRUCTOR_VALUE (vals, i, val)
{
if (constant_p && !TREE_CONSTANT (val))
internal_error ("non-constant element in constant CONSTRUCTOR");
if (!side_effects_p && TREE_SIDE_EFFECTS (val))
internal_error ("side-effects element in no-side-effects CONSTRUCTOR");
}
}
/* Return a new CONSTRUCTOR node whose type is TYPE and whose values
are in the vec pointed to by VALS. */
tree
build_constructor (tree type, vec<constructor_elt, va_gc> *vals)
{
tree c = make_node (CONSTRUCTOR);
TREE_TYPE (c) = type;
CONSTRUCTOR_ELTS (c) = vals;
recompute_constructor_flags (c);
return c;
}
/* Build a CONSTRUCTOR node made of a single initializer, with the specified
INDEX and VALUE. */
tree
build_constructor_single (tree type, tree index, tree value)
{
vec<constructor_elt, va_gc> *v;
constructor_elt elt = {index, value};
vec_alloc (v, 1);
v->quick_push (elt);
return build_constructor (type, v);
}
/* Return a new CONSTRUCTOR node whose type is TYPE and whose values
are in a list pointed to by VALS. */
tree
build_constructor_from_list (tree type, tree vals)
{
tree t;
vec<constructor_elt, va_gc> *v = NULL;
if (vals)
{
vec_alloc (v, list_length (vals));
for (t = vals; t; t = TREE_CHAIN (t))
CONSTRUCTOR_APPEND_ELT (v, TREE_PURPOSE (t), TREE_VALUE (t));
}
return build_constructor (type, v);
}
/* Return a new CONSTRUCTOR node whose type is TYPE. NELTS is the number
of elements, provided as index/value pairs. */
tree
build_constructor_va (tree type, int nelts, ...)
{
vec<constructor_elt, va_gc> *v = NULL;
va_list p;
va_start (p, nelts);
vec_alloc (v, nelts);
while (nelts--)
{
tree index = va_arg (p, tree);
tree value = va_arg (p, tree);
CONSTRUCTOR_APPEND_ELT (v, index, value);
}
va_end (p);
return build_constructor (type, v);
}
/* Return a new FIXED_CST node whose type is TYPE and value is F. */
tree
build_fixed (tree type, FIXED_VALUE_TYPE f)
{
tree v;
FIXED_VALUE_TYPE *fp;
v = make_node (FIXED_CST);
fp = ggc_alloc<fixed_value> ();
memcpy (fp, &f, sizeof (FIXED_VALUE_TYPE));
TREE_TYPE (v) = type;
TREE_FIXED_CST_PTR (v) = fp;
return v;
}
/* Return a new REAL_CST node whose type is TYPE and value is D. */
tree
build_real (tree type, REAL_VALUE_TYPE d)
{
tree v;
REAL_VALUE_TYPE *dp;
int overflow = 0;
/* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
Consider doing it via real_convert now. */
v = make_node (REAL_CST);
dp = ggc_alloc<real_value> ();
memcpy (dp, &d, sizeof (REAL_VALUE_TYPE));
TREE_TYPE (v) = type;
TREE_REAL_CST_PTR (v) = dp;
TREE_OVERFLOW (v) = overflow;
return v;
}
/* Like build_real, but first truncate D to the type. */
tree
build_real_truncate (tree type, REAL_VALUE_TYPE d)
{
return build_real (type, real_value_truncate (TYPE_MODE (type), d));
}
/* Return a new REAL_CST node whose type is TYPE
and whose value is the integer value of the INTEGER_CST node I. */
REAL_VALUE_TYPE
real_value_from_int_cst (const_tree type, const_tree i)
{
REAL_VALUE_TYPE d;
/* Clear all bits of the real value type so that we can later do
bitwise comparisons to see if two values are the same. */
memset (&d, 0, sizeof d);
real_from_integer (&d, type ? TYPE_MODE (type) : VOIDmode, wi::to_wide (i),
TYPE_SIGN (TREE_TYPE (i)));
return d;
}
/* Given a tree representing an integer constant I, return a tree
representing the same value as a floating-point constant of type TYPE. */
tree
build_real_from_int_cst (tree type, const_tree i)
{
tree v;
int overflow = TREE_OVERFLOW (i);
v = build_real (type, real_value_from_int_cst (type, i));
TREE_OVERFLOW (v) |= overflow;
return v;
}
/* Return a newly constructed STRING_CST node whose value is
the LEN characters at STR.
Note that for a C string literal, LEN should include the trailing NUL.
The TREE_TYPE is not initialized. */
tree
build_string (int len, const char *str)
{
tree s;
size_t length;
/* Do not waste bytes provided by padding of struct tree_string. */
length = len + offsetof (struct tree_string, str) + 1;
record_node_allocation_statistics (STRING_CST, length);
s = (tree) ggc_internal_alloc (length);
memset (s, 0, sizeof (struct tree_typed));
TREE_SET_CODE (s, STRING_CST);
TREE_CONSTANT (s) = 1;
TREE_STRING_LENGTH (s) = len;
memcpy (s->string.str, str, len);
s->string.str[len] = '\0';
return s;
}
/* Return a newly constructed COMPLEX_CST node whose value is
specified by the real and imaginary parts REAL and IMAG.
Both REAL and IMAG should be constant nodes. TYPE, if specified,
will be the type of the COMPLEX_CST; otherwise a new type will be made. */
tree
build_complex (tree type, tree real, tree imag)
{
tree t = make_node (COMPLEX_CST);
TREE_REALPART (t) = real;
TREE_IMAGPART (t) = imag;
TREE_TYPE (t) = type ? type : build_complex_type (TREE_TYPE (real));
TREE_OVERFLOW (t) = TREE_OVERFLOW (real) | TREE_OVERFLOW (imag);
return t;
}
/* Build a complex (inf +- 0i), such as for the result of cproj.
TYPE is the complex tree type of the result. If NEG is true, the
imaginary zero is negative. */
tree
build_complex_inf (tree type, bool neg)
{
REAL_VALUE_TYPE rinf, rzero = dconst0;
real_inf (&rinf);
rzero.sign = neg;
return build_complex (type, build_real (TREE_TYPE (type), rinf),
build_real (TREE_TYPE (type), rzero));
}
/* Return the constant 1 in type TYPE. If TYPE has several elements, each
element is set to 1. In particular, this is 1 + i for complex types. */
tree
build_each_one_cst (tree type)
{
if (TREE_CODE (type) == COMPLEX_TYPE)
{
tree scalar = build_one_cst (TREE_TYPE (type));
return build_complex (type, scalar, scalar);
}
else
return build_one_cst (type);
}
/* Return a constant of arithmetic type TYPE which is the
multiplicative identity of the set TYPE. */
tree
build_one_cst (tree type)
{
switch (TREE_CODE (type))
{
case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
case POINTER_TYPE: case REFERENCE_TYPE:
case OFFSET_TYPE:
return build_int_cst (type, 1);
case REAL_TYPE:
return build_real (type, dconst1);
case FIXED_POINT_TYPE:
/* We can only generate 1 for accum types. */
gcc_assert (ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type)));
return build_fixed (type, FCONST1 (TYPE_MODE (type)));
case VECTOR_TYPE:
{
tree scalar = build_one_cst (TREE_TYPE (type));
return build_vector_from_val (type, scalar);
}
case COMPLEX_TYPE:
return build_complex (type,
build_one_cst (TREE_TYPE (type)),
build_zero_cst (TREE_TYPE (type)));
default:
gcc_unreachable ();
}
}
/* Return an integer of type TYPE containing all 1's in as much precision as
it contains, or a complex or vector whose subparts are such integers. */
tree
build_all_ones_cst (tree type)
{
if (TREE_CODE (type) == COMPLEX_TYPE)
{
tree scalar = build_all_ones_cst (TREE_TYPE (type));
return build_complex (type, scalar, scalar);
}
else
return build_minus_one_cst (type);
}
/* Return a constant of arithmetic type TYPE which is the
opposite of the multiplicative identity of the set TYPE. */
tree
build_minus_one_cst (tree type)
{
switch (TREE_CODE (type))
{
case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
case POINTER_TYPE: case REFERENCE_TYPE:
case OFFSET_TYPE:
return build_int_cst (type, -1);
case REAL_TYPE:
return build_real (type, dconstm1);
case FIXED_POINT_TYPE:
/* We can only generate 1 for accum types. */
gcc_assert (ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type)));
return build_fixed (type,
fixed_from_double_int (double_int_minus_one,
SCALAR_TYPE_MODE (type)));
case VECTOR_TYPE:
{
tree scalar = build_minus_one_cst (TREE_TYPE (type));
return build_vector_from_val (type, scalar);
}
case COMPLEX_TYPE:
return build_complex (type,
build_minus_one_cst (TREE_TYPE (type)),
build_zero_cst (TREE_TYPE (type)));
default:
gcc_unreachable ();
}
}
/* Build 0 constant of type TYPE. This is used by constructor folding
and thus the constant should be represented in memory by
zero(es). */
tree
build_zero_cst (tree type)
{
switch (TREE_CODE (type))
{
case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
case POINTER_TYPE: case REFERENCE_TYPE:
case OFFSET_TYPE: case NULLPTR_TYPE:
return build_int_cst (type, 0);
case REAL_TYPE:
return build_real (type, dconst0);
case FIXED_POINT_TYPE:
return build_fixed (type, FCONST0 (TYPE_MODE (type)));
case VECTOR_TYPE:
{
tree scalar = build_zero_cst (TREE_TYPE (type));
return build_vector_from_val (type, scalar);
}
case COMPLEX_TYPE:
{
tree zero = build_zero_cst (TREE_TYPE (type));
return build_complex (type, zero, zero);
}
default:
if (!AGGREGATE_TYPE_P (type))
return fold_convert (type, integer_zero_node);
return build_constructor (type, NULL);
}
}
/* Build a BINFO with LEN language slots. */
tree
make_tree_binfo (unsigned base_binfos MEM_STAT_DECL)
{
tree t;
size_t length = (offsetof (struct tree_binfo, base_binfos)
+ vec<tree, va_gc>::embedded_size (base_binfos));
record_node_allocation_statistics (TREE_BINFO, length);
t = ggc_alloc_tree_node_stat (length PASS_MEM_STAT);
memset (t, 0, offsetof (struct tree_binfo, base_binfos));
TREE_SET_CODE (t, TREE_BINFO);
BINFO_BASE_BINFOS (t)->embedded_init (base_binfos);
return t;
}
/* Create a CASE_LABEL_EXPR tree node and return it. */
tree
build_case_label (tree low_value, tree high_value, tree label_decl)
{
tree t = make_node (CASE_LABEL_EXPR);
TREE_TYPE (t) = void_type_node;
SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (label_decl));
CASE_LOW (t) = low_value;
CASE_HIGH (t) = high_value;
CASE_LABEL (t) = label_decl;
CASE_CHAIN (t) = NULL_TREE;
return t;
}
/* Build a newly constructed INTEGER_CST node. LEN and EXT_LEN are the
values of TREE_INT_CST_NUNITS and TREE_INT_CST_EXT_NUNITS respectively.
The latter determines the length of the HOST_WIDE_INT vector. */
tree
make_int_cst (int len, int ext_len MEM_STAT_DECL)
{
tree t;
int length = ((ext_len - 1) * sizeof (HOST_WIDE_INT)
+ sizeof (struct tree_int_cst));
gcc_assert (len);
record_node_allocation_statistics (INTEGER_CST, length);
t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT);
TREE_SET_CODE (t, INTEGER_CST);
TREE_INT_CST_NUNITS (t) = len;
TREE_INT_CST_EXT_NUNITS (t) = ext_len;
/* to_offset can only be applied to trees that are offset_int-sized
or smaller. EXT_LEN is correct if it fits, otherwise the constant
must be exactly the precision of offset_int and so LEN is correct. */
if (ext_len <= OFFSET_INT_ELTS)
TREE_INT_CST_OFFSET_NUNITS (t) = ext_len;
else
TREE_INT_CST_OFFSET_NUNITS (t) = len;
TREE_CONSTANT (t) = 1;
return t;
}
/* Build a newly constructed TREE_VEC node of length LEN. */
tree
make_tree_vec (int len MEM_STAT_DECL)
{
tree t;
size_t length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
record_node_allocation_statistics (TREE_VEC, length);
t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT);
TREE_SET_CODE (t, TREE_VEC);
TREE_VEC_LENGTH (t) = len;
return t;
}
/* Grow a TREE_VEC node to new length LEN. */
tree
grow_tree_vec (tree v, int len MEM_STAT_DECL)
{
gcc_assert (TREE_CODE (v) == TREE_VEC);
int oldlen = TREE_VEC_LENGTH (v);
gcc_assert (len > oldlen);
size_t oldlength = (oldlen - 1) * sizeof (tree) + sizeof (struct tree_vec);
size_t length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
record_node_allocation_statistics (TREE_VEC, length - oldlength);
v = (tree) ggc_realloc (v, length PASS_MEM_STAT);
TREE_VEC_LENGTH (v) = len;
return v;
}
/* Return 1 if EXPR is the constant zero, whether it is integral, float or
fixed, and scalar, complex or vector. */
int
zerop (const_tree expr)
{
return (integer_zerop (expr)
|| real_zerop (expr)
|| fixed_zerop (expr));
}
/* Return 1 if EXPR is the integer constant zero or a complex constant
of zero. */
int
integer_zerop (const_tree expr)
{
switch (TREE_CODE (expr))
{
case INTEGER_CST:
return wi::to_wide (expr) == 0;
case COMPLEX_CST:
return (integer_zerop (TREE_REALPART (expr))
&& integer_zerop (TREE_IMAGPART (expr)));
case VECTOR_CST:
return (VECTOR_CST_NPATTERNS (expr) == 1
&& VECTOR_CST_DUPLICATE_P (expr)
&& integer_zerop (VECTOR_CST_ENCODED_ELT (expr, 0)));
default:
return false;
}
}
/* Return 1 if EXPR is the integer constant one or the corresponding
complex constant. */
int
integer_onep (const_tree expr)
{
switch (TREE_CODE (expr))
{
case INTEGER_CST:
return wi::eq_p (wi::to_widest (expr), 1);
case COMPLEX_CST:
return (integer_onep (TREE_REALPART (expr))
&& integer_zerop (TREE_IMAGPART (expr)));
case VECTOR_CST:
return (VECTOR_CST_NPATTERNS (expr) == 1
&& VECTOR_CST_DUPLICATE_P (expr)
&& integer_onep (VECTOR_CST_ENCODED_ELT (expr, 0)));
default:
return false;
}
}
/* Return 1 if EXPR is the integer constant one. For complex and vector,
return 1 if every piece is the integer constant one. */
int
integer_each_onep (const_tree expr)
{
if (TREE_CODE (expr) == COMPLEX_CST)
return (integer_onep (TREE_REALPART (expr))
&& integer_onep (TREE_IMAGPART (expr)));
else
return integer_onep (expr);
}
/* Return 1 if EXPR is an integer containing all 1's in as much precision as
it contains, or a complex or vector whose subparts are such integers. */
int
integer_all_onesp (const_tree expr)
{
if (TREE_CODE (expr) == COMPLEX_CST
&& integer_all_onesp (TREE_REALPART (expr))
&& integer_all_onesp (TREE_IMAGPART (expr)))
return 1;
else if (TREE_CODE (expr) == VECTOR_CST)
return (VECTOR_CST_NPATTERNS (expr) == 1
&& VECTOR_CST_DUPLICATE_P (expr)
&& integer_all_onesp (VECTOR_CST_ENCODED_ELT (expr, 0)));
else if (TREE_CODE (expr) != INTEGER_CST)
return 0;
return (wi::max_value (TYPE_PRECISION (TREE_TYPE (expr)), UNSIGNED)
== wi::to_wide (expr));
}
/* Return 1 if EXPR is the integer constant minus one. */
int
integer_minus_onep (const_tree expr)
{
if (TREE_CODE (expr) == COMPLEX_CST)
return (integer_all_onesp (TREE_REALPART (expr))
&& integer_zerop (TREE_IMAGPART (expr)));
else
return integer_all_onesp (expr);
}
/* Return 1 if EXPR is an integer constant that is a power of 2 (i.e., has only
one bit on). */
int
integer_pow2p (const_tree expr)
{
if (TREE_CODE (expr) == COMPLEX_CST
&& integer_pow2p (TREE_REALPART (expr))
&& integer_zerop (TREE_IMAGPART (expr)))
return 1;
if (TREE_CODE (expr) != INTEGER_CST)
return 0;
return wi::popcount (wi::to_wide (expr)) == 1;
}
/* Return 1 if EXPR is an integer constant other than zero or a
complex constant other than zero. */
int
integer_nonzerop (const_tree expr)
{
return ((TREE_CODE (expr) == INTEGER_CST
&& wi::to_wide (expr) != 0)
|| (TREE_CODE (expr) == COMPLEX_CST
&& (integer_nonzerop (TREE_REALPART (expr))
|| integer_nonzerop (TREE_IMAGPART (expr)))));
}
/* Return 1 if EXPR is the integer constant one. For vector,
return 1 if every piece is the integer constant minus one
(representing the value TRUE). */
int
integer_truep (const_tree expr)
{
if (TREE_CODE (expr) == VECTOR_CST)
return integer_all_onesp (expr);
return integer_onep (expr);
}
/* Return 1 if EXPR is the fixed-point constant zero. */
int
fixed_zerop (const_tree expr)
{
return (TREE_CODE (expr) == FIXED_CST
&& TREE_FIXED_CST (expr).data.is_zero ());
}
/* Return the power of two represented by a tree node known to be a
power of two. */
int
tree_log2 (const_tree expr)
{
if (TREE_CODE (expr) == COMPLEX_CST)
return tree_log2 (TREE_REALPART (expr));
return wi::exact_log2 (wi::to_wide (expr));
}
/* Similar, but return the largest integer Y such that 2 ** Y is less
than or equal to EXPR. */
int
tree_floor_log2 (const_tree expr)
{
if (TREE_CODE (expr) == COMPLEX_CST)
return tree_log2 (TREE_REALPART (expr));
return wi::floor_log2 (wi::to_wide (expr));
}
/* Return number of known trailing zero bits in EXPR, or, if the value of
EXPR is known to be zero, the precision of it's type. */
unsigned int
tree_ctz (const_tree expr)
{
if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
&& !POINTER_TYPE_P (TREE_TYPE (expr)))
return 0;
unsigned int ret1, ret2, prec = TYPE_PRECISION (TREE_TYPE (expr));
switch (TREE_CODE (expr))
{
case INTEGER_CST:
ret1 = wi::ctz (wi::to_wide (expr));
return MIN (ret1, prec);
case SSA_NAME:
ret1 = wi::ctz (get_nonzero_bits (expr));
return MIN (ret1, prec);
case PLUS_EXPR:
case MINUS_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case MIN_EXPR:
case MAX_EXPR:
ret1 = tree_ctz (TREE_OPERAND (expr, 0));
if (ret1 == 0)
return ret1;
ret2 = tree_ctz (TREE_OPERAND (expr, 1));
return MIN (ret1, ret2);
case POINTER_PLUS_EXPR:
ret1 = tree_ctz (TREE_OPERAND (expr, 0));
ret2 = tree_ctz (TREE_OPERAND (expr, 1));
/* Second operand is sizetype, which could be in theory
wider than pointer's precision. Make sure we never
return more than prec. */
ret2 = MIN (ret2, prec);
return MIN (ret1, ret2);
case BIT_AND_EXPR:
ret1 = tree_ctz (TREE_OPERAND (expr, 0));
ret2 = tree_ctz (TREE_OPERAND (expr, 1));
return MAX (ret1, ret2);
case MULT_EXPR:
ret1 = tree_ctz (TREE_OPERAND (expr, 0));
ret2 = tree_ctz (TREE_OPERAND (expr, 1));
return MIN (ret1 + ret2, prec);
case LSHIFT_EXPR:
ret1 = tree_ctz (TREE_OPERAND (expr, 0));
if (tree_fits_uhwi_p (TREE_OPERAND (expr, 1))
&& (tree_to_uhwi (TREE_OPERAND (expr, 1)) < prec))
{
ret2 = tree_to_uhwi (TREE_OPERAND (expr, 1));
return MIN (ret1 + ret2, prec);
}
return ret1;
case RSHIFT_EXPR:
if (tree_fits_uhwi_p (TREE_OPERAND (expr, 1))
&& (tree_to_uhwi (TREE_OPERAND (expr, 1)) < prec))
{
ret1 = tree_ctz (TREE_OPERAND (expr, 0));
ret2 = tree_to_uhwi (TREE_OPERAND (expr, 1));
if (ret1 > ret2)
return ret1 - ret2;
}
return 0;
case TRUNC_DIV_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST
&& tree_int_cst_sgn (TREE_OPERAND (expr, 1)) == 1)
{
int l = tree_log2 (TREE_OPERAND (expr, 1));
if (l >= 0)
{
ret1 = tree_ctz (TREE_OPERAND (expr, 0));
ret2 = l;
if (ret1 > ret2)
return ret1 - ret2;
}
}
return 0;
CASE_CONVERT:
ret1 = tree_ctz (TREE_OPERAND (expr, 0));
if (ret1 && ret1 == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
ret1 = prec;
return MIN (ret1, prec);
case SAVE_EXPR:
return tree_ctz (TREE_OPERAND (expr, 0));
case COND_EXPR:
ret1 = tree_ctz (TREE_OPERAND (expr, 1));
if (ret1 == 0)
return 0;
ret2 = tree_ctz (TREE_OPERAND (expr, 2));
return MIN (ret1, ret2);
case COMPOUND_EXPR:
return tree_ctz (TREE_OPERAND (expr, 1));
case ADDR_EXPR:
ret1 = get_pointer_alignment (CONST_CAST_TREE (expr));
if (ret1 > BITS_PER_UNIT)
{
ret1 = ctz_hwi (ret1 / BITS_PER_UNIT);
return MIN (ret1, prec);
}
return 0;
default:
return 0;
}
}
/* Return 1 if EXPR is the real constant zero. Trailing zeroes matter for
decimal float constants, so don't return 1 for them. */
int
real_zerop (const_tree expr)
{
switch (TREE_CODE (expr))
{
case REAL_CST:
return real_equal (&TREE_REAL_CST (expr), &dconst0)
&& !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
case COMPLEX_CST:
return real_zerop (TREE_REALPART (expr))
&& real_zerop (TREE_IMAGPART (expr));
case VECTOR_CST:
{
/* Don't simply check for a duplicate because the predicate
accepts both +0.0 and -0.0. */
unsigned count = vector_cst_encoded_nelts (expr);
for (unsigned int i = 0; i < count; ++i)
if (!real_zerop (VECTOR_CST_ENCODED_ELT (expr, i)))
return false;
return true;
}
default:
return false;
}
}
/* Return 1 if EXPR is the real constant one in real or complex form.
Trailing zeroes matter for decimal float constants, so don't return
1 for them. */
int
real_onep (const_tree expr)
{
switch (TREE_CODE (expr))
{
case REAL_CST:
return real_equal (&TREE_REAL_CST (expr), &dconst1)
&& !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
case COMPLEX_CST:
return real_onep (TREE_REALPART (expr))
&& real_zerop (TREE_IMAGPART (expr));
case VECTOR_CST:
return (VECTOR_CST_NPATTERNS (expr) == 1
&& VECTOR_CST_DUPLICATE_P (expr)
&& real_onep (VECTOR_CST_ENCODED_ELT (expr, 0)));
default:
return false;
}
}
/* Return 1 if EXPR is the real constant minus one. Trailing zeroes
matter for decimal float constants, so don't return 1 for them. */
int
real_minus_onep (const_tree expr)
{
switch (TREE_CODE (expr))
{
case REAL_CST:
return real_equal (&TREE_REAL_CST (expr), &dconstm1)
&& !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
case COMPLEX_CST:
return real_minus_onep (TREE_REALPART (expr))
&& real_zerop (TREE_IMAGPART (expr));
case VECTOR_CST:
return (VECTOR_CST_NPATTERNS (expr) == 1
&& VECTOR_CST_DUPLICATE_P (expr)
&& real_minus_onep (VECTOR_CST_ENCODED_ELT (expr, 0)));
default:
return false;
}
}
/* Nonzero if EXP is a constant or a cast of a constant. */
int
really_constant_p (const_tree exp)
{
/* This is not quite the same as STRIP_NOPS. It does more. */
while (CONVERT_EXPR_P (exp)
|| TREE_CODE (exp) == NON_LVALUE_EXPR)
exp = TREE_OPERAND (exp, 0);
return TREE_CONSTANT (exp);
}
/* Return true if T holds a polynomial pointer difference, storing it in
*VALUE if so. A true return means that T's precision is no greater
than 64 bits, which is the largest address space we support, so *VALUE
never loses precision. However, the signedness of the result does
not necessarily match the signedness of T: sometimes an unsigned type
like sizetype is used to encode a value that is actually negative. */
bool
ptrdiff_tree_p (const_tree t, poly_int64_pod *value)
{
if (!t)
return false;
if (TREE_CODE (t) == INTEGER_CST)
{
if (!cst_and_fits_in_hwi (t))
return false;
*value = int_cst_value (t);
return true;
}
if (POLY_INT_CST_P (t))
{
for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
if (!cst_and_fits_in_hwi (POLY_INT_CST_COEFF (t, i)))
return false;
for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
value->coeffs[i] = int_cst_value (POLY_INT_CST_COEFF (t, i));
return true;
}
return false;
}
poly_int64
tree_to_poly_int64 (const_tree t)
{
gcc_assert (tree_fits_poly_int64_p (t));
if (POLY_INT_CST_P (t))
return poly_int_cst_value (t).force_shwi ();
return TREE_INT_CST_LOW (t);
}
poly_uint64
tree_to_poly_uint64 (const_tree t)
{
gcc_assert (tree_fits_poly_uint64_p (t));
if (POLY_INT_CST_P (t))
return poly_int_cst_value (t).force_uhwi ();
return TREE_INT_CST_LOW (t);
}
/* Return first list element whose TREE_VALUE is ELEM.
Return 0 if ELEM is not in LIST. */
tree
value_member (tree elem, tree list)
{
while (list)
{
if (elem == TREE_VALUE (list))
return list;
list = TREE_CHAIN (list);
}
return NULL_TREE;
}
/* Return first list element whose TREE_PURPOSE is ELEM.
Return 0 if ELEM is not in LIST. */
tree
purpose_member (const_tree elem, tree list)
{
while (list)
{
if (elem == TREE_PURPOSE (list))
return list;
list = TREE_CHAIN (list);
}
return NULL_TREE;
}
/* Return true if ELEM is in V. */
bool
vec_member (const_tree elem, vec<tree, va_gc> *v)
{
unsigned ix;
tree t;
FOR_EACH_VEC_SAFE_ELT (v, ix, t)
if (elem == t)
return true;
return false;
}
/* Returns element number IDX (zero-origin) of chain CHAIN, or
NULL_TREE. */
tree
chain_index (int idx, tree chain)
{
for (; chain && idx > 0; --idx)
chain = TREE_CHAIN (chain);
return chain;
}
/* Return nonzero if ELEM is part of the chain CHAIN. */
int
chain_member (const_tree elem, const_tree chain)
{
while (chain)
{
if (elem == chain)
return 1;
chain = DECL_CHAIN (chain);
}
return 0;
}
/* Return the length of a chain of nodes chained through TREE_CHAIN.
We expect a null pointer to mark the end of the chain.
This is the Lisp primitive `length'. */
int
list_length (const_tree t)
{
const_tree p = t;
#ifdef ENABLE_TREE_CHECKING
const_tree q = t;
#endif
int len = 0;
while (p)
{
p = TREE_CHAIN (p);
#ifdef ENABLE_TREE_CHECKING
if (len % 2)
q = TREE_CHAIN (q);
gcc_assert (p != q);
#endif
len++;
}
return len;
}
/* Returns the first FIELD_DECL in the TYPE_FIELDS of the RECORD_TYPE or
UNION_TYPE TYPE, or NULL_TREE if none. */
tree
first_field (const_tree type)
{
tree t = TYPE_FIELDS (type);
while (t && TREE_CODE (t) != FIELD_DECL)
t = TREE_CHAIN (t);
return t;
}
/* Concatenate two chains of nodes (chained through TREE_CHAIN)
by modifying the last node in chain 1 to point to chain 2.
This is the Lisp primitive `nconc'. */
tree
chainon (tree op1, tree op2)
{
tree t1;
if (!op1)
return op2;
if (!op2)
return op1;
for (t1 = op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1))
continue;
TREE_CHAIN (t1) = op2;
#ifdef ENABLE_TREE_CHECKING
{
tree t2;
for (t2 = op2; t2; t2 = TREE_CHAIN (t2))
gcc_assert (t2 != t1);
}
#endif
return op1;
}
/* Return the last node in a chain of nodes (chained through TREE_CHAIN). */
tree
tree_last (tree chain)
{
tree next;
if (chain)
while ((next = TREE_CHAIN (chain)))
chain = next;
return chain;
}
/* Reverse the order of elements in the chain T,
and return the new head of the chain (old last element). */
tree
nreverse (tree t)
{
tree prev = 0, decl, next;
for (decl = t; decl; decl = next)
{
/* We shouldn't be using this function to reverse BLOCK chains; we
have blocks_nreverse for that. */
gcc_checking_assert (TREE_CODE (decl) != BLOCK);
next = TREE_CHAIN (decl);
TREE_CHAIN (decl) = prev;
prev = decl;
}
return prev;
}
/* Return a newly created TREE_LIST node whose
purpose and value fields are PARM and VALUE. */
tree
build_tree_list (tree parm, tree value MEM_STAT_DECL)
{
tree t = make_node (TREE_LIST PASS_MEM_STAT);
TREE_PURPOSE (t) = parm;
TREE_VALUE (t) = value;
return t;
}
/* Build a chain of TREE_LIST nodes from a vector. */
tree
build_tree_list_vec (const vec<tree, va_gc> *vec MEM_STAT_DECL)
{
tree ret = NULL_TREE;
tree *pp = &ret;
unsigned int i;
tree t;
FOR_EACH_VEC_SAFE_ELT (vec, i, t)
{
*pp = build_tree_list (NULL, t PASS_MEM_STAT);
pp = &TREE_CHAIN (*pp);
}
return ret;
}
/* Return a newly created TREE_LIST node whose
purpose and value fields are PURPOSE and VALUE
and whose TREE_CHAIN is CHAIN. */
tree
tree_cons (tree purpose, tree value, tree chain MEM_STAT_DECL)
{
tree node;
node = ggc_alloc_tree_node_stat (sizeof (struct tree_list) PASS_MEM_STAT);
memset (node, 0, sizeof (struct tree_common));
record_node_allocation_statistics (TREE_LIST, sizeof (struct tree_list));
TREE_SET_CODE (node, TREE_LIST);
TREE_CHAIN (node) = chain;
TREE_PURPOSE (node) = purpose;
TREE_VALUE (node) = value;
return node;
}
/* Return the values of the elements of a CONSTRUCTOR as a vector of
trees. */
vec<tree, va_gc> *
ctor_to_vec (tree ctor)
{
vec<tree, va_gc> *vec;
vec_alloc (vec, CONSTRUCTOR_NELTS (ctor));
unsigned int ix;
tree val;
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), ix, val)
vec->quick_push (val);
return vec;
}
/* Return the size nominally occupied by an object of type TYPE
when it resides in memory. The value is measured in units of bytes,
and its data type is that normally used for type sizes
(which is the first type created by make_signed_type or
make_unsigned_type). */
tree
size_in_bytes_loc (location_t loc, const_tree type)
{
tree t;
if (type == error_mark_node)
return integer_zero_node;
type = TYPE_MAIN_VARIANT (type);
t = TYPE_SIZE_UNIT (type);
if (t == 0)
{
lang_hooks.types.incomplete_type_error (loc, NULL_TREE, type);
return size_zero_node;
}
return t;
}
/* Return the size of TYPE (in bytes) as a wide integer
or return -1 if the size can vary or is larger than an integer. */
HOST_WIDE_INT
int_size_in_bytes (const_tree type)
{
tree t;
if (type == error_mark_node)
return 0;
type = TYPE_MAIN_VARIANT (type);
t = TYPE_SIZE_UNIT (type);
if (t && tree_fits_uhwi_p (t))
return TREE_INT_CST_LOW (t);
else
return -1;
}
/* Return the maximum size of TYPE (in bytes) as a wide integer
or return -1 if the size can vary or is larger than an integer. */
HOST_WIDE_INT
max_int_size_in_bytes (const_tree type)
{
HOST_WIDE_INT size = -1;
tree size_tree;
/* If this is an array type, check for a possible MAX_SIZE attached. */
if (TREE_CODE (type) == ARRAY_TYPE)
{
size_tree = TYPE_ARRAY_MAX_SIZE (type);
if (size_tree && tree_fits_uhwi_p (size_tree))
size = tree_to_uhwi (size_tree);
}
/* If we still haven't been able to get a size, see if the language
can compute a maximum size. */
if (size == -1)
{
size_tree = lang_hooks.types.max_size (type);
if (size_tree && tree_fits_uhwi_p (size_tree))
size = tree_to_uhwi (size_tree);
}
return size;
}
/* Return the bit position of FIELD, in bits from the start of the record.
This is a tree of type bitsizetype. */
tree
bit_position (const_tree field)
{
return bit_from_pos (DECL_FIELD_OFFSET (field),
DECL_FIELD_BIT_OFFSET (field));
}
/* Return the byte position of FIELD, in bytes from the start of the record.
This is a tree of type sizetype. */
tree
byte_position (const_tree field)
{
return byte_from_pos (DECL_FIELD_OFFSET (field),
DECL_FIELD_BIT_OFFSET (field));
}
/* Likewise, but return as an integer. It must be representable in
that way (since it could be a signed value, we don't have the
option of returning -1 like int_size_in_byte can. */
HOST_WIDE_INT
int_byte_position (const_tree field)
{
return tree_to_shwi (byte_position (field));
}
/* Return the strictest alignment, in bits, that T is known to have. */
unsigned int
expr_align (const_tree t)
{
unsigned int align0, align1;
switch (TREE_CODE (t))
{
CASE_CONVERT: case NON_LVALUE_EXPR:
/* If we have conversions, we know that the alignment of the
object must meet each of the alignments of the types. */
align0 = expr_align (TREE_OPERAND (t, 0));
align1 = TYPE_ALIGN (TREE_TYPE (t));
return MAX (align0, align1);
case SAVE_EXPR: case COMPOUND_EXPR: case MODIFY_EXPR:
case INIT_EXPR: case TARGET_EXPR: case WITH_CLEANUP_EXPR:
case CLEANUP_POINT_EXPR:
/* These don't change the alignment of an object. */
return expr_align (TREE_OPERAND (t, 0));
case COND_EXPR:
/* The best we can do is say that the alignment is the least aligned
of the two arms. */
align0 = expr_align (TREE_OPERAND (t, 1));
align1 = expr_align (TREE_OPERAND (t, 2));
return MIN (align0, align1);
/* FIXME: LABEL_DECL and CONST_DECL never have DECL_ALIGN set
meaningfully, it's always 1. */
case LABEL_DECL: case CONST_DECL: