public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Add generic support for "noinit" attribute
@ 2019-07-04 15:34 Christophe Lyon
  2019-07-04 15:43 ` Jozef Lawrynowicz
                   ` (2 more replies)
  0 siblings, 3 replies; 19+ messages in thread
From: Christophe Lyon @ 2019-07-04 15:34 UTC (permalink / raw)
  To: gcc Patches, Richard Earnshaw, nick clifton

[-- Attachment #1: Type: text/plain, Size: 3063 bytes --]

Hi,

Similar to what already exists for TI msp430 or in TI compilers for
arm, this patch adds support for the "noinit" attribute.

It is convenient for embedded targets where the user wants to keep the
value of some data when the program is restarted: such variables are
not zero-initialized. It is mostly a helper/shortcut to placing
variables in a dedicated section.

It's probably desirable to add the following chunk to the GNU linker:
diff --git a/ld/emulparams/armelf.sh b/ld/emulparams/armelf.sh
index 272a8bc..9555cec 100644
--- a/ld/emulparams/armelf.sh
+++ b/ld/emulparams/armelf.sh
@@ -10,7 +10,19 @@ OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue_7)
*(.vfp11_veneer) *(.v4_bx)'
 OTHER_BSS_SYMBOLS="${CREATE_SHLIB+PROVIDE (}__bss_start__ =
.${CREATE_SHLIB+)};"
 OTHER_BSS_END_SYMBOLS="${CREATE_SHLIB+PROVIDE (}_bss_end__ =
.${CREATE_SHLIB+)}; ${CREATE_SHLIB+PROVIDE (}__bss_end__ =
.${CREATE_SHLIB+)};"
 OTHER_END_SYMBOLS="${CREATE_SHLIB+PROVIDE (}__end__ = .${CREATE_SHLIB+)};"
 -OTHER_SECTIONS='.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }'
 +OTHER_SECTIONS='
 +.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
 +  /* This section contains data that is not initialised during load
 +     *or* application reset.  */
 +   .noinit (NOLOAD) :
 +   {
 +     . = ALIGN(2);
 +     PROVIDE (__noinit_start = .);
 +     *(.noinit)
 +     . = ALIGN(2);
 +     PROVIDE (__noinit_end = .);
 +   }
 +'

so that the noinit section has the "NOLOAD" flag.

I'll submit that part separately to the binutils project if OK.

However, I'm not sure for which other targets (beyond arm), I should
update the linker scripts.

I left the new testcase in gcc.target/arm, guarded by
dg-do run { target { *-*-eabi } }
but since this attribute is now generic, I suspect I should move the
test to some other place. But then, which target selector should I
use?

Finally, I tested on arm-eabi, but not on msp430 for which I do not
have the environment, so advice from msp430 maintainers is
appreciated. Since msp430 does not use the same default helpers as
arm, I left the "noinit" handling code in place, to avoid changing
other generic functions which I don't know how to test
(default_select_section, default_section_type_flags).

Thanks,

Christophe

gcc/ChangeLog:

2019-07-04  Christophe Lyon  <christophe.lyon@linaro.org>

* doc/extend.texi: Add "noinit" attribute documentation.
* varasm.c
(default_section_type_flags): Add support for "noinit" section.
(default_elf_select_section): Add support for "noinit" attribute.

gcc/c-family/ChangeLog:

2019-07-04  Christophe Lyon  <christophe.lyon@linaro.org>

* c-attribs.c (c_common_attribute_table): Add "noinit" entry.
(handle_section_attribute): Add support for "noinit" attribute.
(handle_noinit_attribute): New function.

gcc/config/ChangeLog:

2019-07-04  Christophe Lyon  <christophe.lyon@linaro.org>

* msp430/msp430.c (msp430_attribute_table): Remove "noinit" entry.

gcc/testsuite/ChangeLog:

2019-07-04  Christophe Lyon  <christophe.lyon@linaro.org>

* gcc.target/arm/noinit-attribute.c: New test.

[-- Attachment #2: noinit-generic.patch.txt --]
[-- Type: text/plain, Size: 8040 bytes --]

diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 48819e7..3aefe84 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -92,6 +92,7 @@ static tree handle_section_attribute (tree *, tree, tree, int, bool *);
 static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
 static tree handle_warn_if_not_aligned_attribute (tree *, tree, tree,
 						  int, bool *);
+static tree handle_noinit_attribute (tree *, tree, tree, int, bool *);
 static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
 static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ;
 static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *);
