[PATCH 0/2] RISC-V: Support ELF attribute for GCC.

26 views
Skip to first unread message

Kito Cheng

unread,
Feb 13, 2019, 2:14:55 AM2/13/19
to kito....@gmail.com, Binutils, Jim Wilson, RISC-V Patches, Palmer Dabbelt
This patch series is implementation of RISC-V ELF attribute[1], it consists of
two part, first part is improve the -march string parser, in order to support
arch string with version and all kind of extension in the RISC-V ISA spec
v2.2[2], and second part is attribute directive generation, including configure
time and run time option to control that.

[1] https://github.com/riscv/riscv-elf-psabi-doc/pull/71
[2] https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-spec-v2.2.pdf

Kito Cheng

unread,
Feb 13, 2019, 2:14:59 AM2/13/19
to kito....@gmail.com, Binutils, Jim Wilson, RISC-V Patches, Palmer Dabbelt
From: Kito Cheng <kito....@gmail.com>

Kito Cheng <kito....@gmail.com>
Monk Chiang <sh.ch...@gmail.com>

ChangeLog:
gcc:
* common/config/riscv/riscv-common.c:
Include config/riscv/riscv-protos.h.
(INCLUDE_STRING): Defined.
(RISCV_DONT_CARE_VERSION): Defined.
(riscv_subset_t): Declare.
(riscv_subset_list): Declare.
(riscv_subset_list::riscv_subset_list): New.
(riscv_subset_list::~riscv_subset_list): Likewise.
(riscv_subset_list::parsing_subset_version): Likewise.
(riscv_subset_list::parse_std_ext): Likewise.
(riscv_subset_list::parse_sv_or_non_std_ext): Likewise.
(riscv_subset_list::add): Likewise.
(riscv_subset_list::lookup): Likewise.
(riscv_subset_list::xlen): Likewise.
(riscv_subset_list::parse): Likewise.
(riscv_supported_std_ext): Likewise.
(current_subset_list): Likewise.
(riscv_parse_arch_string): Using riscv_subset_list::parse to
parse.

gcc/testsuite:
* gcc.target/riscv/arch-1.c: New.
* gcc.target/riscv/arch-2.c: Likewise.
* gcc.target/riscv/arch-3.c: Likewise.
* gcc.target/riscv/arch-4.c: Likewise.
---
gcc/common/config/riscv/riscv-common.c | 530 ++++++++++++++++++++++++++++----
gcc/testsuite/gcc.target/riscv/arch-1.c | 7 +
gcc/testsuite/gcc.target/riscv/arch-2.c | 6 +
gcc/testsuite/gcc.target/riscv/arch-3.c | 6 +
gcc/testsuite/gcc.target/riscv/arch-4.c | 6 +
5 files changed, 496 insertions(+), 59 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/arch-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/arch-2.c
create mode 100644 gcc/testsuite/gcc.target/riscv/arch-3.c
create mode 100644 gcc/testsuite/gcc.target/riscv/arch-4.c

diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c
index cb5bb7f..e412acb 100644
--- a/gcc/common/config/riscv/riscv-common.c
+++ b/gcc/common/config/riscv/riscv-common.c
@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */

+#define INCLUDE_STRING
#include "config.h"
#include "system.h"
#include "coretypes.h"
@@ -26,99 +27,510 @@ along with GCC; see the file COPYING3. If not see
#include "opts.h"
#include "flags.h"
#include "diagnostic-core.h"
+#include "config/riscv/riscv-protos.h"

-/* Parse a RISC-V ISA string into an option mask. Must clear or set all arch
- dependent mask bits, in case more than one -march string is passed. */
+#define RISCV_DONT_CARE_VERSION -1

-static void
-riscv_parse_arch_string (const char *isa, int *flags, location_t loc)
+/* Subset info. */
+struct riscv_subset_t {
+ riscv_subset_t ();
+
+ std::string name;
+ int major_version;
+ int minor_version;
+ struct riscv_subset_t *next;
+};
+
+/* Subset list. */
+class riscv_subset_list {
+private:
+ /* Original arch string. */
+ const char *m_arch;
+
+ /* Localtion of arch string, used for report error. */
+ location_t m_loc;
+
+ /* Head of subset info list. */
+ riscv_subset_t *m_head;
+
+ /* Tail of subset info list. */
+ riscv_subset_t *m_tail;
+
+ /* X-len of m_arch. */
+ unsigned m_xlen;
+
+ riscv_subset_list (const char *, location_t);
+
+ const char *parsing_subset_version (const char *, unsigned *, unsigned *,
+ unsigned, unsigned, bool);
+
+ const char *parse_std_ext (const char *);
+
+ const char *parse_sv_or_non_std_ext (const char *, const char *,
+ const char *);
+
+public:
+ ~riscv_subset_list ();
+
+ void add (const char *, int, int);
+
+ riscv_subset_t *lookup (const char *,
+ int major_version = RISCV_DONT_CARE_VERSION,
+ int minor_version = RISCV_DONT_CARE_VERSION) const;
+
+ unsigned xlen() const {return m_xlen;};
+
+ static riscv_subset_list *parse (const char *, location_t);
+
+};
+
+static const char *riscv_supported_std_ext (void);
+
+static riscv_subset_list *current_subset_list = NULL;
+
+riscv_subset_t::riscv_subset_t()
+: name (), major_version (0), minor_version (0), next (NULL)
{
- const char *p = isa;
+}

