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

Reply via email to