Mercurial > hg > CbC > CbC_gcc
diff gcc/varasm.c @ 132:d34655255c78
update gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 10:21:07 +0900 |
parents | 84e7813d76e9 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/varasm.c Thu Oct 25 08:08:40 2018 +0900 +++ b/gcc/varasm.c Thu Oct 25 10:21:07 2018 +0900 @@ -1,5 +1,5 @@ /* Output variables, constants and external declarations, for GNU compiler. - Copyright (C) 1987-2017 Free Software Foundation, Inc. + Copyright (C) 1987-2018 Free Software Foundation, Inc. This file is part of GCC. @@ -55,6 +55,7 @@ #include "attribs.h" #include "asan.h" #include "rtl-iter.h" +#include "file-prefix-map.h" /* remap_debug_filename() */ #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data declarations. */ @@ -110,7 +111,7 @@ 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 @@ -224,7 +225,7 @@ { if (sect->common.flags & SECTION_NAMED) return htab_hash_string (sect->named.name); - return sect->common.flags; + return sect->common.flags & ~SECTION_DECLARED; } /* Helper routines for maintaining object_block_htab. */ @@ -295,6 +296,17 @@ 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) { @@ -793,7 +805,7 @@ && 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; @@ -811,6 +823,9 @@ 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); @@ -823,7 +838,7 @@ 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)); @@ -843,15 +858,14 @@ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED, unsigned int flags ATTRIBUTE_UNUSED) { - unsigned int modesize = GET_MODE_BITSIZE (mode); - if (HAVE_GAS_SHF_MERGE && flag_merge_constants && mode != VOIDmode && mode != BLKmode - && modesize <= align + && 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); @@ -984,11 +998,11 @@ /* Return true if DECL's initializer is suitable for a BSS section. */ bool -bss_initializer_p (const_tree decl) -{ - /* Do not put constants into the .bss section, they belong in a readonly - section. */ - return (!TREE_READONLY (decl) +bss_initializer_p (const_tree decl, bool named) +{ + /* Do not put non-common constants into the .bss section, they belong in + a readonly section, except when NAMED is true. */ + return ((!TREE_READONLY (decl) || DECL_COMMON (decl) || named) && (DECL_INITIAL (decl) == NULL /* In LTO we have no errors in program; error_mark_node is used to mark offlined constructors. */ @@ -1166,7 +1180,8 @@ { section *sect = get_named_section (decl, NULL, reloc); - if ((sect->common.flags & SECTION_BSS) && !bss_initializer_p (decl)) + if ((sect->common.flags & SECTION_BSS) + && !bss_initializer_p (decl, true)) { error_at (DECL_SOURCE_LOCATION (decl), "only zero initializers are allowed in section %qs", @@ -1253,10 +1268,9 @@ if (!VAR_P (decl) && TREE_CODE (decl) != CONST_DECL) return false; - /* Detect decls created by dw2_force_const_mem. Such decls are - special because DECL_INITIAL doesn't specify the decl's true value. - dw2_output_indirect_constants will instead call assemble_variable - with dont_output_data set to 1 and then print the contents itself. */ + /* DECL_INITIAL (decl) set to decl is a hack used for some decls that + are never used from code directly and we never want object block handling + for those. */ if (DECL_INITIAL (decl) == decl) return false; @@ -1367,10 +1381,6 @@ } 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 @@ -1795,21 +1805,25 @@ 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 } @@ -1822,10 +1836,7 @@ /* 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); @@ -2110,7 +2121,7 @@ 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 @@ -2133,7 +2144,7 @@ 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))); @@ -2309,7 +2320,9 @@ 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 @@ -2394,7 +2407,7 @@ 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; @@ -2872,35 +2885,39 @@ struct addr_const { rtx base; - HOST_WIDE_INT offset; + poly_int64 offset; }; static void decode_addr_const (tree exp, struct addr_const *value) { tree target = TREE_OPERAND (exp, 0); - int offset = 0; + poly_int64 offset = 0; rtx x; while (1) { + poly_int64 bytepos; if (TREE_CODE (target) == COMPONENT_REF - && tree_fits_shwi_p (byte_position (TREE_OPERAND (target, 1)))) + && poly_int_tree_p (byte_position (TREE_OPERAND (target, 1)), + &bytepos)) { - offset += int_byte_position (TREE_OPERAND (target, 1)); + offset += bytepos; target = TREE_OPERAND (target, 0); } else if (TREE_CODE (target) == ARRAY_REF || TREE_CODE (target) == ARRAY_RANGE_REF) { - offset += (tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (target))) - * tree_to_shwi (TREE_OPERAND (target, 1))); + /* Truncate big offset. */ + offset + += (TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (target))) + * wi::to_poly_widest (TREE_OPERAND (target, 1)).force_shwi ()); target = TREE_OPERAND (target, 0); } else if (TREE_CODE (target) == MEM_REF && TREE_CODE (TREE_OPERAND (target, 0)) == ADDR_EXPR) { - offset += mem_ref_offset (target).to_short_addr (); + offset += mem_ref_offset (target).force_shwi (); target = TREE_OPERAND (TREE_OPERAND (target, 0), 0); } else if (TREE_CODE (target) == INDIRECT_REF @@ -2940,6 +2957,11 @@ 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 (); } @@ -3006,13 +3028,11 @@ case VECTOR_CST: { - unsigned i; - - hi = 7 + VECTOR_CST_NELTS (exp); - - for (i = 0; i < VECTOR_CST_NELTS (exp); ++i) - hi = hi * 563 + const_hash_1 (VECTOR_CST_ELT (exp, i)); - + hi = 7 + VECTOR_CST_NPATTERNS (exp); + hi = hi * 563 + VECTOR_CST_NELTS_PER_PATTERN (exp); + unsigned int count = vector_cst_encoded_nelts (exp); + for (unsigned int i = 0; i < count; ++i) + hi = hi * 563 + const_hash_1 (VECTOR_CST_ENCODED_ELT (exp, i)); return hi; } @@ -3031,6 +3051,10 @@ } 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; @@ -3041,14 +3065,14 @@ case SYMBOL_REF: /* Don't hash the address of the SYMBOL_REF; only use the offset and the symbol name. */ - hi = value.offset; + hi = value.offset.coeffs[0]; p = XSTR (value.base, 0); for (i = 0; p[i] != 0; i++) hi = ((hi * 613) + (unsigned) (p[i])); break; case LABEL_REF: - hi = (value.offset + hi = (value.offset.coeffs[0] + CODE_LABEL_NUMBER (label_ref_label (value.base)) * 13); break; @@ -3117,10 +3141,16 @@ return tree_int_cst_equal (t1, t2); case REAL_CST: - /* Real constants are the same only if the same width of type. */ + /* Real constants are the same only if the same width of type. In + addition to the same width, we need to check whether the modes are the + same. There might be two floating point modes that are the same size + but have different representations, such as the PowerPC that has 2 + different 128-bit floating point types (IBM extended double and IEEE + 128-bit floating point). */ if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2))) return 0; - + if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))) + return 0; return real_identical (&TREE_REAL_CST (t1), &TREE_REAL_CST (t2)); case FIXED_CST: @@ -3131,7 +3161,9 @@ 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) @@ -3144,14 +3176,18 @@ case VECTOR_CST: { - unsigned i; - - if (VECTOR_CST_NELTS (t1) != VECTOR_CST_NELTS (t2)) + if (VECTOR_CST_NPATTERNS (t1) + != VECTOR_CST_NPATTERNS (t2)) return 0; - for (i = 0; i < VECTOR_CST_NELTS (t1); ++i) - if (!compare_constant (VECTOR_CST_ELT (t1, i), - VECTOR_CST_ELT (t2, i))) + if (VECTOR_CST_NELTS_PER_PATTERN (t1) + != VECTOR_CST_NELTS_PER_PATTERN (t2)) + return 0; + + unsigned int count = vector_cst_encoded_nelts (t1); + for (unsigned int i = 0; i < count; ++i) + if (!compare_constant (VECTOR_CST_ENCODED_ELT (t1, i), + VECTOR_CST_ENCODED_ELT (t2, i))) return 0; return 1; @@ -3224,7 +3260,7 @@ decode_addr_const (t1, &value1); decode_addr_const (t2, &value2); - if (value1.offset != value2.offset) + if (maybe_ne (value1.offset, value2.offset)) return 0; code = GET_CODE (value1.base); @@ -3284,8 +3320,9 @@ 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; } @@ -3449,7 +3486,8 @@ 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; @@ -3459,7 +3497,7 @@ 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 (); } @@ -3500,10 +3538,13 @@ || (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); @@ -3566,7 +3607,7 @@ rtx constant; HOST_WIDE_INT offset; hashval_t hash; - machine_mode mode; + fixed_size_mode mode; unsigned int align; int labelno; int mark; @@ -3742,10 +3783,11 @@ } /* Given a constant rtx X, make (or find) a memory constant for its value - and return a MEM rtx to refer to it in memory. */ + and return a MEM rtx to refer to it in memory. IN_MODE is the mode + of X. */ rtx -force_const_mem (machine_mode mode, rtx x) +force_const_mem (machine_mode in_mode, rtx x) { struct constant_descriptor_rtx *desc, tmp; struct rtx_constant_pool *pool; @@ -3754,6 +3796,11 @@ hashval_t hash; unsigned int align; constant_descriptor_rtx **slot; + fixed_size_mode mode; + + /* We can't force variable-sized objects to memory. */ + if (!is_a <fixed_size_mode> (in_mode, &mode)) + return NULL_RTX; /* If we're not allowed to drop X into the constant pool, don't. */ if (targetm.cannot_force_const_mem (mode, x)) @@ -3859,7 +3906,7 @@ /* Similar, return the mode. */ -machine_mode +fixed_size_mode get_pool_mode (const_rtx addr) { return SYMBOL_REF_CONSTANT (addr)->mode; @@ -3879,7 +3926,7 @@ in MODE with known alignment ALIGN. */ static void -output_constant_pool_2 (machine_mode mode, rtx x, unsigned int align) +output_constant_pool_2 (fixed_size_mode mode, rtx x, unsigned int align) { switch (GET_MODE_CLASS (mode)) { @@ -3898,10 +3945,35 @@ 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_BOOL: + { + gcc_assert (GET_CODE (x) == CONST_VECTOR); + + /* Pick the smallest integer mode that contains at least one + whole element. Often this is byte_mode and contains more + than one element. */ + unsigned int nelts = GET_MODE_NUNITS (mode); + unsigned int elt_bits = GET_MODE_BITSIZE (mode) / nelts; + unsigned int int_bits = MAX (elt_bits, BITS_PER_UNIT); + scalar_int_mode int_mode = int_mode_for_size (int_bits, 0).require (); + + /* Build the constant up one integer at a time. */ + unsigned int elts_per_int = int_bits / elt_bits; + for (unsigned int i = 0; i < nelts; i += elts_per_int) + { + unsigned HOST_WIDE_INT value = 0; + unsigned int limit = MIN (nelts - i, elts_per_int); + for (unsigned int j = 0; j < limit; ++j) + if (INTVAL (CONST_VECTOR_ELT (x, i + j)) != 0) + value |= 1 << (j * elt_bits); + output_constant_pool_2 (int_mode, gen_int_mode (value, int_mode), + i != 0 ? MIN (align, int_bits) : align); + } + break; + } case MODE_VECTOR_FLOAT: case MODE_VECTOR_INT: case MODE_VECTOR_FRACT: @@ -3914,7 +3986,7 @@ unsigned int subalign = MIN (align, GET_MODE_BITSIZE (submode)); gcc_assert (GET_CODE (x) == CONST_VECTOR); - units = CONST_VECTOR_NUNITS (x); + units = GET_MODE_NUNITS (mode); for (i = 0; i < units; i++) { @@ -4608,6 +4680,7 @@ } return ret; + case POINTER_DIFF_EXPR: case MINUS_EXPR: if (TREE_CODE (endtype) == REAL_TYPE) return NULL_TREE; @@ -4722,6 +4795,30 @@ 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. */ @@ -4760,7 +4857,7 @@ 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; @@ -4857,7 +4954,6 @@ 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) @@ -4876,10 +4972,11 @@ 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: @@ -4889,8 +4986,12 @@ 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: @@ -4899,12 +5000,14 @@ 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; - for (unsigned int i = 1; i < VECTOR_CST_NELTS (exp); i++) + /* 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; @@ -5025,8 +5128,8 @@ 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; @@ -5108,6 +5211,8 @@ 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)); @@ -5119,8 +5224,8 @@ 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; @@ -5595,7 +5700,8 @@ 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; @@ -5763,11 +5869,6 @@ #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)) @@ -5775,7 +5876,8 @@ 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 ()) @@ -5858,7 +5960,9 @@ # 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 @@ -6089,13 +6193,6 @@ 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); @@ -6314,15 +6411,23 @@ || 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; @@ -6381,7 +6486,7 @@ { 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 @@ -6408,6 +6513,10 @@ 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; @@ -6516,6 +6625,7 @@ } else if (VAR_P (decl)) { + tree d = CONST_CAST_TREE (decl); if (bss_initializer_p (decl)) ret = SECCAT_BSS; else if (! TREE_READONLY (decl) @@ -6536,7 +6646,17 @@ ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO; else if (reloc || flag_merge_constants < 2 || ((flag_sanitize & SANITIZE_ADDRESS) - && asan_protect_global (CONST_CAST_TREE (decl)))) + /* PR 81697: for architectures that use section anchors we + need to ignore DECL_RTL_SET_P (decl) for string constants + inside this asan_protect_global call because otherwise + we'll wrongly put them into SECCAT_RODATA_MERGE_CONST + section, set DECL_RTL (decl) later on and add DECL to + protected globals via successive asan_protect_global + calls. In this scenario we'll end up with wrong + alignment of these strings at runtime and possible ASan + false positives. */ + && asan_protect_global (d, use_object_blocks_p () + && use_blocks_for_decl_p (d)))) /* C and C++ don't allow different variables to share the same location. -fmerge-all-constants allows even that (at the expense of not conforming). */ @@ -6967,7 +7087,8 @@ 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. */ @@ -7520,8 +7641,8 @@ { 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; @@ -7538,7 +7659,7 @@ { 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)