/* Output variables, constants and external declarations, for GNU compiler.
- Copyright (C) 1987-2018 Free Software Foundation, Inc.
+ Copyright (C) 1987-2019 Free Software Foundation, Inc.
This file is part of GCC.
static void output_constant_def_contents (rtx);
static void output_addressed_constants (tree);
static unsigned HOST_WIDE_INT output_constant (tree, unsigned HOST_WIDE_INT,
- unsigned int, bool);
+ unsigned int, bool, bool);
static void globalize_decl (tree);
static bool decl_readonly_section_1 (enum section_category);
#ifdef BSS_SECTION_ASM_OP
else
{
sect = *slot;
+ /* It is fine if one of the sections has SECTION_NOTYPE as long as
+ the other has none of the contrary flags (see the logic at the end
+ of default_section_type_flags, below). */
+ if (((sect->common.flags ^ flags) & SECTION_NOTYPE)
+ && !((sect->common.flags | flags)
+ & (SECTION_CODE | SECTION_BSS | SECTION_TLS | SECTION_ENTSIZE
+ | (HAVE_COMDAT_GROUP ? SECTION_LINKONCE : 0))))
+ {
+ sect->common.flags |= SECTION_NOTYPE;
+ flags |= SECTION_NOTYPE;
+ }
if ((sect->common.flags & ~SECTION_DECLARED) != flags
&& ((sect->common.flags | flags) & SECTION_OVERRIDE) == 0)
{
/* Return the object_block structure for section SECT. Create a new
structure if we haven't created one already. Return null if SECT
- itself is null. */
+ itself is null. Return also null for mergeable sections since
+ section anchors can't be used in mergeable sections anyway,
+ because the linker might move objects around, and using the
+ object blocks infrastructure in that case is both a waste and a
+ maintenance burden. */
static struct object_block *
get_block_for_section (section *sect)
if (sect == NULL)
return NULL;
+ if (sect->common.flags & SECTION_MERGE)
+ return NULL;
+
object_block **slot
= object_block_htab->find_slot_with_hash (sect, hash_section (sect),
INSERT);
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
&& align <= 256
&& (len = int_size_in_bytes (TREE_TYPE (decl))) > 0
- && TREE_STRING_LENGTH (decl) >= len)
+ && TREE_STRING_LENGTH (decl) == len)
{
scalar_int_mode mode;
unsigned int modesize;
if (align < modesize)
align = modesize;
+ if (!HAVE_LD_ALIGNED_SHF_MERGE && align > 8)
+ return readonly_data_section;
+
str = TREE_STRING_POINTER (decl);
unit = GET_MODE_SIZE (mode);
if (j == unit)
break;
}
- if (i == len - unit)
+ if (i == len - unit || (unit == 1 && i == len))
{
sprintf (name, "%s.str%d.%d", prefix,
modesize / 8, (int) (align / 8));
&& known_le (GET_MODE_BITSIZE (mode), align)
&& align >= 8
&& align <= 256
- && (align & (align - 1)) == 0)
+ && (align & (align - 1)) == 0
+ && (HAVE_LD_ALIGNED_SHF_MERGE ? 1 : align == 8))
{
const char *prefix = function_mergeable_rodata_prefix ();
char *name = (char *) alloca (strlen (prefix) + 30);
}
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
Note that we still need to align to DECL_ALIGN, as above,
because ASM_OUTPUT_MAX_SKIP_ALIGN might not do any alignment at all. */
if (! DECL_USER_ALIGN (decl)
- && align_functions_log > align
+ && align_functions.levels[0].log > align
&& optimize_function_for_speed_p (cfun))
{
#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
- int align_log = align_functions_log;
+ int align_log = align_functions.levels[0].log;
#endif
- int max_skip = align_functions - 1;
+ int max_skip = align_functions.levels[0].maxskip;
if (flag_limit_function_alignment && crtl->max_insn_address > 0
&& max_skip >= crtl->max_insn_address)
max_skip = crtl->max_insn_address - 1;
#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, align_log, max_skip);
+ if (max_skip == align_functions.levels[0].maxskip)
+ ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file,
+ align_functions.levels[1].log,
+ align_functions.levels[1].maxskip);
#else
- ASM_OUTPUT_ALIGN (asm_out_file, align_functions_log);
+ ASM_OUTPUT_ALIGN (asm_out_file, align_functions.levels[0].log);
#endif
}
/* Make function name accessible from other files, if appropriate. */
- 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)))
+ if (TREE_PUBLIC (decl))
{
notice_global_symbol (decl);
tree pp_val = TREE_VALUE (patchable_function_entry_attr);
tree patchable_function_entry_value1 = TREE_VALUE (pp_val);
- if (tree_fits_uhwi_p (patchable_function_entry_value1))
- patch_area_size = tree_to_uhwi (patchable_function_entry_value1);
- else
- gcc_unreachable ();
-
+ patch_area_size = tree_to_uhwi (patchable_function_entry_value1);
patch_area_entry = 0;
- if (list_length (pp_val) > 1)
+ if (TREE_CHAIN (pp_val) != NULL_TREE)
{
- tree patchable_function_entry_value2 =
- TREE_VALUE (TREE_CHAIN (pp_val));
-
- if (tree_fits_uhwi_p (patchable_function_entry_value2))
- patch_area_entry = tree_to_uhwi (patchable_function_entry_value2);
- else
- gcc_unreachable ();
+ tree patchable_function_entry_value2
+ = TREE_VALUE (TREE_CHAIN (pp_val));
+ patch_area_entry = tree_to_uhwi (patchable_function_entry_value2);
}
}
if (patch_area_entry > patch_area_size)
{
if (patch_area_size > 0)
- warning (OPT_Wattributes, "Patchable function entry > size");
+ warning (OPT_Wattributes, "patchable function entry > size");
patch_area_entry = 0;
}
/* And the area after the label. Record it if we haven't done so yet. */
if (patch_area_size > patch_area_entry)
targetm.asm_out.print_patchable_function_entry (asm_out_file,
- patch_area_size-patch_area_entry,
+ patch_area_size
+ - patch_area_entry,
patch_area_entry == 0);
if (lookup_attribute ("no_split_stack", DECL_ATTRIBUTES (decl)))
/* Assemble an alignment pseudo op for an ALIGN-bit boundary. */
void
-assemble_align (int align)
+assemble_align (unsigned int align)
{
if (align > BITS_PER_UNIT)
{
static void
assemble_variable_contents (tree decl, const char *name,
- bool dont_output_data)
+ bool dont_output_data, bool merge_strings)
{
/* Do any machine/system dependent processing of the object. */
#ifdef ASM_DECLARE_OBJECT_NAME
output_constant (DECL_INITIAL (decl),
tree_to_uhwi (DECL_SIZE_UNIT (decl)),
get_variable_align (decl),
- false);
+ false, merge_strings);
else
/* Leave space for it. */
assemble_zeros (tree_to_uhwi (DECL_SIZE_UNIT (decl)));
switch_to_section (sect);
if (align > BITS_PER_UNIT)
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
- assemble_variable_contents (decl, name, dont_output_data);
+ assemble_variable_contents (decl, name, dont_output_data,
+ (sect->common.flags & SECTION_MERGE)
+ && (sect->common.flags & SECTION_STRINGS));
if (asan_protected)
{
unsigned HOST_WIDE_INT int size
static bool
incorporeal_function_p (tree decl)
{
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
+ if (TREE_CODE (decl) == FUNCTION_DECL && fndecl_built_in_p (decl))
{
const char *name;
return targetm.asm_out.byte_op;
case 2:
return ops->hi;
+ case 3:
+ return ops->psi;
case 4:
return ops->si;
+ case 5:
+ case 6:
+ case 7:
+ return ops->pdi;
case 8:
return ops->di;
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ return ops->pti;
case 16:
return ops->ti;
default:
case COMPLEX_CST:
case CONSTRUCTOR:
case INTEGER_CST:
- x = output_constant_def (target, 1);
+ x = lookup_constant_def (target);
+ /* Should have been added by output_addressed_constants. */
+ gcc_assert (x);
break;
case INDIRECT_REF:
gen_rtx_SYMBOL_REF (Pmode, "origin of addresses"));
break;
+ case COMPOUND_LITERAL_EXPR:
+ gcc_assert (COMPOUND_LITERAL_EXPR_DECL (target));
+ x = DECL_RTL (COMPOUND_LITERAL_EXPR_DECL (target));
+ break;
+
default:
gcc_unreachable ();
}
}
case ADDR_EXPR:
+ if (CONSTANT_CLASS_P (TREE_OPERAND (exp, 0)))
+ return const_hash_1 (TREE_OPERAND (exp, 0));
+
+ /* Fallthru. */
case FDESC_EXPR:
{
struct addr_const value;
return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1), TREE_FIXED_CST (t2));
case STRING_CST:
- if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
+ if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))
+ || int_size_in_bytes (TREE_TYPE (t1))
+ != int_size_in_bytes (TREE_TYPE (t2)))
return 0;
return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
HOST_WIDE_INT size;
size = int_size_in_bytes (TREE_TYPE (exp));
- if (TREE_CODE (exp) == STRING_CST)
- size = MAX (TREE_STRING_LENGTH (exp), size);
+ gcc_checking_assert (size >= 0);
+ gcc_checking_assert (TREE_CODE (exp) != STRING_CST
+ || size >= TREE_STRING_LENGTH (exp));
return size;
}
return desc;
}
+/* Subroutine of output_constant_def and tree_output_constant_def:
+ Add a constant to the hash table that tracks which constants
+ already have labels. */
+
+static constant_descriptor_tree *
+add_constant_to_table (tree exp)
+{
+ /* The hash table methods may call output_constant_def for addressed
+ constants, so handle them first. */
+ output_addressed_constants (exp);
+
+ /* Sanity check to catch recursive insertion. */
+ static bool inserting;
+ gcc_assert (!inserting);
+ inserting = true;
+
+ /* Look up EXP in the table of constant descriptors. If we didn't
+ find it, create a new one. */
+ struct constant_descriptor_tree key;
+ key.value = exp;
+ key.hash = const_hash_1 (exp);
+ constant_descriptor_tree **loc
+ = const_desc_htab->find_slot_with_hash (&key, key.hash, INSERT);
+
+ inserting = false;
+
+ struct constant_descriptor_tree *desc = *loc;
+ if (!desc)
+ {
+ desc = build_constant_desc (exp);
+ desc->hash = key.hash;
+ *loc = desc;
+ }
+
+ return desc;
+}
+
/* Return an rtx representing a reference to constant data in memory
for the constant expression EXP.
rtx
output_constant_def (tree exp, int defer)
{
- struct constant_descriptor_tree *desc;
- struct constant_descriptor_tree key;
-
- /* 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);
- constant_descriptor_tree **loc
- = const_desc_htab->find_slot_with_hash (&key, key.hash, INSERT);
-
- desc = *loc;
- if (desc == 0)
- {
- desc = build_constant_desc (exp);
- desc->hash = key.hash;
- *loc = desc;
- }
-
+ struct constant_descriptor_tree *desc = add_constant_to_table (exp);
maybe_output_constant_def_contents (desc, defer);
return desc->rtl;
}
constant's alignment in bits. */
static void
-assemble_constant_contents (tree exp, const char *label, unsigned int align)
+assemble_constant_contents (tree exp, const char *label, unsigned int align,
+ bool merge_strings)
{
HOST_WIDE_INT size;
targetm.asm_out.declare_constant_name (asm_out_file, label, exp, size);
/* Output the value of EXP. */
- output_constant (exp, size, align, false);
+ output_constant (exp, size, align, false, merge_strings);
targetm.asm_out.decl_end ();
}
|| (VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl))
? DECL_ALIGN (decl)
: symtab_node::get (decl)->definition_alignment ());
- switch_to_section (get_constant_section (exp, align));
+ section *sect = get_constant_section (exp, align);
+ switch_to_section (sect);
if (align > BITS_PER_UNIT)
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
- assemble_constant_contents (exp, XSTR (symbol, 0), align);
+ assemble_constant_contents (exp, XSTR (symbol, 0), align,
+ (sect->common.flags & SECTION_MERGE)
+ && (sect->common.flags & SECTION_STRINGS));
if (asan_protected)
{
HOST_WIDE_INT size = get_constant_size (exp);
tree
tree_output_constant_def (tree exp)
{
- struct constant_descriptor_tree *desc, key;
- 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);
- constant_descriptor_tree **loc
- = const_desc_htab->find_slot_with_hash (&key, key.hash, INSERT);
-
- desc = *loc;
- if (desc == 0)
- {
- desc = build_constant_desc (exp);
- desc->hash = key.hash;
- *loc = desc;
- }
-
- decl = SYMBOL_REF_DECL (XEXP (desc->rtl, 0));
+ struct constant_descriptor_tree *desc = add_constant_to_table (exp);
+ tree decl = SYMBOL_REF_DECL (XEXP (desc->rtl, 0));
varpool_node::finalize_decl (decl);
return decl;
}
case MODE_UFRACT:
case MODE_ACCUM:
case MODE_UACCUM:
- case MODE_POINTER_BOUNDS:
assemble_integer (x, GET_MODE_SIZE (mode), align, 1);
break;
return false;
}
+/* Check if a STRING_CST fits into the field.
+ Tolerate only the case when the NUL termination
+ does not fit into the field. */
+
+static bool
+check_string_literal (tree string, unsigned HOST_WIDE_INT size)
+{
+ tree type = TREE_TYPE (string);
+ tree eltype = TREE_TYPE (type);
+ unsigned HOST_WIDE_INT elts = tree_to_uhwi (TYPE_SIZE_UNIT (eltype));
+ unsigned HOST_WIDE_INT mem_size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+ int len = TREE_STRING_LENGTH (string);
+
+ if (elts != 1 && elts != 2 && elts != 4)
+ return false;
+ if (len < 0 || len % elts != 0)
+ return false;
+ if (size < (unsigned)len)
+ return false;
+ if (mem_size != size)
+ return false;
+ return true;
+}
+
/* output_constructor outer state of relevance in recursive calls, typically
for nested aggregate bitfields. */
static unsigned HOST_WIDE_INT
output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
- bool reverse)
+ bool reverse, bool merge_strings)
{
enum tree_code code;
unsigned HOST_WIDE_INT thissize;
case REFERENCE_TYPE:
case OFFSET_TYPE:
case FIXED_POINT_TYPE:
- case POINTER_BOUNDS_TYPE:
case NULLPTR_TYPE:
cst = expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
if (reverse)
break;
case COMPLEX_TYPE:
- output_constant (TREE_REALPART (exp), thissize / 2, align, reverse);
+ output_constant (TREE_REALPART (exp), thissize / 2, align,
+ reverse, false);
output_constant (TREE_IMAGPART (exp), thissize / 2,
min_align (align, BITS_PER_UNIT * (thissize / 2)),
- reverse);
+ reverse, false);
break;
case ARRAY_TYPE:
case CONSTRUCTOR:
return output_constructor (exp, size, align, reverse, NULL);
case STRING_CST:
- thissize
- = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp), size);
+ thissize = (unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp);
+ if (merge_strings
+ && (thissize == 0
+ || TREE_STRING_POINTER (exp) [thissize - 1] != '\0'))
+ thissize++;
+ gcc_checking_assert (check_string_literal (exp, size));
assemble_string (TREE_STRING_POINTER (exp), thissize);
break;
case VECTOR_CST:
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,
- reverse);
+ reverse, false);
thissize = elt_size;
/* Static constants must have a fixed size. */
unsigned int nunits = VECTOR_CST_NELTS (exp).to_constant ();
for (unsigned int i = 1; i < nunits; i++)
{
output_constant (VECTOR_CST_ELT (exp, i), elt_size, nalign,
- reverse);
+ reverse, false);
thissize += elt_size;
}
break;
if (local->val == NULL_TREE)
assemble_zeros (fieldsize);
else
- fieldsize
- = output_constant (local->val, fieldsize, align2, local->reverse);
+ fieldsize = output_constant (local->val, fieldsize, align2,
+ local->reverse, false);
/* Count its size. */
local->total_bytes += fieldsize;
on the chain is a TYPE_DECL of the enclosing struct. */
const_tree next = DECL_CHAIN (local->field);
gcc_assert (!fieldsize || !next || TREE_CODE (next) != FIELD_DECL);
+ tree size = TYPE_SIZE_UNIT (TREE_TYPE (local->val));
+ gcc_checking_assert (compare_tree_int (size, fieldsize) == 0);
}
else
fieldsize = tree_to_uhwi (DECL_SIZE_UNIT (local->field));
if (local->val == NULL_TREE)
assemble_zeros (fieldsize);
else
- fieldsize
- = output_constant (local->val, fieldsize, align2, local->reverse);
+ fieldsize = output_constant (local->val, fieldsize, align2,
+ local->reverse, false);
/* Count its size. */
local->total_bytes += fieldsize;
{
int this_time;
int shift;
- HOST_WIDE_INT value;
+ unsigned HOST_WIDE_INT value;
HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
this_time = end - shift + 1;
}
- /* Now get the bits from the appropriate constant word. */
- value = TREE_INT_CST_ELT (local->val, shift / HOST_BITS_PER_WIDE_INT);
- shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
+ /* Now get the bits we want to insert. */
+ value = wi::extract_uhwi (wi::to_widest (local->val),
+ shift, this_time);
/* Get the result. This works only when:
1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
- local->byte |= (((value >> shift)
- & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
- << (BITS_PER_UNIT - this_time - next_bit));
+ local->byte |= value << (BITS_PER_UNIT - this_time - next_bit);
}
else
{
this_time
= HOST_BITS_PER_WIDE_INT - (shift & (HOST_BITS_PER_WIDE_INT - 1));
- /* Now get the bits from the appropriate constant word. */
- value = TREE_INT_CST_ELT (local->val, shift / HOST_BITS_PER_WIDE_INT);
- shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
+ /* Now get the bits we want to insert. */
+ value = wi::extract_uhwi (wi::to_widest (local->val),
+ shift, this_time);
/* Get the result. This works only when:
1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
- local->byte |= (((value >> shift)
- & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
- << next_bit);
+ local->byte |= value << next_bit;
}
next_offset += this_time;
tree alias_decl = TREE_PURPOSE (t);
tree target = ultimate_transparent_alias_target (&TREE_VALUE (t));
- if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias_decl)))
+ if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias_decl))
+ || TREE_SYMBOL_REFERENCED (target))
/* Remove alias_decl from the weak list, but leave entries for
the target alone. */
target = NULL_TREE;
#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) || TREE_PUBLIC (orig_decl))
globalize_decl (decl);
maybe_assemble_visibility (decl);
}
- if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && cgraph_node::get (decl)->ifunc_resolver)
{
#if defined (ASM_OUTPUT_TYPE_DIRECTIVE)
if (targetm.has_ifunc_p ())
# else
if (!DECL_WEAK (decl))
{
- if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
+ /* NB: ifunc_resolver isn't set when an error is detected. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
error_at (DECL_SOURCE_LOCATION (decl),
"ifunc is not supported in this configuration");
else
maybe_assemble_visibility (tree decl)
{
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);
|| strncmp (name, ".gnu.linkonce.tb.", 17) == 0)
flags |= SECTION_TLS | SECTION_BSS;
- /* These three sections have special ELF types. They are neither
- SHT_PROGBITS nor SHT_NOBITS, so when changing sections we don't
- want to print a section type (@progbits or @nobits). If someone
- is silly enough to emit code or TLS variables to one of these
- sections, then don't handle them specially. */
- if (!(flags & (SECTION_CODE | SECTION_BSS | SECTION_TLS))
- && (strcmp (name, ".init_array") == 0
- || strcmp (name, ".fini_array") == 0
- || strcmp (name, ".preinit_array") == 0))
+ /* Various sections have special ELF types that the assembler will
+ assign by default based on the name. They are neither SHT_PROGBITS
+ nor SHT_NOBITS, so when changing sections we don't want to print a
+ section type (@progbits or @nobits). Rather than duplicating the
+ assembler's knowledge of what those special name patterns are, just
+ let the assembler choose the type if we don't know a specific
+ reason to set it to something other than the default. SHT_PROGBITS
+ is the default for sections whose name is not specially known to
+ the assembler, so it does no harm to leave the choice to the
+ assembler when @progbits is the best thing we know to use. If
+ someone is silly enough to emit code or TLS variables to one of
+ these sections, then don't handle them specially.
+
+ default_elf_asm_named_section (below) handles the BSS, TLS, ENTSIZE, and
+ LINKONCE cases when NOTYPE is not set, so leave those to its logic. */
+ if (!(flags & (SECTION_CODE | SECTION_BSS | SECTION_TLS | SECTION_ENTSIZE))
+ && !(HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE)))
flags |= SECTION_NOTYPE;
return flags;
{
if (!(flags & SECTION_DEBUG))
*f++ = 'a';
-#if defined (HAVE_GAS_SECTION_EXCLUDE) && HAVE_GAS_SECTION_EXCLUDE == 1
+#if HAVE_GAS_SECTION_EXCLUDE
if (flags & SECTION_EXCLUDE)
*f++ = 'e';
#endif
fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
+ /* default_section_type_flags (above) knows which flags need special
+ handling here, and sets NOTYPE when none of these apply so that the
+ assembler's logic for default types can apply to user-chosen
+ section names. */
if (!(flags & SECTION_NOTYPE))
{
const char *type;
bool
default_use_anchors_for_symbol_p (const_rtx symbol)
{
- section *sect;
tree decl;
+ section *sect = SYMBOL_REF_BLOCK (symbol)->sect;
- /* Don't use anchors for mergeable sections. The linker might move
- the objects around. */
- sect = SYMBOL_REF_BLOCK (symbol)->sect;
- if (sect->common.flags & SECTION_MERGE)
- return false;
+ /* This function should only be called with non-zero SYMBOL_REF_BLOCK,
+ furthermore get_block_for_section should not create object blocks
+ for mergeable sections. */
+ gcc_checking_assert (sect && !(sect->common.flags & SECTION_MERGE));
/* Don't use anchors for small data sections. The small data register
acts as an anchor for such sections. */
weakref alias. */
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
|| (TREE_CODE (exp) == FUNCTION_DECL
- && lookup_attribute ("ifunc", DECL_ATTRIBUTES (exp))))
+ && cgraph_node::get (exp)
+ && cgraph_node::get (exp)->ifunc_resolver))
return false;
/* Static variables are always local. */
else
switch_to_section (block->sect);
+ gcc_checking_assert (!(block->sect->common.flags & SECTION_MERGE));
assemble_align (block->alignment);
/* Define the values of all anchors relative to the current section
{
HOST_WIDE_INT size;
decl = SYMBOL_REF_DECL (symbol);
- assemble_constant_contents
- (DECL_INITIAL (decl), XSTR (symbol, 0), DECL_ALIGN (decl));
+ assemble_constant_contents (DECL_INITIAL (decl), XSTR (symbol, 0),
+ DECL_ALIGN (decl), false);
size = get_constant_size (DECL_INITIAL (decl));
offset += size;
{
HOST_WIDE_INT size;
decl = SYMBOL_REF_DECL (symbol);
- assemble_variable_contents (decl, XSTR (symbol, 0), false);
+ assemble_variable_contents (decl, XSTR (symbol, 0), false, false);
size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
offset += size;
if ((flag_sanitize & SANITIZE_ADDRESS)