[16/61] Add -msdata-num and -msdata-opt-list support

Message ID 20250131171232.1018281-18-aleksandar.rakic@htecgroup.com
State New
Headers
Series Improve Mips target |

Commit Message

Aleksandar Rakic Jan. 31, 2025, 5:13 p.m. UTC
  From: Matthew Fortune <matthew.fortune@imgtec.com>

Cherry-picked 2403e09c3a08b797e22e30f70f762ed1eadbd783
and f76b493c090cfc2f9270528e84ef0f04fb463c3f
from https://github.com/MIPS/gcc

Signed-off-by: Matthew Fortune <matthew.fortune@imgtec.com>
Signed-off-by: Dragan Mladjenovic <dragan.mladjenovic@rt-rk.com>
Signed-off-by: Faraz Shahbazker <fshahbazker@wavecomp.com>
Signed-off-by: Aleksandar Rakic <aleksandar.rakic@htecgroup.com>
---
 gcc/config/mips/mips.cc  | 161 ++++++++++++++++++++++++++++++++++++++-
 gcc/config/mips/mips.opt |   8 ++
 gcc/doc/invoke.texi      |  36 +++++++++
 3 files changed, 204 insertions(+), 1 deletion(-)
  

Patch

diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index 4c719fbaed5..6e48feeb560 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -640,6 +640,62 @@  TARGET_GNU_ATTRIBUTES (mips_attribute_table, {
   { "use_hazard_barrier_return", 0, 0, true, false, false, false, NULL, NULL }
 });
 
+struct mips_sdata_entry
+{
+  char *var;
+  struct mips_sdata_entry *next;
+};
+
+static struct mips_sdata_entry *mips_sdata_opt_list;
+
+static struct mips_sdata_entry *
+mips_read_list (const char * filename)
+{
+  FILE *fd;
+  char line[256];
+  struct mips_sdata_entry *current = NULL;
+  struct mips_sdata_entry *head = NULL;
+
+  if (filename == NULL)
+    return NULL;
+  fd = fopen (filename, "r");
+  if (fd == NULL)
+    {
+      error ("Bad filename for -msdata-opt-list: %s\n", filename);
+      return NULL;
+    }
+
+  while (fgets (line, sizeof (line), fd))
+    {
+      struct mips_sdata_entry *entry;
+      entry = (struct mips_sdata_entry *)xmalloc (
+	sizeof (struct mips_sdata_entry));
+      entry->var = xstrdup (line);
+      if (entry->var[strlen (entry->var)-1] == '\n')
+	entry->var[strlen (entry->var)-1] = '\0';
+      entry->next = NULL;
+      if (head == NULL)
+	current = head = entry;
+      else
+	current = current->next = entry;
+    }
+  fclose (fd);
+  return head;
+}
+
+static bool
+mips_find_list (const char *var, struct mips_sdata_entry *list)
+{
+  while (list != NULL)
+    {
+      if (strcmp (list->var, var) == 0)
+	return true;
+      list = list->next;
+    }
+
+  return false;
+}
+
 /* A table describing all the processors GCC knows about; see
    mips-cpus.def for details.  */
 static const struct mips_cpu_info mips_cpu_info_table[] = {
@@ -1533,6 +1589,30 @@  mips_insert_attributes (tree decl, tree *attributes)
       if (compression_flags)
 	error ("%qs attribute only applies to functions",
 	       mips_get_compress_on_name (nocompression_flags));
+
+      if (TREE_CODE (decl) == VAR_DECL
+	  && is_global_var (decl)
+	  && DECL_NAME (decl)
+	  && mips_find_list (IDENTIFIER_POINTER (DECL_NAME (decl)),
+			     mips_sdata_opt_list))
+	{
+	  tree attr_args;
+	  if (mips_sdata_section_num > -1)
+	    {
+	      char sec_name[13];
+	      sprintf (sec_name, ".sdata_%d", mips_sdata_section_num);
+	      attr_args = build_tree_list (NULL_TREE,
+					   build_string (strlen (sec_name),
+							 sec_name));
+	    }
+	  else
+	    attr_args = build_tree_list (NULL_TREE,
+					 build_string (6, ".sdata"));
+
+	  *attributes = tree_cons (get_identifier ("section"),
+				   attr_args,
+				   *attributes);
+	}
     }
   else
     {
@@ -9804,6 +9884,70 @@  mips_encode_section_info (tree decl, rtx rtl, int first)
     }
 }
 