- if (strncmp (p, "rv32", 4) == 0)
- *flags &= ~MASK_64BIT, p += 4;
- else if (strncmp (p, "rv64", 4) == 0)
- *flags |= MASK_64BIT, p += 4;
- else
+riscv_subset_list::riscv_subset_list (const char *arch, location_t loc)
+: m_arch (arch), m_loc(loc), m_head (NULL), m_tail (NULL), m_xlen(0)
+{
+}
+
+riscv_subset_list::~riscv_subset_list()
+{
+ if (!m_head)
+ return;
+
+ riscv_subset_t *item = this->m_head->next;
+ while (item != NULL)
{
- error_at (loc, "-march=%s: ISA string must begin with rv32 or rv64", isa);
- return;
+ riscv_subset_t *next = item->next;
+ delete item;
+ item = next;
}
+}

- if (*p == 'g')
- {
- p++;
+/* Add new subset to list. */

- *flags &= ~MASK_RVE;
+void riscv_subset_list::add (const char *subset,
+ int major_version,
+ int minor_version)
+{
+ riscv_subset_t *s = new riscv_subset_t ();

- *flags |= MASK_MUL;
- *flags |= MASK_ATOMIC;
- *flags |= MASK_HARD_FLOAT;
- *flags |= MASK_DOUBLE_FLOAT;
- }
- else if (*p == 'i')
- {
- p++;
+ if (m_head == NULL)
+ m_head = s;
+
+ s->name = subset;
+ s->major_version = major_version;
+ s->minor_version = minor_version;
+ s->next = NULL;
+
+ if (m_tail != NULL)
+ m_tail->next = s;
+
+ m_tail = s;
+}

- *flags &= ~MASK_RVE;
+/* Find subset in list without version checking, return NULL if not found. */

- *flags &= ~MASK_MUL;
- if (*p == 'm')
- *flags |= MASK_MUL, p++;
+riscv_subset_t *riscv_subset_list::lookup (const char *subset,
+ int major_version,
+ int minor_version) const
+{
+ riscv_subset_t *s;
+
+ for (s = m_head; s != NULL; s = s->next)
+ if (strcasecmp (s->name.c_str(), subset) == 0)
+ {
+ if ((major_version != RISCV_DONT_CARE_VERSION)
+ && (s->major_version != major_version))
+ return NULL;
+
+ if ((minor_version != RISCV_DONT_CARE_VERSION)
+ && (s->minor_version != minor_version))
+ return NULL;

- *flags &= ~MASK_ATOMIC;
- if (*p == 'a')
- *flags |= MASK_ATOMIC, p++;
+ return s;
+ }
+
+ return s;
+}
+
+/* Return string which contain all supported standard extensions in
+ canonical order. */
+
+static const char *
+riscv_supported_std_ext (void)
+{
+ return "mafdqlcbjtpvn";
+}
+
+/* Parsing subset version.
+
+ Return Value:
+ Points to the end of version
+
+ Arguments:
+ `p`: Curent parsing position.
+ `major_version`: Parsing result of major version, using
+ default_major_version if version is not present in arch string.
+ `minor_version`: Parsing result of minor version, set to 0 if version is
+ not present in arch string, but set to `default_minor_version` if
+ `major_version` using default_major_version.
+ `default_major_version`: Default major version.
+ `default_minor_version`: Default minor version.
+ `std_ext_p`: True if parsing std extension. */
+
+const char *
+riscv_subset_list::parsing_subset_version (const char *p,
+ unsigned *major_version,
+ unsigned *minor_version,
+ unsigned default_major_version,
+ unsigned default_minor_version,
+ bool std_ext_p)
+{
+ bool major_p = true;
+ unsigned version = 0;
+ unsigned major = 0;
+ unsigned minor = 0;
+ char np;

- *flags &= ~(MASK_HARD_FLOAT | MASK_DOUBLE_FLOAT);
- if (*p == 'f')
+ for (;*p; ++p)
+ {
+ if (*p == 'p')
{
- *flags |= MASK_HARD_FLOAT, p++;
+ np = *(p + 1);

- if (*p == 'd')
+ if (!ISDIGIT (np))
{
- *flags |= MASK_DOUBLE_FLOAT;
- p++;
+ /* Might be beginning of `p` extension. */
+ if (std_ext_p)
+ {
+ *major_version = version;
+ *minor_version = 0;
+ return p;
+ }
+ else
+ {
+ error_at (m_loc, "-march=%s: Expect number after `%dp'.",
+ m_arch, version);
+ return NULL;
+ }
}
+
+ major = version;
+ major_p = false;
+ version = 0;
}
+ else if (ISDIGIT (*p))
+ version = (version * 10) + (*p - '0');
+ else
+ break;
}
- else if (*p == 'e')
+
+ if (major_p)
+ major = version;
+ else
+ minor = version;
+
+ if (major == 0 && minor == 0)
{
- p++;
+ /* We don't found any version string, use default version. */
+ *major_version = default_major_version;
+ *minor_version = default_minor_version;
+ }
+ else
+ {
+ *major_version = major;
+ *minor_version = minor;
+ }
+ return p;
+}
+
+/* Parsing function for standard extensions.
+
+ Return Value:
+ Points to the end of extensions.
+
+ Arguments:
+ `p`: Curent parsing position. */

- *flags |= MASK_RVE;
+const char *
+riscv_subset_list::parse_std_ext (const char *p)
+{
+ const char *all_std_exts = riscv_supported_std_ext ();
+ const char *std_exts = all_std_exts;
+
+ unsigned major_version = 0;
+ unsigned minor_version = 0;
+ char std_ext = '\0';
+
+ /* First letter must start with i, e or g. */
+ switch (*p)
+ {
+ case 'i':
+ p++;
+ p = parsing_subset_version (
+ p, &major_version, &minor_version,
+ /* default_major_version= */ 2,
+ /* default_minor_version= */ 0,
+ /* std_ext_p= */true);
+ add ("i", major_version, minor_version);
+ break;

- if (*flags & MASK_64BIT)
+ case 'e':
+ p++;
+ p = parsing_subset_version (
+ p, &major_version, &minor_version,
+ /* default_major_version= */ 1,
+ /* default_minor_version= */ 9,
+ /* std_ext_p= */true);
+
+ add ("e", major_version, minor_version);
+
+ if (m_xlen > 32)
+ {
+ error_at (m_loc, "-march=%s: rv%de is not a valid base ISA",
+ m_arch, m_xlen);
+ return NULL;
+ }
+
+ break;
+
+ case 'g':
+ p++;
+ p = parsing_subset_version (
+ p, &major_version, &minor_version,
+ /* default_major_version= */ 2,
+ /* default_minor_version= */ 0,
+ /* std_ext_p= */true);
+ add ("i", major_version, minor_version);
+
+ for ( ; *std_exts != 'q'; std_exts++)
+ {
+ const char subset[] = {*std_exts, '\0'};
+ add (subset, major_version, minor_version);
+ }
+ break;
+
+ default:
+ error_at (m_loc, "-march=%s: first ISA subset must be `e', `i' or `g'",
+ m_arch);
+ return NULL;
+ }
+
+ while (*p)
+ {
+ char subset[2] = {0, 0};
+
+ if (*p == 'x' || *p == 's')
+ break;
+
+ if (*p == '_')
{
- error ("RV64E is not a valid base ISA");
- return;
+ p++;
+ continue;
}

- *flags &= ~MASK_MUL;
- if (*p == 'm')
- *flags |= MASK_MUL, p++;
+ std_ext = *p;
+
+ /* Checking canonical order. */
+ while (*std_exts && std_ext != *std_exts) std_exts++;
+
+ if (std_ext != *std_exts)
+ {
+ if (strchr (all_std_exts, std_ext) == NULL)
+ error_at (m_loc, "-march=%s: unsupported ISA subset `%c'",
+ m_arch, *p);
+ else
+ error_at (m_loc,
+ "-march=%s: ISA string is not in canonical order. `%c'",
+ m_arch, *p);
+ return NULL;
+ }

- *flags &= ~MASK_ATOMIC;
- if (*p == 'a')
- *flags |= MASK_ATOMIC, p++;
+ std_exts++;

- *flags &= ~(MASK_HARD_FLOAT | MASK_DOUBLE_FLOAT);
+ p++;
+ p = parsing_subset_version (
+ p, &major_version, &minor_version,
+ /* default_major_version= */ 2,
+ /* default_minor_version= */ 0,
+ /* std_ext_p= */true);
+
+ subset[0] = std_ext;
+
+ add (subset, major_version, minor_version);
}
- else
+ return p;
+}
+
+/* Parsing function for non-standard and supervisor extensions.
+
+ Return Value:
+ Points to the end of extensions.
+
+ Arguments:
+ `p`: Curent parsing position.
+ `ext_type`: What kind of extensions, 'x', 's' or 'sx'.
+ `ext_type_str`: Full name for kind of extension. */
+
+const char *
+riscv_subset_list::parse_sv_or_non_std_ext (const char *p,
+ const char *ext_type,
+ const char *ext_type_str)
+{
+ unsigned major_version = 0;
+ unsigned minor_version = 0;
+ size_t ext_type_len = strlen (ext_type);
+
+ while (*p)
{
- error_at (loc, "-march=%s: invalid ISA string", isa);
- return;
+ if (*p == '_')
+ {
+ p++;
+ continue;
+ }
+
+ if (strncmp (p, ext_type, ext_type_len) != 0)
+ break;
+
+ /* It's non-standard supervisor extension if it prefix with sx. */
+ if ((ext_type[0] == 's') && (ext_type_len == 1)
+ && (*(p + 1) == 'x'))
+ break;
+
+ char *subset = xstrdup (p);
+ char *q = subset;
+ const char *end_of_version;
+
+ while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
+ ;
+
+ end_of_version =
+ parsing_subset_version (
+ q, &major_version, &minor_version,
+ /* default_major_version= */ 2,
+ /* default_minor_version= */ 0,
+ /* std_ext_p= */FALSE);
+
+ *q = '\0';
+
+ add (subset, major_version, minor_version);
+ free (subset);
+ p += end_of_version - subset;
+
+ if (*p != '\0' && *p != '_')
+ {
+ error_at (m_loc, "-march=%s: %s must seperate with _",
+ m_arch, ext_type_str);
+ return NULL;
+ }
}

- *flags &= ~MASK_RVC;
- if (*p == 'c')
- *flags |= MASK_RVC, p++;
+ return p;
+}
+
+/* Parsing arch string to subset list, return NULL if parsing failed. */

- if (*p)
+riscv_subset_list *
+riscv_subset_list::parse (const char *arch, location_t loc)
+{
+ riscv_subset_list *subset_list = new riscv_subset_list (arch, loc);
+ const char *p = arch;
+ if (strncmp (p, "rv32", 4) == 0)
{
- error_at (loc, "-march=%s: unsupported ISA substring %qs", isa, p);
- return;
+ subset_list->m_xlen = 32;
+ p += 4;
}
+ else if (strncmp (p, "rv64", 4) == 0)
+ {
+ subset_list->m_xlen = 64;
+ p += 4;
+ }
+ else
+ {
+ error_at (loc, "-march=%s: ISA string must begin with rv32 or rv64",
+ arch);
+ goto fail;
+ }
+
+ /* Parsing standard extension. */
+ p = subset_list->parse_std_ext (p);
+
+ if (p == NULL)
+ goto fail;
+
+ /* Parsing non-standard extension. */
+ p = subset_list->parse_sv_or_non_std_ext (
+ p, "x", "non-standard extension");
+
+ if (p == NULL)
+ goto fail;
+
+ /* Parsing supervisor extension. */
+ p = subset_list->parse_sv_or_non_std_ext (
+ p, "s", "supervisor extension");
+
+ if (p == NULL)
+ goto fail;
+
+ /* Parsing non-standard supervisor extension. */
+ p = subset_list->parse_sv_or_non_std_ext (
+ p, "sx", "non-standard supervisor extension");
+
+ if (p == NULL)
+ goto fail;
+
+ return subset_list;
+
+fail:
+ delete subset_list;
+ return NULL;
+}
+
+/* Parse a RISC-V ISA string into an option mask. Must clear or set all arch
+ dependent mask bits, in case more than one -march string is passed. */
+
+static void
+riscv_parse_arch_string (const char *isa, int *flags, location_t loc)
+{
+ riscv_subset_list *subset_list;
+ subset_list = riscv_subset_list::parse (isa, loc);
+ if (!subset_list)
+ return;
+
+ if (subset_list->xlen () == 32)
+ *flags &= ~MASK_64BIT;
+ else if (subset_list->xlen () == 64)
+ *flags |= MASK_64BIT;
+
+ *flags &= ~MASK_RVE;
+ if (subset_list->lookup ("e"))
+ *flags |= MASK_RVE;
+
+ *flags &= ~MASK_MUL;
+ if (subset_list->lookup ("m"))
+ *flags |= MASK_MUL;
+
+ *flags &= ~MASK_ATOMIC;
+ if (subset_list->lookup ("a"))
+ *flags |= MASK_ATOMIC;
+
+ *flags &= ~(MASK_HARD_FLOAT | MASK_DOUBLE_FLOAT);
+ if (subset_list->lookup ("f"))
+ *flags |= MASK_HARD_FLOAT;
+
+ if (subset_list->lookup ("d"))
+ *flags |= MASK_DOUBLE_FLOAT;
+
+ if (current_subset_list)
+ delete current_subset_list;
+
+ current_subset_list = subset_list;
}

/* Implement TARGET_HANDLE_OPTION. */
diff --git a/gcc/testsuite/gcc.target/riscv/arch-1.c b/gcc/testsuite/gcc.target/riscv/arch-1.c
new file mode 100644
index 0000000..e7c8738
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-1.c
@@ -0,0 +1,7 @@
+/* Verify the return instruction is mret. */
+/* { dg-do compile } */
+/* { dg-options "-O -march=rv32I -mabi=ilp32" } */
+int foo()
+{
+}
+/* { dg-error ".-march=rv32I: first ISA subset must be `e', `i' or `g'" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/riscv/arch-2.c b/gcc/testsuite/gcc.target/riscv/arch-2.c
new file mode 100644
index 0000000..ed90e2f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-2.c
@@ -0,0 +1,6 @@
+/* Verify the return instruction is mret. */
+/* { dg-do compile } */
+/* { dg-options "-O -march=rv32ixabc_xfoo -mabi=ilp32" } */
+int foo()
+{
+}
diff --git a/gcc/testsuite/gcc.target/riscv/arch-3.c b/gcc/testsuite/gcc.target/riscv/arch-3.c
new file mode 100644
index 0000000..55908dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-3.c
@@ -0,0 +1,6 @@
+/* Verify the return instruction is mret. */
+/* { dg-do compile } */
+/* { dg-options "-O -march=rv32ixbar_sabc_sxfoo -mabi=ilp32" } */
+int foo()
+{
+}
diff --git a/gcc/testsuite/gcc.target/riscv/arch-4.c b/gcc/testsuite/gcc.target/riscv/arch-4.c
new file mode 100644
index 0000000..3c9e1c1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-4.c
@@ -0,0 +1,6 @@
+/* Verify the return instruction is mret. */
+/* { dg-do compile } */
+/* { dg-options "-O -march=rv32i2p3_m4p2 -mabi=ilp32" } */
+int foo()
+{
+}
--
1.8.3.1

Kito Cheng

unread,
Feb 13, 2019, 2:17:32 AM2/13/19
to kito....@gmail.com, GCC Patches, Jim Wilson, RISC-V Patches, Palmer Dabbelt

Kito Cheng

unread,
Feb 13, 2019, 2:17:40 AM2/13/19
to kito....@gmail.com, GCC Patches, Jim Wilson, RISC-V Patches, Palmer Dabbelt

Kito Cheng

unread,
Feb 13, 2019, 2:17:45 AM2/13/19
to kito....@gmail.com, GCC Patches, Jim Wilson, RISC-V Patches, Palmer Dabbelt
From: Kito Cheng <kito....@gmail.com>

This patch added a configure time option, --with-riscv-attribute=[yes|no|default],
run time option, -mriscv-attribute to control the output of ELF attribute.

This feature is only enabled by default for ELF/Bare mental target
configuration.

Kito Cheng <kito....@gmail.com>
Monk Chiang <sh.ch...@gmail.com>

ChangeLog:
gcc:
* common/config/riscv/riscv-common.c: Include sstream.
(riscv_subset_list::to_string): New.
(riscv_arch_str): Likewise.
* config.gcc (riscv*-*-*): Hanlde --with-riscv-attribute=
* config.in: Regen
* config/riscv/riscv-protos.h (riscv_arch_str): New.
* config/riscv/riscv.c (INCLUDE_STRING): Defined.
(riscv_emit_attribute): New.
(riscv_file_start): Emit attribute if needed.
(riscv_option_override): Init riscv_emit_attribute_p.
* config/riscv/riscv.opt (mriscv-attribute): New option.
* configure.ac (riscv*-*-*): Check binutils is supporting ELF
attribute.
* doc/install.texi: Document --with-riscv-attribute.
* doc/invoke.texi: Document -mriscv-attribute.

gcc/testsuite:

* gcc.target/riscv/attribute-1.c: New.
* gcc.target/riscv/attribute-2.c: Likewise.
* gcc.target/riscv/attribute-3.c: Likewise.
* gcc.target/riscv/attribute-4.c: Likewise.
* gcc.target/riscv/attribute-5.c: Likewise.
* gcc.target/riscv/attribute-6.c: Likewise.
* gcc.target/riscv/attribute-7.c: Likewise.
* gcc.target/riscv/attribute-8.c: Likewise.
* gcc.target/riscv/attribute-9.c: Likewise.
---
gcc/common/config/riscv/riscv-common.c | 38 ++++++++++++++++++++++++++++
gcc/config.gcc | 26 ++++++++++++++++++-
gcc/config.in | 6 +++++
gcc/config/riscv/riscv-protos.h | 3 +++
gcc/config/riscv/riscv.c | 25 ++++++++++++++++++
gcc/config/riscv/riscv.opt | 4 +++
gcc/configure.ac | 7 +++++
gcc/doc/install.texi | 8 ++++++
gcc/doc/invoke.texi | 7 ++++-
gcc/testsuite/gcc.target/riscv/attribute-1.c | 7 +++++
gcc/testsuite/gcc.target/riscv/attribute-2.c | 7 +++++
gcc/testsuite/gcc.target/riscv/attribute-3.c | 7 +++++
gcc/testsuite/gcc.target/riscv/attribute-4.c | 7 +++++
gcc/testsuite/gcc.target/riscv/attribute-5.c | 7 +++++
gcc/testsuite/gcc.target/riscv/attribute-6.c | 7 +++++
gcc/testsuite/gcc.target/riscv/attribute-7.c | 7 +++++
gcc/testsuite/gcc.target/riscv/attribute-8.c | 7 +++++
gcc/testsuite/gcc.target/riscv/attribute-9.c | 7 +++++
18 files changed, 185 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-2.c
create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-3.c
create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-5.c
create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-6.c
create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-7.c
create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-8.c
create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-9.c

diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c
index e412acb..3f938ba 100644
--- a/gcc/common/config/riscv/riscv-common.c
+++ b/gcc/common/config/riscv/riscv-common.c
@@ -17,6 +17,8 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */

+#include <sstream>
+
#define INCLUDE_STRING
#include "config.h"
#include "system.h"
@@ -78,6 +80,8 @@ public:
int major_version = RISCV_DONT_CARE_VERSION,
int minor_version = RISCV_DONT_CARE_VERSION) const;

