From 2fe2aba3cd7c2daf16c545bc7fa34481157bfcaf Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Wed, 16 Nov 2016 17:12:08 +0000 Subject: [PATCH] MIPS/GCC: Mark text contents as code or data 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 | 20 ++++++ gcc/config/mips/mips-protos.h | 2 + gcc/config/mips/mips.c | 69 +++++++++++++++++-- gcc/config/mips/mips.h | 26 +++++++ gcc/config/mips/mips.md | 12 +++- gcc/testsuite/ChangeLog | 7 ++ gcc/testsuite/gcc.target/mips/data-sym-jump.c | 50 ++++++++++++++ gcc/testsuite/gcc.target/mips/data-sym-pool.c | 25 +++++++ gcc/testsuite/gcc.target/mips/insn-pseudo-4.c | 4 +- 9 files changed, 209 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.target/mips/data-sym-jump.c create mode 100644 gcc/testsuite/gcc.target/mips/data-sym-pool.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3a48f13122c..6f46dd404f2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2016-11-16 Maciej W. Rozycki + + * 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 * params.def (PARAM_VECT_EPILOGUES_NOMASK): New. diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 09cf6626e27..117c78cc34f 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -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); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 44cdeb72c1d..10c20393ca4 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -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 +} /* 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 mulsidi3 pattern. diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 12662a7ea39..bb66c428dd1 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -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. */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index b7e8e96820d..dc071d5e7b2 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -121,6 +121,7 @@ ;; MIPS16 constant pools. UNSPEC_ALIGN UNSPEC_CONSTTABLE + UNSPEC_CONSTTABLE_END UNSPEC_CONSTTABLE_INT UNSPEC_CONSTTABLE_FLOAT @@ -7321,7 +7322,16 @@ ;; (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") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2d036754695..a1a66c3775a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2016-11-16 Maciej W. Rozycki + + * 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 * 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 index 00000000000..c3ba2944cdc --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/data-sym-jump.c @@ -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 index 00000000000..805778322e9 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/data-sym-pool.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.target/mips/insn-pseudo-4.c b/gcc/testsuite/gcc.target/mips/insn-pseudo-4.c index 49a48519161..ad4f2d9ddf3 100644 --- a/gcc/testsuite/gcc.target/mips/insn-pseudo-4.c +++ b/gcc/testsuite/gcc.target/mips/insn-pseudo-4.c @@ -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" } } */ -- 2.30.2