Variables with the "noinit" attribute are ignored at -O0 because they are treated like a regular .bss variable and placed in the .bss section.
With -fdata-sections they are ignored because they are not handled in resolve_unique_section. Successfully bootstrapped/regtested x86_64-pc-linux-gnu and regtested for arm-none-eabi. Ok for trunk?
>From 965de1985a21ef449d1b1477be566efcf3405f7e Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz <joze...@mittosystems.com> Date: Mon, 26 Oct 2020 14:11:08 +0000 Subject: [PATCH 1/2] Fix "noinit" attribute being ignored for -O0 and -fdata-sections Variables with the "noinit" attribute are ignored at -O0 because they are treated like a regular .bss variable and placed in the .bss section. With -fdata-sections they are ignored because they are not handled in resolve_unique_section. gcc/c-family/ChangeLog: * c-attribs.c (handle_noinit_attribute): Set DECL_NOINIT_P. gcc/ChangeLog: * cgraph.h (symtab_node): Add noinit flag. * cgraphunit.c (process_function_and_variable_attributes): Set noinit flag of varpool node for DECL_NOINIT_P decls. * lto-cgraph.c (lto_output_varpool_node): Pack noinit flag value. (input_varpool_node): Unpack noinit flag value. * tree-core.h (struct tree_decl_common): Add noinit_flag. * tree.h (DECL_NOINIT_P): Define DECL_NOINIT_P. * varasm.c (get_variable_section): Set DECL_NOINIT_P from varpool node noinit flag. (default_elf_select_section): Check DECL_NOINIT_P instead of looking up attribute for .noinit section selection. (default_unique_section): Check DECL_NOINIT_P for .noinit section selection. gcc/testsuite/ChangeLog: * gcc.c-torture/execute/noinit-attribute.c: Don't override optimization options set by torture test harness. * lib/target-supports.exp (check_effective_target_noinit): Adjust comment formatting. --- gcc/c-family/c-attribs.c | 4 ++++ gcc/cgraph.h | 6 +++++- gcc/cgraphunit.c | 2 ++ gcc/lto-cgraph.c | 2 ++ .../gcc.c-torture/execute/noinit-attribute.c | 2 +- gcc/testsuite/lib/target-supports.exp | 2 +- gcc/tree-core.h | 1 + gcc/tree.h | 6 ++++++ gcc/varasm.c | 11 ++++++++--- 9 files changed, 30 insertions(+), 6 deletions(-) diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 8283e959c89..6f8288326ee 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -2394,6 +2394,10 @@ handle_noinit_attribute (tree * node, valid. */ if (DECL_COMMON (*node)) DECL_COMMON (*node) = 0; + + /* Set DECL_NOINIT_P to indicate the decaration should not be + initialized by the startup code. */ + DECL_NOINIT_P (*node) = 1; } } diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 96d6cf609fe..4176f761482 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -120,7 +120,7 @@ public: used_from_other_partition (false), in_other_partition (false), address_taken (false), in_init_priority_hash (false), need_lto_streaming (false), offloadable (false), ifunc_resolver (false), - order (false), next_sharing_asm_name (NULL), + noinit (false), order (false), next_sharing_asm_name (NULL), previous_sharing_asm_name (NULL), same_comdat_group (NULL), ref_list (), alias_target (NULL), lto_file_data (NULL), aux (NULL), x_comdat_group (NULL_TREE), x_section (NULL) @@ -577,6 +577,10 @@ public: /* Set when symbol is an IFUNC resolver. */ unsigned ifunc_resolver : 1; + /* Set when the symbol is decorated with the "noinit" attribute, + which indicates it should not be initialized by the runtime + startup code. */ + unsigned noinit : 1; /* Ordering of all symtab entries. */ int order; diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 19ae8763373..9437e7b719e 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -915,6 +915,8 @@ process_function_and_variable_attributes (cgraph_node *first, if (DECL_EXTERNAL (decl) && DECL_INITIAL (decl)) varpool_node::finalize_decl (decl); + if (DECL_NOINIT_P (decl)) + vnode->noinit = true; if (DECL_PRESERVE_P (decl)) vnode->force_output = true; else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl))) diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 93a99f3465b..8d6ba74dcad 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -631,6 +631,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node, bp_pack_value (&bp, node->tls_model, 3); bp_pack_value (&bp, node->used_by_single_function, 1); bp_pack_value (&bp, node->dynamically_initialized, 1); + bp_pack_value (&bp, node->noinit, 1); streamer_write_bitpack (&bp); group = node->get_comdat_group (); @@ -1395,6 +1396,7 @@ input_varpool_node (struct lto_file_decl_data *file_data, node->tls_model = (enum tls_model)bp_unpack_value (&bp, 3); node->used_by_single_function = (enum tls_model)bp_unpack_value (&bp, 1); node->dynamically_initialized = bp_unpack_value (&bp, 1); + node->noinit = bp_unpack_value (&bp, 1); group = read_identifier (ib); if (group) { diff --git a/gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c b/gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c index 20a2a452e79..c8fa22bf38b 100644 --- a/gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c +++ b/gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c @@ -1,6 +1,6 @@ /* { dg-do run } */ /* { dg-require-effective-target noinit } */ -/* { dg-options "-O2" } */ +/* { dg-options "-Wattributes" } */ /* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */ /* This test checks that noinit data is handled correctly. diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 8439720baea..4122285cc1d 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -368,7 +368,7 @@ proc check_weak_override_available { } { return [check_weak_available] } -# The noinit attribute is only supported by some targets. +# The "noinit" attribute is only supported by some targets. # This proc returns 1 if it's supported, 0 if it's not. proc check_effective_target_noinit { } { diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 752bec31c3f..b2deb332ce5 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -1691,6 +1691,7 @@ struct GTY(()) tree_decl_common { unsigned abstract_flag : 1; unsigned artificial_flag : 1; unsigned preserve_flag: 1; + unsigned noinit_flag: 1; unsigned debug_expr_is_from : 1; unsigned lang_flag_0 : 1; diff --git a/gcc/tree.h b/gcc/tree.h index f43ac9f1942..ac73f3c3af9 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2648,6 +2648,12 @@ extern tree vector_element_bits_tree (const_tree); #define DECL_PRESERVE_P(DECL) \ DECL_COMMON_CHECK (DECL)->decl_common.preserve_flag +/* Nonzero for a decl that is decorated with the "noinit" attribute. + decls with this attribute are placed into a special section so they are not + initialized by the target's startup code. */ +#define DECL_NOINIT_P(DECL) \ + DECL_COMMON_CHECK (DECL)->decl_common.noinit_flag + /* For function local variables of COMPLEX and VECTOR types, indicates that the variable is not aliased, and that all modifications to the variable have been adjusted so that diff --git a/gcc/varasm.c b/gcc/varasm.c index ea0b59cf44a..0d44342e813 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -1156,6 +1156,7 @@ get_variable_section (tree decl, bool prefer_noswitch_p) { vnode = vnode->ultimate_alias_target (); decl = vnode->decl; + DECL_NOINIT_P (decl) = vnode->noinit; } if (TREE_TYPE (decl) != error_mark_node) @@ -1203,6 +1204,7 @@ get_variable_section (tree decl, bool prefer_noswitch_p) if (ADDR_SPACE_GENERIC_P (as) && !DECL_THREAD_LOCAL_P (decl) + && !DECL_NOINIT_P (decl) && !(prefer_noswitch_p && targetm.have_switchable_bss_sections) && bss_initializer_p (decl)) { @@ -7004,13 +7006,11 @@ default_elf_select_section (tree decl, int reloc, sname = ".tdata"; break; case SECCAT_BSS: - if (DECL_P (decl) - && lookup_attribute ("noinit", DECL_ATTRIBUTES (decl)) != NULL_TREE) + if (DECL_P (decl) && DECL_NOINIT_P (decl)) { sname = ".noinit"; break; } - if (bss_section) return bss_section; sname = ".bss"; @@ -7073,6 +7073,11 @@ default_unique_section (tree decl, int reloc) prefix = one_only ? ".s" : ".sdata"; break; case SECCAT_BSS: + if (DECL_P (decl) && DECL_NOINIT_P (decl)) + { + prefix = one_only ? ".n" : ".noinit"; + break; + } prefix = one_only ? ".b" : ".bss"; break; case SECCAT_SBSS: -- 2.28.0