+ std::string to_string() const;
+
unsigned xlen() const {return m_xlen;};

static riscv_subset_list *parse (const char *, location_t);
@@ -134,6 +138,32 @@ void riscv_subset_list::add (const char *subset,
m_tail = s;
}

+/* Convert subset info to string with explicit version info. */
+
+std::string riscv_subset_list::to_string() const
+{
+ std::ostringstream oss;
+ oss << "rv" << m_xlen;
+
+ bool first = true;
+ riscv_subset_t *subset = m_head;
+
+ while (subset != NULL)
+ {
+ if (!first)
+ oss << '_';
+ first = false;
+
+ oss << subset->name
+ << subset->major_version
+ << 'p'
+ << subset->minor_version;
+ subset = subset->next;
+ }
+
+ return oss.str();
+}
+
/* Find subset in list without version checking, return NULL if not found. */

riscv_subset_t *riscv_subset_list::lookup (const char *subset,
@@ -492,6 +522,14 @@ fail:
return NULL;
}

+/* Return the current arch string. */
+
+std::string riscv_arch_str ()
+{
+ gcc_assert (current_subset_list);
+ return current_subset_list->to_string ();
+}
+
/* Parse a RISC-V ISA string into an option mask. Must clear or set all arch
dependent mask bits, in case more than one -march string is passed. */

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 31b47c5..5103476 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -4209,7 +4209,7 @@ case "${target}" in
;;

