From: Matthew Fortune <[email protected]>
Allow GP-relative data to be placed in numbered small-data sections,
enabling multiple small-data areas within an executable. Also support
selecting individual global variables for small-data placement from a
list file.
gcc/ChangeLog:
* config/mips/mips.cc (mips_sdata_entry): New struct.
(mips_sdata_opt_list): New static variable.
(mips_read_list): New static function.
(mips_find_list): Likewise.
(mips_insert_attributes): Place a variable from
mips_sdata_opt_list in .sdata section number
mips_sdata_section_num.
(mips_asm_unique_section): New static function.
(mips_asm_select_section): New static function.
(mips_section_type_flags): New static function.
(mips_in_small_data_p): Consider .sdata_ and .sbss_.
(mips_option_override): Read a list of variables that should be
placed in sdata section. Check if mips_sdata_section_num is in
the range from 0 to 999.
(TARGET_ASM_SELECT_SECTION): Define.
(TARGET_ASM_UNIQUE_SECTION): Define.
(TARGET_SECTION_TYPE_FLAGS): Define.
* config/mips/mips.opt: Add the options -msdata-num and
-msdata-opt-list.
* doc/invoke.texi: Document the options -msdata-num and
-msdata-opt-list.
gcc/testsuite/ChangeLog:
* gcc.target/mips/sdata-num-1.c: New test.
* gcc.target/mips/sdata-opt-list-1.c: New test.
* gcc.target/mips/sdata-opt-list-1.lst: New test input file.
* gcc.target/mips/mips.exp: Add sdata-num and sdata-opt-list options.
Cherry-picked 2403e09c3a08b797e22e30f70f762ed1eadbd783
and f76b493c090cfc2f9270528e84ef0f04fb463c3f
from https://github.com/MIPS/gcc
Signed-off-by: Matthew Fortune <[email protected]>
Signed-off-by: Dragan Mladjenovic <[email protected]>
Signed-off-by: Faraz Shahbazker <[email protected]>
Signed-off-by: Aleksandar Rakic <[email protected]>
Signed-off-by: Eldar Osmanovic <[email protected]>
---
gcc/config/mips/mips.cc | 161 +++++++++++++++++-
gcc/config/mips/mips.opt | 8 +
gcc/doc/invoke.texi | 36 ++++
gcc/testsuite/gcc.target/mips/mips.exp | 2 +
gcc/testsuite/gcc.target/mips/sdata-num-1.c | 22 +++
.../gcc.target/mips/sdata-opt-list-1.c | 21 +++
.../gcc.target/mips/sdata-opt-list-1.lst | 1 +
7 files changed, 250 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/mips/sdata-num-1.c
create mode 100644 gcc/testsuite/gcc.target/mips/sdata-opt-list-1.c
create mode 100644 gcc/testsuite/gcc.target/mips/sdata-opt-list-1.lst
diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index d03145a16d8..6e5e7afe80b 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -639,6 +639,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
{
@@ -9825,6 +9905,70 @@ mips_encode_section_info (tree decl, rtx rtl, int first)
}
}
+/* Implement TARGET_ASM_UNIQUE_SECTION. */
+
+static 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. */
+
+static 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 *
@@ -9860,7 +10004,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
@@ -20554,6 +20700,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
@@ -21099,6 +21247,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 ();
}
@@ -23768,6 +23919,14 @@ mips_print_patchable_function_entry (FILE *file
ATTRIBUTE_UNUSED,
#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
#undef TARGET_DOCUMENTATION_NAME
#define TARGET_DOCUMENTATION_NAME "MIPS"
diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt
index 11b252a6530..5012515df15 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -533,3 +533,11 @@ Enum(mips_lib_setting) String(tiny) Value(MIPS_LIB_TINY)
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 ae01f8f2456..8be323969a4 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1236,6 +1236,8 @@ Objective-C and Objective-C++ Dialects}.
-mlong64 -mlong32 -msym32
-G@var{num} -mno-local-sdata -mno-extern-sdata -mno-gopt
-membedded-data -muninit-const-in-rodata
+-msdata-num=@var{num}
+-msdata-opt-list=@var{file}
-mcode-readable=@var{setting} -mno-data-in-code -mcode-xonly
-mdead-loads -mno-dead-loads
-msplit-addresses -mexplicit-relocs -mexplicit-relocs=@var{release}
@@ -29585,6 +29587,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
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp
b/gcc/testsuite/gcc.target/mips/mips.exp
index a57e030798a..06795fdc253 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -315,6 +315,8 @@ foreach option {
code-readable
nan
r10k-cache-barrier
+ sdata-num
+ sdata-opt-list
tune
} {
lappend mips_option_groups $option "-m$option=.*"
diff --git a/gcc/testsuite/gcc.target/mips/sdata-num-1.c
b/gcc/testsuite/gcc.target/mips/sdata-num-1.c
new file mode 100644
index 00000000000..f3e71b0978f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/sdata-num-1.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-G4 -mexplicit-relocs -msdata-num=7" } */
+
+volatile int sdata_num_data = 1;
+volatile int sdata_num_bss __attribute__((nocommon));
+
+int
+read_sdata_num_data (void)
+{
+ return sdata_num_data;
+}
+
+int
+read_sdata_num_bss (void)
+{
+ return sdata_num_bss;
+}
+
+/* { dg-final { scan-assembler "\\.section\[ \t\]+\\.sdata_7" } } */
+/* { dg-final { scan-assembler "\\.section\[ \t\]+\\.sbss_7" } } */
+/* { dg-final { scan-assembler "%gp_?rel\\(sdata_num_data\\)" } } */
+/* { dg-final { scan-assembler "%gp_?rel\\(sdata_num_bss\\)" } } */
diff --git a/gcc/testsuite/gcc.target/mips/sdata-opt-list-1.c
b/gcc/testsuite/gcc.target/mips/sdata-opt-list-1.c
new file mode 100644
index 00000000000..ba489becf32
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/sdata-opt-list-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-G4 -mexplicit-relocs -msdata-num=5
-msdata-opt-list=${srcdir}/gcc.target/mips/sdata-opt-list-1.lst" } */
+
+int sdata_opt_list_data[2] = {1, 2};
+int sdata_opt_list_other[2] = {3, 4};
+
+int
+read_sdata_opt_list_data (void)
+{
+ return sdata_opt_list_data[0];
+}
+
+int
+read_sdata_opt_list_other (void)
+{
+ return sdata_opt_list_other[0];
+}
+
+/* { dg-final { scan-assembler "\\.section\[ \t\]+\\.sdata_5" } } */
+/* { dg-final { scan-assembler "%gp_?rel\\(sdata_opt_list_data\\)" } } */
+/* { dg-final { scan-assembler-not "%gp_?rel\\(sdata_opt_list_other\\)" } } */
diff --git a/gcc/testsuite/gcc.target/mips/sdata-opt-list-1.lst
b/gcc/testsuite/gcc.target/mips/sdata-opt-list-1.lst
new file mode 100644
index 00000000000..b04755c1429
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/sdata-opt-list-1.lst
@@ -0,0 +1 @@
+sdata_opt_list_data
--
2.43.0