+/* Implement TARGET_ASM_UNIQUE_SECTION.  */
+
+void
+mips_asm_unique_section (tree decl, int reloc)
+{
+  default_unique_section (decl, reloc);
+
+  const char *name = DECL_SECTION_NAME (decl);
+
+  if (mips_sdata_section_num > -1
+      && (strncmp (".sdata", name, 6) == 0
+	  || strncmp (".sbss", name, 5) == 0))
+    {
+      char *sec_name = (char*) alloca (strlen (name) + 5);
+      if (strncmp (".sdata", name, 6) == 0)
+	sprintf (sec_name, ".sdata_%d%s", mips_sdata_section_num, name + 6);
+      else
+	sprintf (sec_name, ".sbss_%d%s", mips_sdata_section_num, name + 5);
+
+      set_decl_section_name (decl, sec_name);
+    }
+}
+
+/* Implement TARGET_ASM_SELECT_SECTION.  */
+
+static section *
+mips_asm_select_section (tree exp, int reloc, unsigned HOST_WIDE_INT align)
+{
+  char * sec_name;
+  section *s;
+
+  s = default_elf_select_section (exp, reloc, align);
+
+  if (mips_sdata_section_num > -1
+      && (s->named.common.flags & SECTION_NAMED)
+      && (strncmp (".sdata", s->named.name, 6) == 0
+	  || strncmp (".sbss", s->named.name, 5) == 0))
+    {
+      sec_name = (char*) alloca (strlen (s->named.name) + 5);
+      if (strncmp (".sdata", s->named.name, 6) == 0)
+	sprintf (sec_name, ".sdata_%d%s", mips_sdata_section_num,
+		 s->named.name + 6);
+      else
+	sprintf (sec_name, ".sbss_%d%s", mips_sdata_section_num,
+		 s->named.name + 5);
+      s = get_section (sec_name, s->named.common.flags, exp);
+    }
+  return s;
+}
+
+/* Implement TARGET_SECTION_TYPE_FLAGS.  */
+
+unsigned int
+mips_section_type_flags (tree decl, const char *name, int reloc)
+{
+  unsigned int flags = default_section_type_flags (decl, name, reloc);
+
+  if (mips_sdata_section_num > -1
+      && strncmp (name, ".sbss_", 6) == 0)
+    flags |= SECTION_BSS;
+
+  return flags;
+}
+
 /* Implement TARGET_SELECT_RTX_SECTION.  */
 
 static section *
@@ -9839,7 +9983,9 @@  mips_in_small_data_p (const_tree decl)
 
       /* Reject anything that isn't in a known small-data section.  */
       name = DECL_SECTION_NAME (decl);
-      if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0)
+      if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0
+	  && strncmp (name, ".sdata_", 7) != 0
+	  && strncmp (name, ".sbss_", 6) != 0)
 	return false;
 
       /* If a symbol is defined externally, the assembler will use the
@@ -20518,6 +20664,8 @@  mips_option_override (void)
   if (TARGET_FLIP_MIPS16)
     TARGET_INTERLINK_COMPRESSED = 1;
 
+  mips_sdata_opt_list = mips_read_list (mips_sdata_opt_list_file);
+
   /* Set the small data limit.  */
   mips_small_data_threshold = (OPTION_SET_P (g_switch_value)
 			       ? g_switch_value
@@ -21067,6 +21215,9 @@  mips_option_override (void)
   if (TARGET_HARD_FLOAT_ABI && TARGET_MIPS5900)
     REAL_MODE_FORMAT (SFmode) = &spu_single_format;
 
+  if (mips_sdata_section_num >= 1000)
+    error ("Number for -msdata-num must be between 0 and 999");
+
   mips_register_frame_header_opt ();
 }
 
