MIPS/GCC: Mark text contents as code or data
authorMaciej W. Rozycki <macro@imgtec.com>
Wed, 16 Nov 2016 17:12:08 +0000 (17:12 +0000)
committerMaciej W. Rozycki <macro@gcc.gnu.org>
Wed, 16 Nov 2016 17:12:08 +0000 (17:12 +0000)
gcc/
* config/mips/mips-protos.h (mips_set_text_contents_type): New
prototype.
* config/mips/mips.h (ASM_OUTPUT_BEFORE_CASE_LABEL): New macro.
(ASM_OUTPUT_CASE_END): Likewise.
* config/mips/mips.c (mips_set_text_contents_type): New
function.
(mips16_emit_constants): Record the pool's initial label number
with the `consttable' insn.  Emit a `consttable_end' insn at the
end.
(mips_final_prescan_insn): Call `mips_set_text_contents_type'
for `consttable' insns.
(mips_final_postscan_insn): Call `mips_set_text_contents_type'
for `consttable_end' insns.
* config/mips/mips.md (unspec): Add UNSPEC_CONSTTABLE_END enum
value.
(consttable): Add operand.
(consttable_end): New insn.

gcc/testsuite/
* gcc.target/mips/data-sym-jump.c: New test case.
* gcc.target/mips/data-sym-pool.c: New test case.
* gcc.target/mips/insn-pseudo-4.c: Adjust for constant pool
annotation.

From-SVN: r242502

gcc/ChangeLog
gcc/config/mips/mips-protos.h
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/data-sym-jump.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/data-sym-pool.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/insn-pseudo-4.c

index 3a48f13122cea987b0ba96df1bae5088dd96a2d5..6f46dd404f2de58374c5e969d5bd16055f5aee9a 100644 (file)
@@ -1,3 +1,23 @@
+2016-11-16  Maciej W. Rozycki  <macro@imgtec.com>
+
+       * config/mips/mips-protos.h (mips_set_text_contents_type): New
+       prototype.
+       * config/mips/mips.h (ASM_OUTPUT_BEFORE_CASE_LABEL): New macro.
+       (ASM_OUTPUT_CASE_END): Likewise.
+       * config/mips/mips.c (mips_set_text_contents_type): New
+       function.
+       (mips16_emit_constants): Record the pool's initial label number
+       with the `consttable' insn.  Emit a `consttable_end' insn at the
+       end.
+       (mips_final_prescan_insn): Call `mips_set_text_contents_type'
+       for `consttable' insns.
+       (mips_final_postscan_insn): Call `mips_set_text_contents_type'
+       for `consttable_end' insns.
+       * config/mips/mips.md (unspec): Add UNSPEC_CONSTTABLE_END enum
+       value.
+       (consttable): Add operand.
+       (consttable_end): New insn.
+
 2016-11-16  Yuri Rumyantsev  <ysrumyan@gmail.com>
 
        * params.def (PARAM_VECT_EPILOGUES_NOMASK): New.
index 09cf6626e273b042de9d5f84e3ba0062031f1b40..117c78cc34f1f9e640fb0f669a0e1808cfbaed3d 100644 (file)
@@ -271,6 +271,8 @@ extern void mips_declare_object (FILE *, const char *, const char *,
                                 const char *, ...) ATTRIBUTE_PRINTF_4;
 extern void mips_declare_object_name (FILE *, const char *, tree);
 extern void mips_finish_declare_object (FILE *, tree, int, int);
+extern void mips_set_text_contents_type (FILE *, const char *,
+                                        unsigned long, bool);
 
 extern bool mips_small_data_pattern_p (rtx);
 extern rtx mips_rewrite_small_data (rtx);
index 44cdeb72c1d41823091e4032983ae472cdfa53c3..10c20393ca4a7e292adc6ba8992ce38bf7165148 100644 (file)
@@ -9749,6 +9749,37 @@ mips_finish_declare_object (FILE *stream, tree decl, int top_level, int at_end)
     }
 }
 #endif