riscv*-*-*)
- supported_defaults="abi arch tune"
+ supported_defaults="abi arch tune riscv_attribute"

case "${target}" in
riscv-* | riscv32*) xlen=32 ;;
@@ -4217,6 +4217,30 @@ case "${target}" in
*) echo "Unsupported RISC-V target ${target}" 1>&2; exit 1 ;;
esac

+ case "${with_riscv_attribute}" in
+ yes)
+ tm_defines="${tm_defines} TARGET_RISCV_ATTRIBUTE=1"
+ ;;
+ no)
+ tm_defines="${tm_defines} TARGET_RISCV_ATTRIBUTE=0"
+ ;;
+ ""|default)
+ case "${target}" in
+ riscv*-*-elf*)
+ tm_defines="${tm_defines} TARGET_RISCV_ATTRIBUTE=1"
+ ;;
+ *)
+ tm_defines="${tm_defines} TARGET_RISCV_ATTRIBUTE=0"
+ ;;
+ esac
+ ;;
+ *)
+ echo "--with-riscv-attribute=${with_riscv_attribute} is not supported. The argument must begin with yes, no or default." 1>&2
+ exit 1
+ ;;
+ esac
+
+
# Infer arch from --with-arch, --target, and --with-abi.
case "${with_arch}" in
rv32e* | rv32i* | rv32g* | rv64i* | rv64g*)
diff --git a/gcc/config.in b/gcc/config.in
index 48a533b..a718cea 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -601,6 +601,12 @@
#endif


