Hi, The patch adds support for __attribute__ ((code_readable)) with optional argument that accepts `no', `yes' or `pcrel' just like the -mcode-readable= command line switch. If the argument is not specified then the default `yes' is applied.
This of course has only effect on targets supporting -mcode-readable=. Regards, Robert 2016-05-24 Matthew Fortune <matthew.fort...@imgtec.com> Simon Dardis <simon.dar...@imgtec.com> gcc/ * config/mips/mips.c (mips_base_code_readable): New. (mips_handle_code_readable_attr): New static function. (mips_get_code_readable_attr): Likewise. (mips_set_current_function): Add support for the code_readable attribute. (mips_option_override): Likewise. * doc/extend.text: Document the new attribute. gcc/testsuite/ * gcc.target/mips/code-readable-attr-1.c: New test. * gcc.target/mips/code-readable-attr-2.c: Ditto. * gcc.target/mips/code-readable-attr-3.c: Ditto. * gcc.target/mips/code-readable-attr-4.c: Ditto. * gcc.target/mips/code-readable-attr-5.c: Ditto. --- gcc/config/mips/mips.c | 94 +++++++++++++++++++++- gcc/doc/extend.texi | 17 ++++ .../gcc.target/mips/code-readable-attr-1.c | 51 ++++++++++++ .../gcc.target/mips/code-readable-attr-2.c | 49 +++++++++++ .../gcc.target/mips/code-readable-attr-3.c | 50 ++++++++++++ .../gcc.target/mips/code-readable-attr-4.c | 51 ++++++++++++ .../gcc.target/mips/code-readable-attr-5.c | 5 ++ 7 files changed, 316 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/mips/code-readable-attr-1.c create mode 100644 gcc/testsuite/gcc.target/mips/code-readable-attr-2.c create mode 100644 gcc/testsuite/gcc.target/mips/code-readable-attr-3.c create mode 100644 gcc/testsuite/gcc.target/mips/code-readable-attr-4.c create mode 100644 gcc/testsuite/gcc.target/mips/code-readable-attr-5.c diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 24d98fe..6a469a2 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -492,6 +492,9 @@ static int mips_base_target_flags; /* The default compression mode. */ unsigned int mips_base_compression_flags; +/* The default code readable setting. */ +enum mips_code_readable_setting mips_base_code_readable; + /* The ambient values of other global variables. */ static int mips_base_schedule_insns; /* flag_schedule_insns */ static int mips_base_reorder_blocks_and_partition; /* flag_reorder... */ @@ -596,6 +599,7 @@ const enum reg_class mips_regno_to_class[FIRST_PSEUDO_REGISTER] = { ALL_REGS, ALL_REGS, ALL_REGS, ALL_REGS }; +static tree mips_handle_code_readable_attr (tree *, tree, tree, int, bool *); static tree mips_handle_interrupt_attr (tree *, tree, tree, int, bool *); static tree mips_handle_use_shadow_register_set_attr (tree *, tree, tree, int, bool *); @@ -616,6 +620,8 @@ static const struct attribute_spec mips_attribute_table[] = { { "micromips", 0, 0, true, false, false, NULL, false }, { "nomicromips", 0, 0, true, false, false, NULL, false }, { "nocompression", 0, 0, true, false, false, NULL, false }, + { "code_readable", 0, 1, true, false, false, mips_handle_code_readable_attr, + false }, /* Allow functions to be specified as interrupt handlers */ { "interrupt", 0, 1, false, true, true, mips_handle_interrupt_attr, false }, @@ -1296,6 +1302,77 @@ mips_use_debug_exception_return_p (tree type) TYPE_ATTRIBUTES (type)) != NULL; } +/* Verify the arguments to a code_readable attribute. */ + +static tree +mips_handle_code_readable_attr (tree *node, tree name, tree args, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + const char * str; + + if (!is_attribute_p ("code_readable", name) || args == NULL) + return NULL_TREE; + + if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) + { + warning (OPT_Wattributes, + "%qE attribute requires a string argument", name); + *no_add_attrs = true; + } + else if (strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "no") != 0 + && strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "pcrel") != 0 + && strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "yes") != 0) + { + warning (OPT_Wattributes, + "argument to %qE attribute is neither no, pcrel nor yes", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Return the code_readable setting for a function if it has one. If there + is no argument or the function does not have the attribute, return GCC's + default. */ + +static enum mips_code_readable_setting +mips_get_code_readable_attr (tree decl) +{ + tree attr; + + if (decl == NULL) + return mips_base_code_readable; + + attr = lookup_attribute ("code_readable", DECL_ATTRIBUTES (decl)); + + if (attr != NULL) + { + if (TREE_VALUE (attr) != NULL_TREE) + { + const char * str; + + str = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))); + if (strcmp (str, "no") == 0) + return CODE_READABLE_NO; + else if (strcmp (str, "pcrel") == 0) + return CODE_READABLE_PCREL; + else if (strcmp (str, "yes") == 0) + return CODE_READABLE_YES; + + /* mips_handle_code_readable_attr will have verified that + the arguments are correct before adding the attribute. */ + gcc_unreachable (); + } + + /* Just like GCC's default -mcode-readable= setting, the presence of + the code_readable attribute implies that a function can read data + from the instruction stream by default. */ + return CODE_READABLE_YES; + } + + return mips_base_code_readable; +} + /* Return the set of compression modes that are explicitly required by the attributes in ATTRIBUTES. */ @@ -19441,12 +19518,25 @@ mips_set_compression_mode (unsigned int compression_mode) /* Implement TARGET_SET_CURRENT_FUNCTION. Decide whether the current function should use the MIPS16 or microMIPS ISA and switch modes - accordingly. */ + accordingly. Also set the current code_readable mode. */ static void mips_set_current_function (tree fndecl) { + enum mips_code_readable_setting old_code_readable = mips_code_readable; + mips_set_compression_mode (mips_get_compress_mode (fndecl)); + + mips_code_readable = mips_get_code_readable_attr (fndecl); + + /* Since the mips_code_readable setting has potientially changed, the + relocation tables must be reinitialized. Otherwise GCC will not + split symbols for functions that are code_readable ("no") when others + are code_readable ("yes") and ICE later on in places such as + mips_emit_move. Ditto for similar paired cases. It must be restored + to its previous state as well. */ + if (old_code_readable != mips_code_readable) + mips_init_relocs (); } /* Allocate a chunk of memory for per-function machine-dependent data. */ @@ -19576,6 +19666,8 @@ mips_option_override (void) mips_base_compression_flags = TARGET_COMPRESSION; target_flags &= ~TARGET_COMPRESSION; + mips_base_code_readable = mips_code_readable; + /* -mno-float overrides -mhard-float and -msoft-float. */ if (TARGET_NO_FLOAT) { diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index e4d6c1c..dd23c70 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -4441,6 +4441,23 @@ On MIPS targets, you can use the @code{nocompression} function attribute to locally turn off MIPS16 and microMIPS code generation. This attribute overrides the @option{-mips16} and @option{-mmicromips} options on the command line (@pxref{MIPS Options}). + +@item code_readable +@cindex @code{code_readable} function attribute, MIPS +For MIPS targets that support PC-relative addressing modes, this attribute +can be used to control how an object is addressed. The attribute takes +a single optional argument: + +@table @samp +@item no +The function should not read the instruction stream as data. +@item yes +The function can read the instruction stream as data. +@item pcrel +The function can read the instruction stream in a pc-relative mode. +@end table + +If there is no argument supplied, the default of @code{"yes"} applies. @end table @node MSP430 Function Attributes diff --git a/gcc/testsuite/gcc.target/mips/code-readable-attr-1.c b/gcc/testsuite/gcc.target/mips/code-readable-attr-1.c new file mode 100644 index 0000000..4ccb27c --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/code-readable-attr-1.c @@ -0,0 +1,51 @@ +/* { dg-options "(-mips16) -mgp32 addressing=absolute" } */ +/* { dg-skip-if ".half requires -O" { *-*-* } { "-O0" } { "" } } */ + +volatile int x1; +volatile int x2; +volatile int x3; +volatile int x4; +volatile int x5; +volatile int x6; +volatile int x7; +volatile int x8; +volatile int x9; +volatile int x10; +volatile int x11; + +MIPS16 __attribute__ ((code_readable)) int +foo (int i, volatile int *x) +{ + switch (i) + { + case 1: return x1 + x[0]; + case 2: return x2 + x[1]; + case 3: return x3 + x[2]; + case 4: return x4 + x[3]; + case 5: return x5 + x[4]; + case 6: return x6 + x[5]; + case 7: return x7 + x[6]; + case 8: return x8 + x[7]; + case 9: return x9 + x[8]; + case 10: return x10 + x[9]; + case 11: return x11 + x[10]; + default: return 0; + } +} + +extern int k[]; + +MIPS16 __attribute__ ((code_readable)) int * +bar (void) +{ + return k; +} + +/* { dg-final { scan-assembler "\tla\t" } } */ +/* { dg-final { scan-assembler "\t\\.half\t" } } */ +/* { dg-final { scan-assembler-not "%hi\\(\[^)\]*L" } } */ +/* { dg-final { scan-assembler-not "%lo\\(\[^)\]*L" } } */ + +/* { dg-final { scan-assembler "\t\\.word\tk\n" } } */ +/* { dg-final { scan-assembler-not "%hi\\(k\\)" } } */ +/* { dg-final { scan-assembler-not "%lo\\(k\\)" } } */ diff --git a/gcc/testsuite/gcc.target/mips/code-readable-attr-2.c b/gcc/testsuite/gcc.target/mips/code-readable-attr-2.c new file mode 100644 index 0000000..c7dd511 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/code-readable-attr-2.c @@ -0,0 +1,49 @@ +/* { dg-options "(-mips16) -mgp32 addressing=absolute" } */ + +volatile int x1; +volatile int x2; +volatile int x3; +volatile int x4; +volatile int x5; +volatile int x6; +volatile int x7; +volatile int x8; +volatile int x9; +volatile int x10; +volatile int x11; + +MIPS16 __attribute__((code_readable ("pcrel"))) int +foo (int i, volatile int *x) +{ + switch (i) + { + case 1: return x1 + x[0]; + case 2: return x2 + x[1]; + case 3: return x3 + x[2]; + case 4: return x4 + x[3]; + case 5: return x5 + x[4]; + case 6: return x6 + x[5]; + case 7: return x7 + x[6]; + case 8: return x8 + x[7]; + case 9: return x9 + x[8]; + case 10: return x10 + x[9]; + case 11: return x11 + x[10]; + default: return 0; + } +} + +extern int k[]; + +MIPS16 __attribute__((code_readable ("pcrel"))) int * +bar (void) +{ + return k; +} + +/* { dg-final { scan-assembler-not "\tla\t" } } */ +/* { dg-final { scan-assembler-not "\t\\.half\t" } } */ +/* { dg-final { scan-assembler "\t\\.word\t\[^\n\]*L" } } */ + +/* { dg-final { scan-assembler "\t\\.word\tk\n" } } */ +/* { dg-final { scan-assembler-not "%hi\\(k\\)" } } */ +/* { dg-final { scan-assembler-not "%lo\\(k\\)" } } */ diff --git a/gcc/testsuite/gcc.target/mips/code-readable-attr-3.c b/gcc/testsuite/gcc.target/mips/code-readable-attr-3.c new file mode 100644 index 0000000..99c13a9 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/code-readable-attr-3.c @@ -0,0 +1,50 @@ +/* { dg-options "(-mips16) -mgp32 addressing=absolute" } */ + +volatile int x1; +volatile int x2; +volatile int x3; +volatile int x4; +volatile int x5; +volatile int x6; +volatile int x7; +volatile int x8; +volatile int x9; +volatile int x10; +volatile int x11; + +MIPS16 __attribute__((code_readable ("no"))) int +foo (int i, volatile int *x) +{ + switch (i) + { + case 1: return x1 + x[0]; + case 2: return x2 + x[1]; + case 3: return x3 + x[2]; + case 4: return x4 + x[3]; + case 5: return x5 + x[4]; + case 6: return x6 + x[5]; + case 7: return x7 + x[6]; + case 8: return x8 + x[7]; + case 9: return x9 + x[8]; + case 10: return x10 + x[9]; + case 11: return x11 + x[10]; + default: return 0; + } +} + +extern int k[]; + +MIPS16 __attribute__((code_readable ("no"))) int * +bar (void) +{ + return k; +} + +/* { dg-final { scan-assembler-not "\tla\t" } } */ +/* { dg-final { scan-assembler-not "\t\\.half\t" } } */ +/* { dg-final { scan-assembler "%hi\\(\[^)\]*L" } } */ +/* { dg-final { scan-assembler "%lo\\(\[^)\]*L" } } */ + +/* { dg-final { scan-assembler-not "\t\\.word\tk\n" } } */ +/* { dg-final { scan-assembler "%hi\\(k\\)" } } */ +/* { dg-final { scan-assembler "%lo\\(k\\)" } } */ diff --git a/gcc/testsuite/gcc.target/mips/code-readable-attr-4.c b/gcc/testsuite/gcc.target/mips/code-readable-attr-4.c new file mode 100644 index 0000000..9e3baa0 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/code-readable-attr-4.c @@ -0,0 +1,51 @@ +/* { dg-options "(-mips16) -mabi=eabi -mgp64" } */ +/* { dg-skip-if ".half requires -O" { *-*-* } { "-O0" } { "" } } */ + +volatile int x1; +volatile int x2; +volatile int x3; +volatile int x4; +volatile int x5; +volatile int x6; +volatile int x7; +volatile int x8; +volatile int x9; +volatile int x10; +volatile int x11; + +MIPS16 __attribute__((code_readable ("yes"))) int +foo (int i, volatile int *x) +{ + switch (i) + { + case 1: return x1 + x[0]; + case 2: return x2 + x[1]; + case 3: return x3 + x[2]; + case 4: return x4 + x[3]; + case 5: return x5 + x[4]; + case 6: return x6 + x[5]; + case 7: return x7 + x[6]; + case 8: return x8 + x[7]; + case 9: return x9 + x[8]; + case 10: return x10 + x[9]; + case 11: return x11 + x[10]; + default: return 0; + } +} + +extern int k[]; + +MIPS16 __attribute__((code_readable ("yes"))) int * +bar (void) +{ + return k; +} + +/* { dg-final { scan-assembler "\tla\t" } } */ +/* { dg-final { scan-assembler "\t\\.half\t" } } */ +/* { dg-final { scan-assembler-not "%hi\\(\[^)\]*L" } } */ +/* { dg-final { scan-assembler-not "%lo\\(\[^)\]*L" } } */ + +/* { dg-final { scan-assembler "\t\\.dword\tk\n" } } */ +/* { dg-final { scan-assembler-not "%hi\\(k\\)" } } */ +/* { dg-final { scan-assembler-not "%lo\\(k\\)" } } */ diff --git a/gcc/testsuite/gcc.target/mips/code-readable-attr-5.c b/gcc/testsuite/gcc.target/mips/code-readable-attr-5.c new file mode 100644 index 0000000..0a547a9 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/code-readable-attr-5.c @@ -0,0 +1,5 @@ +/* { dg-options "(-mips16) isa_rev<=5" } */ + + __attribute__((code_readable ("magic"))) int foo () {} /* { dg-warning "argument to 'code_readable' attribute is neither no, pcrel nor yes" } */ + + __attribute__((code_readable (1))) int * bar () {} /* { dg-warning "'code_readable' attribute requires a string argument" } */ -- 2.8.2.396.g5fe494c