+
+/* Mark text contents as code or data, mainly for the purpose of correct
+   disassembly.  Emit a local symbol and set its type appropriately for
+   that purpose.  Also emit `.insn' if marking contents as code so that
+   the ISA mode is recorded and any padding that follows is disassembled
+   as correct instructions.  */
+
+void
+mips_set_text_contents_type (FILE *file ATTRIBUTE_UNUSED,
+                            const char *prefix ATTRIBUTE_UNUSED,
+                            unsigned long num ATTRIBUTE_UNUSED,
+                            bool function_p ATTRIBUTE_UNUSED)
+{
+#ifdef ASM_OUTPUT_TYPE_DIRECTIVE
+  char buf[(sizeof (num) * 10) / 4 + 2];
+  const char *fnname;
+  char *sname;
+  rtx symbol;
+
+  sprintf (buf, "%lu", num);
+  symbol = XEXP (DECL_RTL (current_function_decl), 0);
+  fnname = targetm.strip_name_encoding (XSTR (symbol, 0));
+  sname = ACONCAT ((prefix, fnname, "_", buf, NULL));
+
+  ASM_OUTPUT_TYPE_DIRECTIVE (file, sname, function_p ? "function" : "object");
+  assemble_name (file, sname);
+  fputs (":\n", file);
+  if (function_p)
+    fputs ("\t.insn\n", file);
+#endif
+}
 \f
 /* Return the FOO in the name of the ".mdebug.FOO" section associated
    with the current ABI.  */
@@ -17131,17 +17162,22 @@ mips16_emit_constants_1 (machine_mode mode, rtx value, rtx_insn *insn)
   gcc_unreachable ();
 }
 
-/* Dump out the constants in CONSTANTS after INSN.  */
+/* Dump out the constants in CONSTANTS after INSN.  Record the initial
+   label number in the `consttable' and `consttable_end' insns emitted
+   at the beginning and the end of the constant pool respectively, so
+   that individual pools can be uniquely marked as data for the purpose
+   of disassembly.  */
 
 static void
 mips16_emit_constants (struct mips16_constant *constants, rtx_insn *insn)
 {
+  int label_num = constants ? CODE_LABEL_NUMBER (constants->label) : 0;
   struct mips16_constant *c, *next;
   int align;
 
   align = 0;
   if (constants)
-    insn = emit_insn_after (gen_consttable (), insn);
+    insn = emit_insn_after (gen_consttable (GEN_INT (label_num)), insn);
   for (c = constants; c != NULL; c = next)
     {
       /* If necessary, increase the alignment of PC.  */
@@ -17158,6 +17194,8 @@ mips16_emit_constants (struct mips16_constant *constants, rtx_insn *insn)
       next = c->next;
       free (c);
     }
+  if (constants)
+    insn = emit_insn_after (gen_consttable_end (GEN_INT (label_num)), insn);
 
   emit_barrier_after (insn);
 }
@@ -20268,16 +20306,32 @@ mips_need_noat_wrapper_p (rtx_insn *insn, rtx *opvec, int noperands)
   return false;
 }
 
-/* Implement FINAL_PRESCAN_INSN.  */
+/* Implement FINAL_PRESCAN_INSN.  Mark MIPS16 inline constant pools
+   as data for the purpose of disassembly.  For simplicity embed the
+   pool's initial label number in the local symbol produced so that
+   multiple pools within a single function end up marked with unique
+   symbols.  The label number is carried by the `consttable' insn
+   emitted at the beginning of each pool.  */
 
 void
 mips_final_prescan_insn (rtx_insn *insn, rtx *opvec, int noperands)
 {
+  if (INSN_P (insn)
+      && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
+      && XINT (PATTERN (insn), 1) == UNSPEC_CONSTTABLE)
+    mips_set_text_contents_type (asm_out_file, "__pool_",
+                                XINT (XVECEXP (PATTERN (insn), 0, 0), 0),
+                                FALSE);
+
   if (mips_need_noat_wrapper_p (insn, opvec, noperands))
     mips_push_asm_switch (&mips_noat);
 }
 