+/* Define if your assembler supports .attribute. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_RISCV_ATTRIBUTE
+#endif
+
+
/* Define if your assembler supports relocs needed by -fpic. */
#ifndef USED_FOR_TARGET
#undef HAVE_AS_SMALL_PIC_RELOCS
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index f0a5e11..b81eff0 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -84,4 +84,7 @@ extern rtx riscv_expand_builtin (tree, rtx, rtx, machine_mode, int);
extern tree riscv_builtin_decl (unsigned int, bool);
extern void riscv_init_builtins (void);

+/* Routines implemented in riscv-common.c. */
+extern std::string riscv_arch_str ();
+
#endif /* ! GCC_RISCV_PROTOS_H */
diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index bf4571d..103e5f5 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see

#define IN_TARGET_CODE 1

+#define INCLUDE_STRING
#include "config.h"
#include "system.h"
#include "coretypes.h"
@@ -4177,6 +4178,20 @@ riscv_issue_rate (void)
return tune_info->issue_rate;
}

+/* Auxiliary function for emit RISC-V ELF attribute. */
+static void
+riscv_emit_attribute ()
+{
+ fprintf (asm_out_file, "\t.attribute arch, \"%s\"\n",
+ riscv_arch_str ().c_str ());
+
+ fprintf (asm_out_file, "\t.attribute unaligned_access, %d\n",
+ TARGET_STRICT_ALIGN ? 0 : 1);
+
+ fprintf (asm_out_file, "\t.attribute stack_align, %d\n",
+ riscv_stack_boundary / 8);
+}
+
/* Implement TARGET_ASM_FILE_START. */