@@ -458,6 +459,8 @@ const struct attribute_spec c_common_attribute_table[] =
 			      handle_nocf_check_attribute, NULL },
   { "copy",                   1, 1, false, false, false, false,
 			      handle_copy_attribute, NULL },
+  { "noinit",                 0, 0, true,  false, false, false,
+			      handle_noinit_attribute, NULL },
   { NULL,                     0, 0, false, false, false, false, NULL, NULL }
 };
 
@@ -1912,6 +1915,13 @@ handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
       goto fail;
     }
 
+  if (DECL_P (decl) && lookup_attribute ("noinit", DECL_ATTRIBUTES (decl)) != NULL_TREE)
+    {
+      warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
+		"section attribute cannot be applied to variables with noinit attribute");
+      goto fail;
+    }
+
   set_decl_section_name (decl, TREE_STRING_POINTER (TREE_VALUE (args)));
   return NULL_TREE;
 
@@ -2224,6 +2234,48 @@ handle_weak_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
+/* Handle a "noinit" attribute; arguments as in struct
+   attribute_spec.handler. Check whether the attribute is allowed here
+   and add the attribute to the variable decl tree or otherwise issue
+   a diagnostic. This function checks NODE is of the expected type and
+   issues diagnostics otherwise using NAME.  If it is not of the
+   expected type *NO_ADD_ATTRS will be set to true.  */
+
+static tree
+handle_noinit_attribute (tree * node,
+		  tree   name,
+		  tree   args,
+		  int    flags ATTRIBUTE_UNUSED,
+		  bool * no_add_attrs)
+{
+  const char * message = NULL;
+
+  gcc_assert (DECL_P (*node));
+  gcc_assert (args == NULL);
+
+  if (TREE_CODE (* node) != VAR_DECL)
+    message = G_("%qE attribute only applies to variables");
+
+  /* Check that it's possible for the variable to have a section.  */
+  if ((TREE_STATIC (* node) || DECL_EXTERNAL (* node) || in_lto_p)
+      && DECL_SECTION_NAME (* node))
+    message = G_("%qE attribute cannot be applied to variables with specific sections");
+
+  /* If this var is thought to be common, then change this.  Common variables
+     are assigned to sections before the backend has a chance to process them.  */
+  if (DECL_COMMON (* node))
+    DECL_COMMON (* node) = 0;
+
+  if (message)
+    {
+      warning (OPT_Wattributes, message, name);
+      * no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+
 /* Handle a "noplt" attribute; arguments as in
    struct attribute_spec.handler.  */
 
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 365e9eb..8266fa0 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -1807,7 +1807,6 @@ const char * const  ATTR_CRIT   = "critical";
 const char * const  ATTR_LOWER  = "lower";
 const char * const  ATTR_UPPER  = "upper";
 const char * const  ATTR_EITHER = "either";
-const char * const  ATTR_NOINIT = "noinit";
 const char * const  ATTR_PERSIST = "persistent";
 
 static inline bool
@@ -2108,8 +2107,6 @@ const struct attribute_spec msp430_attribute_table[] =
   { ATTR_EITHER,      0, 0, true,  false, false, false, msp430_section_attr,
     NULL },
 
-  { ATTR_NOINIT,      0, 0, true,  false, false, false, msp430_data_attr,
-    NULL },
   { ATTR_PERSIST,     0, 0, true,  false, false, false, msp430_data_attr,
     NULL },
 
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index f2619e1..850153e 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -7129,6 +7129,12 @@ The @code{visibility} attribute is described in
 The @code{weak} attribute is described in
 @ref{Common Function Attributes}.
 
+@item noinit
+@cindex @code{noinit} variable attribute
+Any data with the @code{noinit} attribute will not be initialized by
+the C runtime startup code, or the program loader.  Not initializing
+data in this way can reduce program startup times.
+
 @end table
 
 @node ARC Variable Attributes
diff --git a/gcc/testsuite/gcc.target/arm/noinit-attribute.c b/gcc/testsuite/gcc.target/arm/noinit-attribute.c
new file mode 100644
index 0000000..242de2f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/noinit-attribute.c
@@ -0,0 +1,56 @@
+/* { dg-do run { target { *-*-eabi } } } */
+/* { dg-options "-O2" } */
+
+/* This test checks that noinit data is handled correctly.  */
+
+extern void _start (void) __attribute__ ((noreturn));
+extern void abort (void) __attribute__ ((noreturn));
+extern void exit (int) __attribute__ ((noreturn));
+
+int var_common;
+int var_zero = 0;
+int var_one = 1;
+int __attribute__((noinit)) var_noinit;
+int var_init = 2;
+
+int __attribute__((noinit)) func(); /* { dg-warning "attribute only applies to variables" } */
+int __attribute__((section ("mysection"), noinit)) var_section1; /* { dg-warning "attribute cannot be applied to variables with specific sections" } */
+int __attribute__((noinit, section ("mysection"))) var_section2; /* { dg-warning "attribute cannot be applied to variables with noinit attribute" } */
+
+
+int
+main (void)
+{
+  /* Make sure that the C startup code has correctly initialised the ordinary variables.  */
+  if (var_common != 0)
+    abort ();
+
+  /* Initialised variables are not re-initialised during startup, so check their original values only during the first run of this test.  */
+  if (var_init == 2)
+    if (var_zero != 0 || var_one != 1)
+      abort ();
+
+  switch (var_init)
+    {
+    case 2:
+      /* First time through - change all the values.  */
+      var_common = var_zero = var_one = var_noinit = var_init = 3;
+      break;
+
+    case 3:
+      /* Second time through - make sure that d has not been reset.  */
+      if (var_noinit != 3)
+	abort ();
+      exit (0);
+
+    default:
+      /* Any other value for var_init is an error.  */
+      abort ();
+    }
+
+  /* Simulate a processor reset by calling the C startup code.  */
+  _start ();
+
+  /* Should never reach here.  */
+  abort ();
+}
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 626a4c9..d013486 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -6428,6 +6428,9 @@ default_section_type_flags (tree decl, const char *name, int reloc)
       || strncmp (name, ".gnu.linkonce.tb.", 17) == 0)
     flags |= SECTION_TLS | SECTION_BSS;
 
+  if (strcmp (name, ".noinit") == 0)
+    flags |= SECTION_WRITE | SECTION_BSS | SECTION_NOTYPE;
+
   /* 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
@@ -6748,11 +6751,14 @@ decl_readonly_section (const_tree decl, int reloc)
 
 /* Select a section based on the above categorization.  */
 
+static section *noinit_section = NULL;
+
 section *
 default_elf_select_section (tree decl, int reloc,
 			    unsigned HOST_WIDE_INT align)
 {
   const char *sname;
+
   switch (categorize_decl_for_section (decl, reloc))
     {
     case SECCAT_TEXT:
@@ -6790,6 +6796,13 @@ 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 (noinit_section == NULL)
+	    noinit_section = get_named_section (decl, ".noinit", reloc);
+	  return noinit_section;
+	}
+
       if (bss_section)
 	return bss_section;
       sname = ".bss";

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2019-08-14 17:58 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-04 15:34 [PATCH] Add generic support for "noinit" attribute Christophe Lyon
2019-07-04 15:43 ` Jozef Lawrynowicz
2019-07-04 21:46 ` Jozef Lawrynowicz
2019-07-05 10:32   ` Christophe Lyon
2019-07-05 11:09     ` Jozef Lawrynowicz
2019-07-05 11:50       ` Christophe Lyon
2019-07-06 20:35 ` Martin Sebor
2019-07-08 11:27   ` Christophe Lyon
2019-07-08 22:10     ` Martin Sebor
2019-07-16  9:07       ` Christophe Lyon
2019-07-16 10:11     ` Richard Sandiford
2019-07-30 13:38       ` Christophe Lyon
2019-08-12 17:07         ` Jozef Lawrynowicz
2019-08-13 18:21         ` Christophe Lyon
2019-08-14 13:05         ` Richard Sandiford
2019-08-14 13:36           ` Christophe Lyon
2019-08-14 16:11             ` Tamar Christina
2019-08-14 17:20               ` Christophe Lyon
2019-08-14 18:04                 ` Christophe Lyon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).