-/* Implement TARGET_ASM_FINAL_POSTSCAN_INSN.  */
+/* Implement TARGET_ASM_FINAL_POSTSCAN_INSN.  Reset text marking to
+   code after a MIPS16 inline constant pool.  Like with the beginning
+   of a pool table use the pool's initial label number to keep symbols
+   unique.  The label number is carried by the `consttable_end' insn
+   emitted at the end of each pool.  */
 
 static void
 mips_final_postscan_insn (FILE *file ATTRIBUTE_UNUSED, rtx_insn *insn,
@@ -20285,6 +20339,13 @@ mips_final_postscan_insn (FILE *file ATTRIBUTE_UNUSED, rtx_insn *insn,
 {
   if (mips_need_noat_wrapper_p (insn, opvec, noperands))
     mips_pop_asm_switch (&mips_noat);
+
+  if (INSN_P (insn)
+      && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
+      && XINT (PATTERN (insn), 1) == UNSPEC_CONSTTABLE_END)
+    mips_set_text_contents_type (asm_out_file, "__pend_",
+                                XINT (XVECEXP (PATTERN (insn), 0, 0), 0),
+                                TRUE);
 }
 
 /* Return the function that is used to expand the <u>mulsidi3 pattern.
index 12662a7ea396b63b87dcca309650529b9961451d..bb66c428dd1a7d0546974fe890590ed93595f13b 100644 (file)
@@ -2986,6 +2986,32 @@ do {                                                                     \
             LOCAL_LABEL_PREFIX, VALUE);                                \
 } while (0)
 
+/* Mark inline jump tables as data for the purpose of disassembly.  For
+   simplicity embed the jump table's label number in the local symbol
+   produced so that multiple jump tables within a single function end
+   up marked with unique symbols.  Retain the alignment setting from
+   `elfos.h' as we are replacing the definition from there.  */
+
+#undef ASM_OUTPUT_BEFORE_CASE_LABEL
+#define ASM_OUTPUT_BEFORE_CASE_LABEL(STREAM, PREFIX, NUM, TABLE)       \
+  do                                                                   \
+    {                                                                  \
+      ASM_OUTPUT_ALIGN ((STREAM), 2);                                  \
+      if (JUMP_TABLES_IN_TEXT_SECTION)                                 \
+       mips_set_text_contents_type (STREAM, "__jump_", NUM, FALSE);    \
+    }                                                                  \
+  while (0);
+
+/* Reset text marking to code after an inline jump table.  Like with
+   the beginning of a jump table use the label number to keep symbols
+   unique.  */
+
+#define ASM_OUTPUT_CASE_END(STREAM, NUM, TABLE)                                \
+  do                                                                   \
+    if (JUMP_TABLES_IN_TEXT_SECTION)                                   \
+      mips_set_text_contents_type (STREAM, "__jend_", NUM, TRUE);      \
+  while (0);
+
 /* This is how to output an assembler line
    that says to advance the location counter
    to a multiple of 2**LOG bytes.  */
index b7e8e96820d77aa98a0f5c2e650bd6366c135967..dc071d5e7b2ceaa3f54bcd855c9b934249363328 100644 (file)
   ;; MIPS16 constant pools.
   UNSPEC_ALIGN
   UNSPEC_CONSTTABLE
+  UNSPEC_CONSTTABLE_END
   UNSPEC_CONSTTABLE_INT
   UNSPEC_CONSTTABLE_FLOAT
 
 ;;
 
 (define_insn "consttable"
-  [(unspec_volatile [(const_int 0)] UNSPEC_CONSTTABLE)]
+  [(unspec_volatile [(match_operand 0 "const_int_operand" "")]
+                   UNSPEC_CONSTTABLE)]
+  ""
+  ""
+  [(set_attr "mode" "none")
+   (set_attr "insn_count" "0")])
+
+(define_insn "consttable_end"
+  [(unspec_volatile [(match_operand 0 "const_int_operand" "")]
+                   UNSPEC_CONSTTABLE_END)]
   ""
   ""
   [(set_attr "mode" "none")
index 2d0367546959217b347f7e666a65ffd440ef6fef..a1a66c3775a407f7efa3b322872df7c298ca9ad0 100644 (file)
@@ -1,3 +1,10 @@
+2016-11-16  Maciej W. Rozycki  <macro@imgtec.com>
+
+       * gcc.target/mips/data-sym-jump.c: New test case.
+       * gcc.target/mips/data-sym-pool.c: New test case.
+       * gcc.target/mips/insn-pseudo-4.c: Adjust for constant pool
+       annotation.
+
 2016-11-16  Yuri Rumyantsev  <ysrumyan@gmail.com>
 
        * lib/target-supports.exp (check_avx2_hw_available): New.
diff --git a/gcc/testsuite/gcc.target/mips/data-sym-jump.c b/gcc/testsuite/gcc.target/mips/data-sym-jump.c
new file mode 100644 (file)
index 0000000..c3ba294
--- /dev/null
@@ -0,0 +1,50 @@
+/* { dg-do compile } */
+/* { dg-options "-mips16 -mcode-readable=yes" } */
+/* { dg-skip-if "MIPS16 `casesi' loses at -Os" { *-*-* } { "-Os"} { "" } } */
+
+int
+frob (int i)
+{
+  switch (i)
+    {
+    case -5:
+      return -2;
+    case -3:
+      return -1;
+    case 0:
+      return 0;
+    case 3:
+      return 1;
+    case 5:
+      break;
+    default:
+      __builtin_unreachable ();
+    }
+  return i;
+}
+
+/* Expect assembly like:
+
+       la      $2, $L4
+                                               # Anything goes here.
+       .type   __jump_frob_4, @object          # Symbol # must match label.
+__jump_frob_4:                                 # The symbol must match.
+$L4:                                           # The label must match.
+       .half   $L3-$L4                         # Or `.word'.  The subtrahend
+       .half   $L2-$L4                         # label must match thoughout
+       .half   $L9-$L4                         # (repeated 11 times).
+       .half   $L2-$L4                         # .
+       .half   $L2-$L4                         # .
+       .half   $L8-$L4                         # .
+       .half   $L2-$L4                         # .
+       .half   $L2-$L4                         # .
+       .half   $L7-$L4                         # .
+       .half   $L2-$L4                         # .
+       .half   $L8-$L4                         # .
+       .type   __jend_frob_4, @function        # Symbol # must match label.
+__jend_frob_4:                                 # The symbol must match.
+       .insn
+
+   that is `__jump_*'/`__jend_*' symbols inserted around a jump table.  */
+
+/* { dg-final { scan-assembler "\tla\t\\\$\[0-9\]+, (.L(\[0-9\]+))\n.*\t\\.type\t(__jump_frob_\\2), @object\n\\3:\n\\1:\n(?:\t\\.(?:half|word)\t.L\[0-9\]+-\\1\n)\{11\}\t\\.type\t(__jend_frob_\\2), @function\n\\4:\n\t\\.insn\n" } } */
diff --git a/gcc/testsuite/gcc.target/mips/data-sym-pool.c b/gcc/testsuite/gcc.target/mips/data-sym-pool.c
new file mode 100644 (file)
index 0000000..8057783
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mips16 -mcode-readable=yes" } */
+
+int
+frob (void)
+{
+  return 0x12345678;
+}
+
+/* Expect assembly like:
+
+       lw      $2,$L3
+                                               # Anything goes here.
+       .type   __pool_frob_3, @object          # Symbol # must match label.
+__pool_frob_3:                                 # The symbol must match.
+       .align  2
+$L3:                                           # The label must match.
+       .word   305419896
+       .type   __pend_frob_3, @function        # Symbol # must match label.
+__pend_frob_3:                                 # The symbol must match.
+       .insn
+
+   that is `__pool_*'/`__pend_*' symbols inserted around a constant pool.  */
+
+/* { dg-final { scan-assembler "\tlw\t\\\$\[0-9\]+,(.L(\[0-9\]+))\n.*\t\\.type\t(__pool_frob_\\2), @object\n\\3:\n\t\\.align\t2\n\\1:\n\t\\.word\t305419896\n\t\\.type\t(__pend_frob_\\2), @function\n\\4:\n\t\\.insn\n" } } */
index 49a4851916166a27320bd9cccf984b7cfc1c1e61..ad4f2d9ddf35f65789e67eb81121400e24438591 100644 (file)
@@ -18,10 +18,12 @@ punt:
 $L2:                           # The label must match.
        .insn
 $L3 = .                                # It's there, but we don't care.
+       .type   __pool_unreachable_5, @object
+__pool_unreachable_5:
        .align  2
 $L5:                           # The label must match.
        .word   305419896
 
    that is .insn to be inserted if a code label is at a constant pool.  */
 
-/* { dg-final { scan-assembler "\tlw\t(\\\$\[0-9\]+),(.L\[0-9\]+)\n.*\tbeqz\t\\1,(.L\[0-9\]+)\n.*\n\\3:\n\t\\.insn\n(?:.L\[0-9\]+ = \\.\n)?\t\\.align\t2\n\\2:\n\t\\.word\t305419896\n" } } */
+/* { dg-final { scan-assembler "\tlw\t(\\\$\[0-9\]+),(.L\[0-9\]+)\n.*\tbeqz\t\\1,(.L\[0-9\]+)\n.*\n\\3:\n\t\\.insn\n(?:.L\[0-9\]+ = \\.\n)?\t\\.type\t__pool_unreachable_\[0-9\]+, @object\n__pool_unreachable_\[0-9\]+:\n\t\\.align\t2\n\\2:\n\t\\.word\t305419896\n" } } */