static void
@@ -4191,6 +4206,9 @@ riscv_file_start (void)
relaxation in the assembler. */
if (! riscv_mrelax)
fprintf (asm_out_file, "\t.option norelax\n");
+
+ if (riscv_emit_attribute_p)
+ riscv_emit_attribute ();
}

/* Implement TARGET_ASM_OUTPUT_MI_THUNK. Generate rtl rather than asm text
@@ -4361,6 +4379,13 @@ riscv_option_override (void)

riscv_stack_boundary = 8 << riscv_preferred_stack_boundary_arg;
}
+
+ if (riscv_emit_attribute_p < 0)
+#ifdef HAVE_AS_RISCV_ATTRIBUTE
+ riscv_emit_attribute_p = TARGET_RISCV_ATTRIBUTE;
+#else
+ riscv_emit_attribute_p = 0;
+#endif
}

/* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index bb8ec95..1cf035f 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -127,3 +127,7 @@ Mask(DOUBLE_FLOAT)
Mask(RVC)

Mask(RVE)
+
+mriscv-attribute
+Target Report Var(riscv_emit_attribute_p) Init(-1)
+Emit RISC-V attribute.
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 7837035..666ae97 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -4881,6 +4881,13 @@ pointers into PC-relative form.])
[Requesting --with-nan= requires assembler support for -mnan=])
fi
;;
+ riscv*-*-*)
+ gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
+ gcc_cv_as_riscv_attribute, [2,32,0],,
+ [.attribute stack_align,4],,
+ [AC_DEFINE(HAVE_AS_RISCV_ATTRIBUTE, 1,
+ [Define if your assembler supports .attribute.])])
+ ;;
s390*-*-*)
gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
gcc_cv_as_s390_gnu_attribute, [2,18,0],,
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 1d925eb..666e536 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -2161,6 +2161,14 @@ is used, it is enabled on Linux/x86 if target binutils
supports @code{Intel CET} instructions and disabled otherwise.
In this case the target libraries are configured to get additional
@option{-fcf-protection} option.
+
+@item --with-riscv-attribute=@samp{yes}, @samp{no} or @samp{default}
+Generate RISC-V attribute by default, in order to record extra build information
+in object.
+
+The option is disabled by default. It is enabled on RISC-V/ELF (bare-metal)
+target if target binutils supported.
+
@end table

@subheading Cross-Compiler-Specific Options
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index f5044a6..be09abf 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1057,7 +1057,8 @@ See RS/6000 and PowerPC Options.
-mstrict-align -mno-strict-align @gol
-mcmodel=medlow -mcmodel=medany @gol
-mexplicit-relocs -mno-explicit-relocs @gol
--mrelax -mno-relax}
+-mrelax -mno-relax @gol
+-mriscv-attribute -mmo-riscv-attribute}

@emph{RL78 Options}
@gccoptlist{-msim -mmul=none -mmul=g13 -mmul=g14 -mallregs @gol
@@ -23798,6 +23799,10 @@ Take advantage of linker relaxations to reduce the number of instructions
required to materialize symbol addresses. The default is to take advantage of
linker relaxations.

+@item -memit-attribute
+@itemx -mno-emit-attribute
+Emit RISC-V attribute to record extra information into ELF objects.
+
@end table

@node RL78 Options
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-1.c b/gcc/testsuite/gcc.target/riscv/attribute-1.c
new file mode 100644
index 0000000..e835876
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-1.c
@@ -0,0 +1,7 @@
+/* Verify the return instruction is mret. */
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-2.c b/gcc/testsuite/gcc.target/riscv/attribute-2.c
new file mode 100644
index 0000000..f7aa066
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-2.c
@@ -0,0 +1,7 @@
+/* Verify the return instruction is mret. */
+/* { dg-do compile } */
+/* { dg-options "-O -mno-riscv-attribute" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler-not ".attribute arch" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-3.c b/gcc/testsuite/gcc.target/riscv/attribute-3.c
new file mode 100644
index 0000000..0bd2523
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-3.c
@@ -0,0 +1,7 @@
+/* Verify the return instruction is mret. */
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -mpreferred-stack-boundary=8" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute stack_align, 256" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-4.c b/gcc/testsuite/gcc.target/riscv/attribute-4.c
new file mode 100644
index 0000000..51240b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-4.c
@@ -0,0 +1,7 @@
+/* Verify the return instruction is mret. */
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -mstrict-align" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute unaligned_access, 0" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-5.c b/gcc/testsuite/gcc.target/riscv/attribute-5.c
new file mode 100644
index 0000000..d500534
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-5.c
@@ -0,0 +1,7 @@
+/* Verify the return instruction is mret. */
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -mno-strict-align" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute unaligned_access, 1" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-6.c b/gcc/testsuite/gcc.target/riscv/attribute-6.c
new file mode 100644
index 0000000..6a034b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-6.c
@@ -0,0 +1,7 @@
+/* Verify the return instruction is mret. */
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32g2p0 -mabi=ilp32" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_m2p0_a2p0_f2p0_d2p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-7.c b/gcc/testsuite/gcc.target/riscv/attribute-7.c
new file mode 100644
index 0000000..f48bbee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-7.c
@@ -0,0 +1,7 @@
+/* Verify the return instruction is mret. */
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32e1p9 -mabi=ilp32e" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32e1p9\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-8.c b/gcc/testsuite/gcc.target/riscv/attribute-8.c
new file mode 100644
index 0000000..0a74e69
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-8.c
@@ -0,0 +1,7 @@
+/* Verify the return instruction is mret. */
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32i2p0xv5_xabc -mabi=ilp32" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_xv5p0_xabc2p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-9.c b/gcc/testsuite/gcc.target/riscv/attribute-9.c
new file mode 100644
index 0000000..6db2509
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-9.c
@@ -0,0 +1,7 @@
+/* Verify the return instruction is mret. */
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32i2p0xbar_sabc_sxfoo -mabi=ilp32e" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_xbar2p0_sabc2p0_sxfoo2p0\"" } } */
--
1.8.3.1

