#include "stringpool.h"
#include "varasm.h"
#include "flags.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "vec.h"
+#include "machmode.h"
+#include "hard-reg-set.h"
+#include "input.h"
#include "function.h"
#include "expr.h"
-#include "hard-reg-set.h"
#include "regs.h"
#include "output.h"
#include "diagnostic-core.h"
-#include "hashtab.h"
#include "ggc.h"
#include "langhooks.h"
#include "tm_p.h"
#include "target.h"
#include "common/common-target.h"
#include "targhooks.h"
+#include "predict.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "basic-block.h"
+#include "hash-map.h"
+#include "is-a.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
#include "cgraph.h"
-#include "hash-set.h"
#include "asan.h"
-#include "basic-block.h"
+#include "rtl-iter.h"
+#include "tree-chkp.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data
bool first_function_block_is_cold;
-/* We give all constants their own alias set. Perhaps redundant with
- MEM_READONLY_P, but pre-dates it. */
-
-static alias_set_type const_alias_set;
-
/* Whether we saw any functions with no_split_stack. */
static bool saw_no_split_stack;
static bool incorporeal_function_p (tree);
#endif
static void decode_addr_const (tree, struct addr_const *);
-static hashval_t const_desc_hash (const void *);
-static int const_desc_eq (const void *, const void *);
static hashval_t const_hash_1 (const tree);
static int compare_constant (const tree, const tree);
static void output_constant_def_contents (rtx);
((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \
&& DECL_SECTION_NAME (DECL) != NULL)
+struct section_hasher : ggc_hasher<section *>
+{
+ typedef const char *compare_type;
+
+ static hashval_t hash (section *);
+ static bool equal (section *, const char *);
+};
+
/* Hash table of named sections. */
-static GTY((param_is (section))) htab_t section_htab;
+static GTY(()) hash_table<section_hasher> *section_htab;
+
+struct object_block_hasher : ggc_hasher<object_block *>
+{
+ typedef const section *compare_type;
+
+ static hashval_t hash (object_block *);
+ static bool equal (object_block *, const section *);
+};
/* A table of object_blocks, indexed by section. */
-static GTY((param_is (struct object_block))) htab_t object_block_htab;
+static GTY(()) hash_table<object_block_hasher> *object_block_htab;
/* The next number to use for internal anchor labels. */
static GTY(()) int anchor_labelno;
/* Helper routines for maintaining section_htab. */
-static int
-section_entry_eq (const void *p1, const void *p2)
+bool
+section_hasher::equal (section *old, const char *new_name)
{
- const section *old = (const section *) p1;
- const char *new_name = (const char *) p2;
-
return strcmp (old->named.name, new_name) == 0;
}
-static hashval_t
-section_entry_hash (const void *p)
+hashval_t
+section_hasher::hash (section *old)
{
- const section *old = (const section *) p;
return htab_hash_string (old->named.name);
}
/* Helper routines for maintaining object_block_htab. */
-static int
-object_block_entry_eq (const void *p1, const void *p2)
+inline bool
+object_block_hasher::equal (object_block *old, const section *new_section)
{
- const struct object_block *old = (const struct object_block *) p1;
- const section *new_section = (const section *) p2;
-
return old->sect == new_section;
}
-static hashval_t
-object_block_entry_hash (const void *p)
+hashval_t
+object_block_hasher::hash (object_block *old)
{
- const struct object_block *old = (const struct object_block *) p;
return hash_section (old->sect);
}
{
section *sect, **slot;
- slot = (section **)
- htab_find_slot_with_hash (section_htab, name,
- htab_hash_string (name), INSERT);
+ slot = section_htab->find_slot_with_hash (name, htab_hash_string (name),
+ INSERT);
flags |= SECTION_NAMED;
if (*slot == NULL)
{
get_block_for_section (section *sect)
{
struct object_block *block;
- void **slot;
if (sect == NULL)
return NULL;
- slot = htab_find_slot_with_hash (object_block_htab, sect,
- hash_section (sect), INSERT);
- block = (struct object_block *) *slot;
+ object_block **slot
+ = object_block_htab->find_slot_with_hash (sect, hash_section (sect),
+ INSERT);
+ block = *slot;
if (block == NULL)
{
block = ggc_cleared_alloc<object_block> ();
&& (len = int_size_in_bytes (TREE_TYPE (decl))) > 0
&& TREE_STRING_LENGTH (decl) >= len)
{
- enum machine_mode mode;
+ machine_mode mode;
unsigned int modesize;
const char *str;
HOST_WIDE_INT i;
/* Return the section to use for constant merging. */
section *
-mergeable_constant_section (enum machine_mode mode ATTRIBUTE_UNUSED,
+mergeable_constant_section (machine_mode mode ATTRIBUTE_UNUSED,
unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED,
unsigned int flags ATTRIBUTE_UNUSED)
{
if (asmspec[0] != 0 && i < 0)
{
i = atoi (asmspec);
- if (i < FIRST_PSEUDO_REGISTER && i >= 0)
+ if (i < FIRST_PSEUDO_REGISTER && i >= 0 && reg_names[i][0])
return i;
else
return -2;
for (i = 0; i < (int) ARRAY_SIZE (table); i++)
if (table[i].name[0]
- && ! strcmp (asmspec, table[i].name))
+ && ! strcmp (asmspec, table[i].name)
+ && reg_names[table[i].number][0])
return table[i].number;
}
#endif /* ADDITIONAL_REGISTER_NAMES */
return targetm.use_blocks_for_decl_p (decl);
}
+/* Follow the IDENTIFIER_TRANSPARENT_ALIAS chain starting at *ALIAS
+ until we find an identifier that is not itself a transparent alias.
+ Modify the alias passed to it by reference (and all aliases on the
+ way to the ultimate target), such that they do not have to be
+ followed again, and return the ultimate target of the alias
+ chain. */
+
+static inline tree
+ultimate_transparent_alias_target (tree *alias)
+{
+ tree target = *alias;
+
+ if (IDENTIFIER_TRANSPARENT_ALIAS (target))
+ {
+ gcc_assert (TREE_CHAIN (target));
+ target = ultimate_transparent_alias_target (&TREE_CHAIN (target));
+ gcc_assert (! IDENTIFIER_TRANSPARENT_ALIAS (target)
+ && ! TREE_CHAIN (target));
+ *alias = target;
+ }
+
+ return target;
+}
+
/* Create the DECL_RTL for a VAR_DECL or FUNCTION_DECL. DECL should
have static storage duration. In other words, it should not be an
automatic variable, including PARM_DECLs.
{
const char *name = 0;
int reg_number;
+ tree id;
rtx x;
/* Check that we are not being given an automatic variable. */
return;
}
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ id = DECL_ASSEMBLER_NAME (decl);
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && cgraph_node::get (decl)
+ && cgraph_node::get (decl)->instrumentation_clone)
+ ultimate_transparent_alias_target (&id);
+ name = IDENTIFIER_POINTER (id);
if (name[0] != '*' && TREE_CODE (decl) != FUNCTION_DECL
&& DECL_REGISTER (decl))
else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
{
const char *asmspec = name+1;
- enum machine_mode mode = DECL_MODE (decl);
+ machine_mode mode = DECL_MODE (decl);
reg_number = decode_reg_name (asmspec);
/* First detect errors in declaring global registers. */
if (reg_number == -1)
/* As a register variable, it has no section. */
return;
}
+ /* Avoid internal errors from invalid register
+ specifications. */
+ SET_DECL_ASSEMBLER_NAME (decl, NULL_TREE);
+ DECL_HARD_REGISTER (decl) = 0;
+ return;
}
/* Now handle ordinary static variables and functions (in memory).
Also handle vars declared register invalidly. */
x = create_block_symbol (name, get_block_for_decl (decl), -1);
else
{
- enum machine_mode address_mode = Pmode;
+ machine_mode address_mode = Pmode;
if (TREE_TYPE (decl) != error_mark_node)
{
addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
{
switch_to_section (sec);
assemble_align (POINTER_SIZE);
- assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+ assemble_integer (symbol, POINTER_SIZE_UNITS, POINTER_SIZE, 1);
}
/* Return the numbered .ctors.N (if CONSTRUCTOR_P) or .dtors.N (if
in_cold_section_p = first_function_block_is_cold;
}
+/* Get the function's name, as described by its RTL. This may be
+ different from the DECL_NAME name used in the source file. */
+const char *
+get_fnname_from_decl (tree decl)
+{
+ rtx x = DECL_RTL (decl);
+ gcc_assert (MEM_P (x));
+ x = XEXP (x, 0);
+ gcc_assert (GET_CODE (x) == SYMBOL_REF);
+ return XSTR (x, 0);
+}
+
/* Output assembler code for the constant pool of a function and associated
with defining the name of the function. DECL describes the function.
NAME is the function's name. For the constant pool, we use the current
/* Make function name accessible from other files, if appropriate. */
- if (TREE_PUBLIC (decl))
+ if (TREE_PUBLIC (decl)
+ || (cgraph_node::get (decl)->instrumentation_clone
+ && cgraph_node::get (decl)->instrumented_version
+ && TREE_PUBLIC (cgraph_node::get (decl)->instrumented_version->decl)))
{
notice_global_symbol (decl);
else
/* Leave space for it. */
assemble_zeros (tree_to_uhwi (DECL_SIZE_UNIT (decl)));
+ targetm.asm_out.decl_end ();
}
}
+/* Write out assembly for the variable DECL, which is not defined in
+ the current translation unit. */
+void
+assemble_undefined_decl (tree decl)
+{
+ const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+ targetm.asm_out.assemble_undefined_decl (asm_out_file, name, decl);
+}
+
/* Assemble everything that is needed for a variable or function declaration.
Not used for automatic variables, and not used for function definitions.
Should not be called for variables of incomplete structure type.
}
-/* Follow the IDENTIFIER_TRANSPARENT_ALIAS chain starting at *ALIAS
- until we find an identifier that is not itself a transparent alias.
- Modify the alias passed to it by reference (and all aliases on the
- way to the ultimate target), such that they do not have to be
- followed again, and return the ultimate target of the alias
- chain. */
-
-static inline tree
-ultimate_transparent_alias_target (tree *alias)
-{
- tree target = *alias;
-
- if (IDENTIFIER_TRANSPARENT_ALIAS (target))
- {
- gcc_assert (TREE_CHAIN (target));
- target = ultimate_transparent_alias_target (&TREE_CHAIN (target));
- gcc_assert (! IDENTIFIER_TRANSPARENT_ALIAS (target)
- && ! TREE_CHAIN (target));
- *alias = target;
- }
-
- return target;
-}
-
/* Output to FILE (an assembly file) a reference to NAME. If NAME
starts with a *, the rest of NAME is output verbatim. Otherwise
NAME is transformed in a target-specific way (usually by the
const char *op = integer_asm_op (size, aligned_p);
/* Avoid GAS bugs for large values. Specifically negative values whose
absolute value fits in a bfd_vma, but not in a bfd_signed_vma. */
- if (size > UNITS_PER_WORD && size > POINTER_SIZE / BITS_PER_UNIT)
+ if (size > UNITS_PER_WORD && size > POINTER_SIZE_UNITS)
return false;
return op && (assemble_integer_with_op (op, x), true);
}
it into words it if is multi-word, otherwise split it into bytes. */
if (size > 1)
{
- enum machine_mode omode, imode;
+ machine_mode omode, imode;
unsigned int subalign;
unsigned int subsize, i;
enum mode_class mclass;
}
\f
void
-assemble_real (REAL_VALUE_TYPE d, enum machine_mode mode, unsigned int align)
+assemble_real (REAL_VALUE_TYPE d, machine_mode mode, unsigned int align)
{
long data[4] = {0, 0, 0, 0};
int i;
value->offset = offset;
}
\f
-
-static GTY((param_is (struct constant_descriptor_tree)))
- htab_t const_desc_htab;
+static GTY(()) hash_table<tree_descriptor_hasher> *const_desc_htab;
static void maybe_output_constant_def_contents (struct constant_descriptor_tree *, int);
/* Constant pool accessor function. */
-htab_t
+hash_table<tree_descriptor_hasher> *
constant_pool_htab (void)
{
return const_desc_htab;
/* Compute a hash code for a constant expression. */
-static hashval_t
-const_desc_hash (const void *ptr)
+hashval_t
+tree_descriptor_hasher::hash (constant_descriptor_tree *ptr)
{
- return ((const struct constant_descriptor_tree *)ptr)->hash;
+ return ptr->hash;
}
static hashval_t
break;
case LABEL_REF:
- hi = value.offset + CODE_LABEL_NUMBER (XEXP (value.base, 0)) * 13;
+ hi = (value.offset
+ + CODE_LABEL_NUMBER (LABEL_REF_LABEL (value.base)) * 13);
break;
default:
}
/* Wrapper of compare_constant, for the htab interface. */
-static int
-const_desc_eq (const void *p1, const void *p2)
+bool
+tree_descriptor_hasher::equal (constant_descriptor_tree *c1,
+ constant_descriptor_tree *c2)
{
- const struct constant_descriptor_tree *const c1
- = (const struct constant_descriptor_tree *) p1;
- const struct constant_descriptor_tree *const c2
- = (const struct constant_descriptor_tree *) p2;
if (c1->hash != c2->hash)
return 0;
return compare_constant (c1->value, c2->value);
break;
case LABEL_REF:
- ret = (CODE_LABEL_NUMBER (XEXP (value1.base, 0))
- == CODE_LABEL_NUMBER (XEXP (value2.base, 0)));
+ ret = (CODE_LABEL_NUMBER (LABEL_REF_LABEL (value1.base))
+ == CODE_LABEL_NUMBER (LABEL_REF_LABEL (value2.base)));
break;
default:
rtl = gen_const_mem (TYPE_MODE (TREE_TYPE (exp)), symbol);
set_mem_attributes (rtl, exp, 1);
set_mem_alias_set (rtl, 0);
- set_mem_alias_set (rtl, const_alias_set);
/* We cannot share RTX'es in pool entries.
Mark this piece of RTL as required for unsharing. */
{
struct constant_descriptor_tree *desc;
struct constant_descriptor_tree key;
- void **loc;
/* Look up EXP in the table of constant descriptors. If we didn't find
it, create a new one. */
key.value = exp;
key.hash = const_hash_1 (exp);
- loc = htab_find_slot_with_hash (const_desc_htab, &key, key.hash, INSERT);
+ constant_descriptor_tree **loc
+ = const_desc_htab->find_slot_with_hash (&key, key.hash, INSERT);
- desc = (struct constant_descriptor_tree *) *loc;
+ desc = *loc;
if (desc == 0)
{
desc = build_constant_desc (exp);
/* Output the value of EXP. */
output_constant (exp, size, align);
+
+ targetm.asm_out.decl_end ();
}
/* We must output the constant data referred to by SYMBOL; do so. */
rtx
lookup_constant_def (tree exp)
{
- struct constant_descriptor_tree *desc;
struct constant_descriptor_tree key;
key.value = exp;
key.hash = const_hash_1 (exp);
- desc = (struct constant_descriptor_tree *)
- htab_find_with_hash (const_desc_htab, &key, key.hash);
+ constant_descriptor_tree *desc
+ = const_desc_htab->find_with_hash (&key, key.hash);
return (desc ? desc->rtl : NULL_RTX);
}
tree_output_constant_def (tree exp)
{
struct constant_descriptor_tree *desc, key;
- void **loc;
tree decl;
/* Look up EXP in the table of constant descriptors. If we didn't find
it, create a new one. */
key.value = exp;
key.hash = const_hash_1 (exp);
- loc = htab_find_slot_with_hash (const_desc_htab, &key, key.hash, INSERT);
+ constant_descriptor_tree **loc
+ = const_desc_htab->find_slot_with_hash (&key, key.hash, INSERT);
- desc = (struct constant_descriptor_tree *) *loc;
+ desc = *loc;
if (desc == 0)
{
desc = build_constant_desc (exp);
return decl;
}
\f
+struct GTY((chain_next ("%h.next"), for_user)) constant_descriptor_rtx {
+ struct constant_descriptor_rtx *next;
+ rtx mem;
+ rtx sym;
+ rtx constant;
+ HOST_WIDE_INT offset;
+ hashval_t hash;
+ machine_mode mode;
+ unsigned int align;
+ int labelno;
+ int mark;
+};
+
+struct const_rtx_desc_hasher : ggc_hasher<constant_descriptor_rtx *>
+{
+ static hashval_t hash (constant_descriptor_rtx *);
+ static bool equal (constant_descriptor_rtx *, constant_descriptor_rtx *);
+};
+
/* Used in the hash tables to avoid outputting the same constant
twice. Unlike 'struct constant_descriptor_tree', RTX constants
are output once per function, not once per file. */
It is used on RISC machines where immediate integer arguments and
constant addresses are restricted so that such constants must be stored
in memory. */
- htab_t GTY((param_is (struct constant_descriptor_rtx))) const_rtx_htab;
+ hash_table<const_rtx_desc_hasher> *const_rtx_htab;
/* Current offset in constant pool (does not include any
machine-specific header). */
HOST_WIDE_INT offset;
};
-struct GTY((chain_next ("%h.next"))) constant_descriptor_rtx {
- struct constant_descriptor_rtx *next;
- rtx mem;
- rtx sym;
- rtx constant;
- HOST_WIDE_INT offset;
- hashval_t hash;
- enum machine_mode mode;
- unsigned int align;
- int labelno;
- int mark;
-};
-
/* Hash and compare functions for const_rtx_htab. */
-static hashval_t
-const_desc_rtx_hash (const void *ptr)
+hashval_t
+const_rtx_desc_hasher::hash (constant_descriptor_rtx *desc)
{
- const struct constant_descriptor_rtx *const desc
- = (const struct constant_descriptor_rtx *) ptr;
return desc->hash;
}
-static int
-const_desc_rtx_eq (const void *a, const void *b)
+bool
+const_rtx_desc_hasher::equal (constant_descriptor_rtx *x,
+ constant_descriptor_rtx *y)
{
- const struct constant_descriptor_rtx *const x
- = (const struct constant_descriptor_rtx *) a;
- const struct constant_descriptor_rtx *const y
- = (const struct constant_descriptor_rtx *) b;
-
if (x->mode != y->mode)
return 0;
return rtx_equal_p (x->constant, y->constant);
}
-/* This is the worker function for const_rtx_hash, called via for_each_rtx. */
+/* Hash one component of a constant. */
-static int
-const_rtx_hash_1 (rtx *xp, void *data)
+static hashval_t
+const_rtx_hash_1 (const_rtx x)
{
unsigned HOST_WIDE_INT hwi;
- enum machine_mode mode;
+ machine_mode mode;
enum rtx_code code;
- hashval_t h, *hp;
- rtx x;
+ hashval_t h;
int i;
- x = *xp;
code = GET_CODE (x);
mode = GET_MODE (x);
h = (hashval_t) code * 1048573 + mode;
h ^= fixed_hash (CONST_FIXED_VALUE (x));
break;
- case CONST_VECTOR:
- {
- int i;
- for (i = XVECLEN (x, 0); i-- > 0; )
- h = h * 251 + const_rtx_hash_1 (&XVECEXP (x, 0, i), data);
- }
- break;
-
case SYMBOL_REF:
h ^= htab_hash_string (XSTR (x, 0));
break;
case LABEL_REF:
- h = h * 251 + CODE_LABEL_NUMBER (XEXP (x, 0));
+ h = h * 251 + CODE_LABEL_NUMBER (LABEL_REF_LABEL (x));
break;
case UNSPEC:
break;
}
- hp = (hashval_t *) data;
- *hp = *hp * 509 + h;
- return 0;
+ return h;
}
/* Compute a hash value for X, which should be a constant. */
const_rtx_hash (rtx x)
{
hashval_t h = 0;
- for_each_rtx (&x, const_rtx_hash_1, &h);
+ subrtx_iterator::array_type array;
+ FOR_EACH_SUBRTX (iter, array, x, ALL)
+ h = h * 509 + const_rtx_hash_1 (*iter);
return h;
}
struct rtx_constant_pool *pool;
pool = ggc_alloc<rtx_constant_pool> ();
- pool->const_rtx_htab = htab_create_ggc (31, const_desc_rtx_hash,
- const_desc_rtx_eq, NULL);
+ pool->const_rtx_htab = hash_table<const_rtx_desc_hasher>::create_ggc (31);
pool->first = NULL;
pool->last = NULL;
pool->offset = 0;
and return a MEM rtx to refer to it in memory. */
rtx
-force_const_mem (enum machine_mode mode, rtx x)
+force_const_mem (machine_mode mode, rtx x)
{
struct constant_descriptor_rtx *desc, tmp;
struct rtx_constant_pool *pool;
rtx def, symbol;
hashval_t hash;
unsigned int align;
- void **slot;
+ constant_descriptor_rtx **slot;
/* If we're not allowed to drop X into the constant pool, don't. */
if (targetm.cannot_force_const_mem (mode, x))
tmp.constant = x;
tmp.mode = mode;
hash = const_rtx_hash (x);
- slot = htab_find_slot_with_hash (pool->const_rtx_htab, &tmp, hash, INSERT);
- desc = (struct constant_descriptor_rtx *) *slot;
+ slot = pool->const_rtx_htab->find_slot_with_hash (&tmp, hash, INSERT);
+ desc = *slot;
/* If the constant was already present, return its memory. */
if (desc)
/* Given a constant pool SYMBOL_REF, return the corresponding constant. */
rtx
-get_pool_constant (rtx addr)
+get_pool_constant (const_rtx addr)
{
return SYMBOL_REF_CONSTANT (addr)->constant;
}
/* Similar, return the mode. */
-enum machine_mode
+machine_mode
get_pool_mode (const_rtx addr)
{
return SYMBOL_REF_CONSTANT (addr)->mode;
in MODE with known alignment ALIGN. */
static void
-output_constant_pool_2 (enum machine_mode mode, rtx x, unsigned int align)
+output_constant_pool_2 (machine_mode mode, rtx x, unsigned int align)
{
switch (GET_MODE_CLASS (mode))
{
case MODE_UFRACT:
case MODE_ACCUM:
case MODE_UACCUM:
+ case MODE_POINTER_BOUNDS:
assemble_integer (x, GET_MODE_SIZE (mode), align, 1);
break;
case MODE_VECTOR_UACCUM:
{
int i, units;
- enum machine_mode submode = GET_MODE_INNER (mode);
+ machine_mode submode = GET_MODE_INNER (mode);
unsigned int subalign = MIN (align, GET_MODE_BITSIZE (submode));
gcc_assert (GET_CODE (x) == CONST_VECTOR);
CODE_LABEL into a NOTE. */
/* ??? This seems completely and utterly wrong. Certainly it's
not true for NOTE_INSN_DELETED_LABEL, but I disbelieve proper
- functioning even with INSN_DELETED_P and friends. */
+ functioning even with rtx_insn::deleted and friends. */
tmp = x;
switch (GET_CODE (tmp))
/* FALLTHRU */
case LABEL_REF:
- tmp = XEXP (tmp, 0);
- gcc_assert (!INSN_DELETED_P (tmp));
+ tmp = LABEL_REF_LABEL (tmp);
+ gcc_assert (!as_a<rtx_insn *> (tmp)->deleted ());
gcc_assert (!NOTE_P (tmp)
|| NOTE_KIND (tmp) != NOTE_INSN_DELETED);
break;
return;
}
-/* Given a SYMBOL_REF CURRENT_RTX, mark it and all constants it refers
- to as used. Emit referenced deferred strings. This function can
- be used with for_each_rtx to mark all SYMBOL_REFs in an rtx. */
+/* Mark all constants that are referenced by SYMBOL_REFs in X.
+ Emit referenced deferred strings. */
-static int
-mark_constant (rtx *current_rtx, void *data ATTRIBUTE_UNUSED)
+static void
+mark_constants_in_pattern (rtx insn)
{
- rtx x = *current_rtx;
-
- if (x == NULL_RTX || GET_CODE (x) != SYMBOL_REF)
- return 0;
-
- if (CONSTANT_POOL_ADDRESS_P (x))
- {
- struct constant_descriptor_rtx *desc = SYMBOL_REF_CONSTANT (x);
- if (desc->mark == 0)
- {
- desc->mark = 1;
- for_each_rtx (&desc->constant, mark_constant, NULL);
- }
- }
- else if (TREE_CONSTANT_POOL_ADDRESS_P (x))
+ subrtx_iterator::array_type array;
+ FOR_EACH_SUBRTX (iter, array, PATTERN (insn), ALL)
{
- tree decl = SYMBOL_REF_DECL (x);
- if (!TREE_ASM_WRITTEN (DECL_INITIAL (decl)))
+ const_rtx x = *iter;
+ if (GET_CODE (x) == SYMBOL_REF)
{
- n_deferred_constants--;
- output_constant_def_contents (x);
+ if (CONSTANT_POOL_ADDRESS_P (x))
+ {
+ struct constant_descriptor_rtx *desc = SYMBOL_REF_CONSTANT (x);
+ if (desc->mark == 0)
+ {
+ desc->mark = 1;
+ iter.substitute (desc->constant);
+ }
+ }
+ else if (TREE_CONSTANT_POOL_ADDRESS_P (x))
+ {
+ tree decl = SYMBOL_REF_DECL (x);
+ if (!TREE_ASM_WRITTEN (DECL_INITIAL (decl)))
+ {
+ n_deferred_constants--;
+ output_constant_def_contents (CONST_CAST_RTX (x));
+ }
+ }
}
}
-
- return -1;
}
/* Look through appropriate parts of INSN, marking all entries in the
/* Insns may appear inside a SEQUENCE. Only check the patterns of
insns, not any notes that may be attached. We don't want to mark
a constant just because it happens to appear in a REG_EQUIV note. */
- if (GET_CODE (PATTERN (insn)) == SEQUENCE)
+ if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (insn)))
{
- rtx seq = PATTERN (insn);
- int i, n = XVECLEN (seq, 0);
+ int i, n = seq->len ();
for (i = 0; i < n; ++i)
{
- rtx subinsn = XVECEXP (seq, 0, i);
+ rtx subinsn = seq->element (i);
if (INSN_P (subinsn))
- for_each_rtx (&PATTERN (subinsn), mark_constant, NULL);
+ mark_constants_in_pattern (subinsn);
}
}
else
- for_each_rtx (&PATTERN (insn), mark_constant, NULL);
+ mark_constants_in_pattern (insn);
}
/* Look through the instructions for this function, and mark all the
case REFERENCE_TYPE:
case OFFSET_TYPE:
case FIXED_POINT_TYPE:
+ case POINTER_BOUNDS_TYPE:
case NULLPTR_TYPE:
if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
EXPAND_INITIALIZER),
break;
case VECTOR_CST:
{
- enum machine_mode inner = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
+ machine_mode inner = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
unsigned int nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
int elt_size = GET_MODE_SIZE (inner);
output_constant (VECTOR_CST_ELT (exp, 0), elt_size, align);
static void
mark_weak (tree decl)
{
+ if (DECL_WEAK (decl))
+ return;
+
+ struct symtab_node *n = symtab_node::get (decl);
+ if (n && n->refuse_visibility_changes)
+ error ("%+D declared weak after being used", decl);
DECL_WEAK (decl) = 1;
if (DECL_RTL_SET_P (decl)
void
do_assemble_alias (tree decl, tree target)
{
+ tree id;
+
/* Emulated TLS had better not get this var. */
gcc_assert (!(!targetm.have_tls
&& TREE_CODE (decl) == VAR_DECL
if (TREE_ASM_WRITTEN (decl))
return;
+ id = DECL_ASSEMBLER_NAME (decl);
+ ultimate_transparent_alias_target (&id);
+
/* We must force creation of DECL_RTL for debug info generation, even though
we don't use it here. */
make_decl_rtl (decl);
TREE_ASM_WRITTEN (decl) = 1;
TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1;
+ TREE_ASM_WRITTEN (id) = 1;
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
{
#ifdef ASM_OUTPUT_WEAKREF
ASM_OUTPUT_WEAKREF (asm_out_file, decl,
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
+ IDENTIFIER_POINTER (id),
IDENTIFIER_POINTER (target));
#else
if (!TARGET_SUPPORTS_WEAK)
}
#ifdef ASM_OUTPUT_DEF
+ tree orig_decl = decl;
+
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && cgraph_node::get (decl)->instrumentation_clone
+ && cgraph_node::get (decl)->instrumented_version)
+ orig_decl = cgraph_node::get (decl)->instrumented_version->decl;
+
/* Make name accessible from other files, if appropriate. */
- if (TREE_PUBLIC (decl))
+ if (TREE_PUBLIC (decl) || TREE_PUBLIC (orig_decl))
{
globalize_decl (decl);
maybe_assemble_visibility (decl);
#if defined (ASM_OUTPUT_TYPE_DIRECTIVE)
if (targetm.has_ifunc_p ())
ASM_OUTPUT_TYPE_DIRECTIVE
- (asm_out_file, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
+ (asm_out_file, IDENTIFIER_POINTER (id),
IFUNC_ASM_TYPE);
else
#endif
ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, decl, target);
# else
ASM_OUTPUT_DEF (asm_out_file,
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
+ IDENTIFIER_POINTER (id),
IDENTIFIER_POINTER (target));
# endif
#elif defined (ASM_OUTPUT_WEAK_ALIAS) || defined (ASM_WEAKEN_DECL)
const char *name;
tree *p, t;
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ name = IDENTIFIER_POINTER (id);
# ifdef ASM_WEAKEN_DECL
ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target));
# else
/* Remove this function from the pending weak list so that
we do not emit multiple .weak directives for it. */
for (p = &weak_decls; (t = *p) ; )
- if (DECL_ASSEMBLER_NAME (decl) == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))
+ if (DECL_ASSEMBLER_NAME (decl) == DECL_ASSEMBLER_NAME (TREE_VALUE (t))
+ || id == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))
*p = TREE_CHAIN (t);
else
p = &TREE_CHAIN (t);
list, for the same reason. */
for (p = &weakref_targets; (t = *p) ; )
{
- if (DECL_ASSEMBLER_NAME (decl)
- == ultimate_transparent_alias_target (&TREE_VALUE (t)))
+ if (id == ultimate_transparent_alias_target (&TREE_VALUE (t)))
*p = TREE_CHAIN (t);
else
p = &TREE_CHAIN (t);
}
assemble_integer (XEXP (DECL_RTL (src), 0),
- POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+ POINTER_SIZE_UNITS, POINTER_SIZE, 1);
assemble_integer (XEXP (DECL_RTL (dst), 0),
- POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+ POINTER_SIZE_UNITS, POINTER_SIZE, 1);
}
}
{
enum symbol_visibility vis = DECL_VISIBILITY (decl);
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && cgraph_node::get (decl)
+ && cgraph_node::get (decl)->instrumentation_clone
+ && cgraph_node::get (decl)->instrumented_version)
+ vis = DECL_VISIBILITY (cgraph_node::get (decl)->instrumented_version->decl);
+
if (vis != VISIBILITY_DEFAULT)
{
targetm.asm_out.assemble_visibility (decl, vis);
void
init_varasm_once (void)
{
- section_htab = htab_create_ggc (31, section_entry_hash,
- section_entry_eq, NULL);
- object_block_htab = htab_create_ggc (31, object_block_entry_hash,
- object_block_entry_eq, NULL);
- const_desc_htab = htab_create_ggc (1009, const_desc_hash,
- const_desc_eq, NULL);
+ section_htab = hash_table<section_hasher>::create_ggc (31);
+ object_block_htab = hash_table<object_block_hasher>::create_ggc (31);
+ const_desc_htab = hash_table<tree_descriptor_hasher>::create_ggc (1009);
- const_alias_set = new_alias_set ();
shared_constant_pool = create_constant_pool ();
#ifdef TEXT_SECTION_ASM_OP
if (strcmp (name, ".bss") == 0
|| strncmp (name, ".bss.", 5) == 0
|| strncmp (name, ".gnu.linkonce.b.", 16) == 0
+ || strcmp (name, ".persistent.bss") == 0
|| strcmp (name, ".sbss") == 0
|| strncmp (name, ".sbss.", 6) == 0
|| strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
if (!(flags & SECTION_DEBUG))
*f++ = 'a';
+#if defined (HAVE_GAS_SECTION_EXCLUDE) && HAVE_GAS_SECTION_EXCLUDE == 1
if (flags & SECTION_EXCLUDE)
*f++ = 'e';
+#endif
if (flags & SECTION_WRITE)
*f++ = 'w';
if (flags & SECTION_CODE)
bool one_only = DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP;
const char *prefix, *name, *linkonce;
char *string;
+ tree id;
switch (categorize_decl_for_section (decl, reloc))
{
gcc_unreachable ();
}
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ id = DECL_ASSEMBLER_NAME (decl);
+ ultimate_transparent_alias_target (&id);
+ name = IDENTIFIER_POINTER (id);
name = targetm.strip_name_encoding (name);
/* If we're using one_only, then there needs to be a .gnu.linkonce
set_decl_section_name (decl, string);
}
-/* Like compute_reloc_for_constant, except for an RTX. The return value
- is a mask for which bit 1 indicates a global relocation, and bit 0
- indicates a local relocation. */
+/* Subroutine of compute_reloc_for_rtx for leaf rtxes. */
static int
-compute_reloc_for_rtx_1 (rtx *xp, void *data)
+compute_reloc_for_rtx_1 (const_rtx x)
{
- int *preloc = (int *) data;
- rtx x = *xp;
-
switch (GET_CODE (x))
{
case SYMBOL_REF:
- *preloc |= SYMBOL_REF_LOCAL_P (x) ? 1 : 2;
- break;
+ return SYMBOL_REF_LOCAL_P (x) ? 1 : 2;
case LABEL_REF:
- *preloc |= 1;
- break;
+ return 1;
default:
- break;
+ return 0;
}
-
- return 0;
}
+/* Like compute_reloc_for_constant, except for an RTX. The return value
+ is a mask for which bit 1 indicates a global relocation, and bit 0
+ indicates a local relocation. */
+
static int
-compute_reloc_for_rtx (rtx x)
+compute_reloc_for_rtx (const_rtx x)
{
- int reloc;
-
switch (GET_CODE (x))
{
- case CONST:
case SYMBOL_REF:
case LABEL_REF:
- reloc = 0;
- for_each_rtx (&x, compute_reloc_for_rtx_1, &reloc);
- return reloc;
+ return compute_reloc_for_rtx_1 (x);
+
+ case CONST:
+ {
+ int reloc = 0;
+ subrtx_iterator::array_type array;
+ FOR_EACH_SUBRTX (iter, array, x, ALL)
+ reloc |= compute_reloc_for_rtx_1 (*iter);
+ return reloc;
+ }
default:
return 0;
}
section *
-default_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED,
+default_select_rtx_section (machine_mode mode ATTRIBUTE_UNUSED,
rtx x,
unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
{
}
section *
-default_elf_select_rtx_section (enum machine_mode mode, rtx x,
+default_elf_select_rtx_section (machine_mode mode, rtx x,
unsigned HOST_WIDE_INT align)
{
int reloc = compute_reloc_for_rtx (x);
/* A htab_traverse callback used to call output_object_block for
each member of object_block_htab. */
-static int
-output_object_block_htab (void **slot, void *data ATTRIBUTE_UNUSED)
+int
+output_object_block_htab (object_block **slot, void *)
{
- output_object_block ((struct object_block *) (*slot));
+ output_object_block (*slot);
return 1;
}
void
output_object_blocks (void)
{
- htab_traverse (object_block_htab, output_object_block_htab, NULL);
+ object_block_htab->traverse<void *, output_object_block_htab> (NULL);
}
/* This function provides a possible implementation of the
make_debug_expr_from_rtl (const_rtx exp)
{
tree ddecl = make_node (DEBUG_EXPR_DECL), type;
- enum machine_mode mode = GET_MODE (exp);
+ machine_mode mode = GET_MODE (exp);
rtx dval;
DECL_ARTIFICIAL (ddecl) = 1;