@@ -23721,6 +23872,14 @@  mips_bit_clear_p (enum machine_mode mode, unsigned HOST_WIDE_INT m)
 
 #undef TARGET_C_MODE_FOR_FLOATING_TYPE
 #define TARGET_C_MODE_FOR_FLOATING_TYPE mips_c_mode_for_floating_type
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION mips_asm_select_section
+
+#undef TARGET_ASM_UNIQUE_SECTION
+#define TARGET_ASM_UNIQUE_SECTION mips_asm_unique_section
+
+#undef TARGET_SECTION_TYPE_FLAGS
+#define TARGET_SECTION_TYPE_FLAGS mips_section_type_flags
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt
index 28b8de216fe..ca7d064dd6e 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -540,3 +540,11 @@  Target Undocumented Var(TARGET_FORBIDDEN_SLOTS) Init(1)
 mdead-loads
 Target Var(TARGET_DEAD_LOADS) Init(0)
 Redirect dead loads to $0 to avoid spurious output dependencies.
+
+msdata-num=
+Target RejectNegative Joined UInteger Var(mips_sdata_section_num) Init(-1)
+Place all gp relative data in sdata section number NUM.
+
+msdata-opt-list=
+Target RejectNegative Joined Var(mips_sdata_opt_list_file)
+msdata-opt-list=FILE    Use to specify variables to go in the .sdata section.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 636aea39e53..d3b0187daff 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1151,6 +1151,8 @@  Objective-C and Objective-C++ Dialects}.
 -G@var{num}  -mlocal-sdata  -mno-local-sdata
 -mextern-sdata  -mno-extern-sdata  -mgpopt  -mno-gopt
 -membedded-data  -mno-embedded-data
+-msdata-num=@var{num}
+-msdata-opt-list=@var{file}
 -muninit-const-in-rodata  -mno-uninit-const-in-rodata
 -mcode-readable=@var{setting}
 -mdead-loads -mno-dead-loads
@@ -28806,6 +28808,40 @@  next in the small data section if possible, otherwise in data.  This gives
 slightly slower code than the default, but reduces the amount of RAM required
 when executing, and thus may be preferred for some embedded systems.
 
+@opindex msdata-num
+@item -msdata-num=@var{num}
+Use a numbered small data section instead of the default to enable multiple
+small data areas within one executable.  This feature is for advanced users
+only and requires very careful management of where data is accessed.  The
+aim is to allow code which executes solely within one software context to
+use a unique small data area.
+
+Compilation units should be grouped such that all units within a group can
+share a small data section.  The @code{num} value should be set to the same
+number for all related modules.  Any data that is shared between contexts
+will need to be explicitly placed in a named section using
+@code{__attribute__((section (".my_shared_data")))}.  Alternatively use the
+@option{-mno-extern-sdata} option to ensure that the compiler does not
+automatically place global data in the small data section and instead
+use the @option{-msdata-opt-list} option to explicitly place some global
+data in the small data section where it is only used by one context.
+
+It is the user's responsibility to ensure that the global pointer for any
+given software context is set to point at the appropriate small data area.
+It is also the user's responsibility to ensure that data placed in one
+software context's small data area is not accessed using the small data
+model from a different software context as the application may not link.
+Linker support for this feature is also required and should be enabled
+using @option{-Wl,--user-defined-sdata-sections}.
+
+@opindex msdata-opt-list
+@item -msdata-opt-list
+Read a list of data variables from a file that must be accessed using the
+small data model.  This is equivalent to adding
+@code{__attribute__((section (".sdata"))} to the declaration in the source.
+For this option to take effect on uninitialised globals then
+@option{-fno-common} must also be used.
+
 @opindex muninit-const-in-rodata
 @opindex mno-uninit-const-in-rodata
 @item -muninit-const-in-rodata