Jim Wilson

unread,
Feb 20, 2019, 9:31:26 PM2/20/19
to Kito Cheng, Kito Cheng, GCC Patches, RISC-V Patches, Palmer Dabbelt
This looks pretty good to me, and looks like it works the same way as
the binutils patches that already went in before the binutils-2.32
release. I just see some minor issues that need fixing.

On Tue, Feb 12, 2019 at 11:17 PM Kito Cheng <ki...@andestech.com> wrote:
>
> From: Kito Cheng <kito....@gmail.com>
>
> Kito Cheng <kito....@gmail.com>
> Monk Chiang <sh.ch...@gmail.com>
>
> ChangeLog:
> gcc:
> * common/config/riscv/riscv-common.c:
> Include config/riscv/riscv-protos.h.
> (INCLUDE_STRING): Defined.
> (RISCV_DONT_CARE_VERSION): Defined.
> (riscv_subset_t): Declare.

Doesn't mention riscv_subset_t::riscv_subset_t.
Localtion -> Location.
Looks like the first item in the list never gets freed. I think this
should be just "this->m_head;".
Except this actually does do version checking, if versions are not
RISCV_DONT_CARE_VERSION. The comment needs to be clarified.
contain -> contains
We don't found -> We didn't find
This doesn't follow GNU style. There shouldn't be an open paren at
the end of the line, just start putting the args there.

> + add ("i", major_version, minor_version);
> + break;
>
> - if (*flags & MASK_64BIT)
> + case 'e':
> + p++;
> + p = parsing_subset_version (
> + p, &major_version, &minor_version,
> + /* default_major_version= */ 1,
> + /* default_minor_version= */ 9,
> + /* std_ext_p= */true);

This doesn't follow GNU style. There shouldn't be an open paren at
the end of the line, just start putting the args there.

> +
> + add ("e", major_version, minor_version);
> +
> + if (m_xlen > 32)
> + {
> + error_at (m_loc, "-march=%s: rv%de is not a valid base ISA",
> + m_arch, m_xlen);
> + return NULL;
> + }
> +

This blank line should be deleted.

> + break;
> +
> + case 'g':
> + p++;
> + p = parsing_subset_version (
> + p, &major_version, &minor_version,
> + /* default_major_version= */ 2,
> + /* default_minor_version= */ 0,
> + /* std_ext_p= */true);

This doesn't follow GNU style. There shouldn't be an open paren at
the end of the line, just start putting the args there.
This doesn't follow GNU style. There shouldn't be an open paren at
the end of the line, just start putting the args there.

> +
> + *q = '\0';
> +
> + add (subset, major_version, minor_version);
> + free (subset);
> + p += end_of_version - subset;
> +
> + if (*p != '\0' && *p != '_')
> + {
> + error_at (m_loc, "-march=%s: %s must seperate with _",

seperate -> separate
This comment isn't valid for this testcase and should be dropped or
updated. Likewise for all of the other testcases.

> +/* { dg-do compile } */
> +/* { dg-options "-O -march=rv32I -mabi=ilp32" } */
> +int foo()
> +{
> +}
> +/* { dg-error ".-march=rv32I: first ISA subset must be `e', `i' or `g'" "" { target *-*-* } 0 } */

The arch-1.c testcase fails for a 64-bit target. I get
cc1: error: -march=rv32I: first ISA subset must be `e', `i' or `g'^M
cc1: error: ABI requires -march=rv32^M
compiler exited with status 1
PASS: gcc.target/riscv/arch-1.c (test for errors, line )
FAIL: gcc.target/riscv/arch-1.c (test for excess errors)
the actual options passed to gcc by the testsuite infrastructure are
-march=rv64gc -mabi=lp64d -march=rv32I -mabi=ilp32
since the rv32I fails, the rv64gc takes effect and conflicts with the ilp32 abi
we can fix this by adding a -march=rv32i option after the failing one,
we still get the error, and the last one wins so avoids the ilp32 abi
conflict

Jim Wilson

unread,
Feb 20, 2019, 9:40:09 PM2/20/19
to Kito Cheng, Kito Cheng, GCC Patches, RISC-V Patches, Palmer Dabbelt
This also looks mostly OK to me with only some minor issues that need
to be fixed.

On Tue, Feb 12, 2019 at 11:17 PM Kito Cheng <ki...@andestech.com> wrote:
>
> From: Kito Cheng <kito....@gmail.com>
>
> This patch added a configure time option, --with-riscv-attribute=[yes|no|default],
> run time option, -mriscv-attribute to control the output of ELF attribute.
>
> This feature is only enabled by default for ELF/Bare mental target
> configuration.
>
> Kito Cheng <kito....@gmail.com>
> Monk Chiang <sh.ch...@gmail.com>
>
> ChangeLog:
> gcc:
> * common/config/riscv/riscv-common.c: Include sstream.
> (riscv_subset_list::to_string): New.
> (riscv_arch_str): Likewise.
> * config.gcc (riscv*-*-*): Hanlde --with-riscv-attribute=

Hanlde -> Handle

> * config.in: Regen
> * config/riscv/riscv-protos.h (riscv_arch_str): New.
> * config/riscv/riscv.c (INCLUDE_STRING): Defined.
> (riscv_emit_attribute): New.
> (riscv_file_start): Emit attribute if needed.
> (riscv_option_override): Init riscv_emit_attribute_p.
> * config/riscv/riscv.opt (mriscv-attribute): New option.
> * configure.ac (riscv*-*-*): Check binutils is supporting ELF
> attribute.

Should be a line that says configure was regenerated. The actual
patch wasn't included but tends not to be very useful if other people
modify configure meanwhile, but we still need the changelog entry.
I'd suggest "Emit RISC-V ELF attribute" to avoid confusion with C attributes.

> diff --git a/gcc/configure.ac b/gcc/configure.ac
> index 7837035..666ae97 100644
> --- a/gcc/configure.ac
> +++ b/gcc/configure.ac
> @@ -4881,6 +4881,13 @@ pointers into PC-relative form.])
> [Requesting --with-nan= requires assembler support for -mnan=])
> fi
> ;;
> + riscv*-*-*)
> + gcc_GAS_CHECK_FEATURE([.gnu_attribute support],

The comment says ".gnu_attribute support" but it is actually .attribute not
.gnu_attribute that we support here.

> + gcc_cv_as_riscv_attribute, [2,32,0],,
> + [.attribute stack_align,4],,
> + [AC_DEFINE(HAVE_AS_RISCV_ATTRIBUTE, 1,
> + [Define if your assembler supports .attribute.])])
> + ;;
> s390*-*-*)
> gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
> gcc_cv_as_s390_gnu_attribute, [2,18,0],,
> diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
> index 1d925eb..666e536 100644
> --- a/gcc/doc/install.texi
> +++ b/gcc/doc/install.texi
> @@ -2161,6 +2161,14 @@ is used, it is enabled on Linux/x86 if target binutils
> supports @code{Intel CET} instructions and disabled otherwise.
> In this case the target libraries are configured to get additional
> @option{-fcf-protection} option.
> +
> +@item --with-riscv-attribute=@samp{yes}, @samp{no} or @samp{default}
> +Generate RISC-V attribute by default, in order to record extra build information

This line is over 80 chars long, can just move information to the next line.

> +in object.
> +
> +The option is disabled by default. It is enabled on RISC-V/ELF (bare-metal)
> +target if target binutils supported.
> +

Don't need the blank line here.

> @end table
>
> @subheading Cross-Compiler-Specific Options
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index f5044a6..be09abf 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -1057,7 +1057,8 @@ See RS/6000 and PowerPC Options.
> -mstrict-align -mno-strict-align @gol
> -mcmodel=medlow -mcmodel=medany @gol
> -mexplicit-relocs -mno-explicit-relocs @gol
> --mrelax -mno-relax}
> +-mrelax -mno-relax @gol
> +-mriscv-attribute -mmo-riscv-attribute}
>
> @emph{RL78 Options}
> @gccoptlist{-msim -mmul=none -mmul=g13 -mmul=g14 -mallregs @gol
> @@ -23798,6 +23799,10 @@ Take advantage of linker relaxations to reduce the number of instructions
> required to materialize symbol addresses. The default is to take advantage of
> linker relaxations.
>
> +@item -memit-attribute
> +@itemx -mno-emit-attribute
> +Emit RISC-V attribute to record extra information into ELF objects.
> +

I'd suggest "Emit (do not emit)" since one option turns it on and the other
turns it off.

We don't need the blank line here.

Maybe this should mention that it depends on GNU as 2.32, or maybe we can add
code to check for this case where the user turns it on but the assembler
doesn't support it, and give an error?

> @end table
>
> @node RL78 Options
> diff --git a/gcc/testsuite/gcc.target/riscv/attribute-1.c b/gcc/testsuite/gcc.target/riscv/attribute-1.c
> new file mode 100644
> index 0000000..e835876
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/attribute-1.c
> @@ -0,0 +1,7 @@
> +/* Verify the return instruction is mret. */

The comment is wrong as in the previous patch.
Reply all
Reply to author
Forward
0 new messages