This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] MIPS/GCC: Mark text contents as code or data
- From: "Maciej W. Rozycki" <macro at imgtec dot com>
- To: <gcc-patches at gcc dot gnu dot org>
- Cc: Catherine Moore <clm at codesourcery dot com>, Matthew Fortune <Matthew dot Fortune at imgtec dot com>
- Date: Fri, 11 Nov 2016 17:05:18 +0000
- Subject: [PATCH] MIPS/GCC: Mark text contents as code or data
- Authentication-results: sourceware.org; auth=none
Add local symbols of the correct type at the beginning and the end of
inline jump tables and MIPS16 constant pools, marking these data areas
as such while keeping code outside marked as such as well.
Consider the following example, built as MIPS16 code:
$ cat switch16.c
int
foo (int i)
{
static int j;
j += i;
switch (i)
{
case -5:
return -2;
case -3:
return -1;
case 0:
return 0;
case 3:
return 1;
case 5:
return 2;
default:
break;
}
return j;
}
$ gcc -mips16 -O2 -S switch16.c -o switch16-0.s
$ cat switch16-0.s
.file 1 "switch16.c"
.section .mdebug.abi32
.previous
.nan legacy
.module fp=xx
.module nooddspreg
.abicalls
.option pic0
.text
.align 2
.globl foo
.set mips16
.set nomicromips
.ent foo
.type foo, @function
foo:
.frame $sp,0,$31 # vars= 0, regs= 0/0, args= 0, gp= 0
.mask 0x00000000,0
.fmask 0x00000000,0
lw $3,$L11
lw $2,0($3)
addu $2,$4,$2
sw $2,0($3)
addiu $3,$4,5
sltu $3, 11
bteqz $L1
sll $5, $3, 1
la $3, $L4
addu $5, $3, $5
lh $5, 0($5)
addu $3, $3, $5
j $3
.align 1
.align 2
$L4:
.half $L9-$L4
.half $L1-$L4
.half $L5-$L4
.half $L1-$L4
.half $L1-$L4
.half $L6-$L4
.half $L1-$L4
.half $L1-$L4
.half $L7-$L4
.half $L1-$L4
.half $L8-$L4
$L9:
li $2,2
neg $2,$2
$L1:
jr $31
$L5:
li $2,1
.set noreorder
.set nomacro
jr $31
neg $2,$2
.set macro
.set reorder
$L6:
.set noreorder
.set nomacro
jr $31
move $2,$4
.set macro
.set reorder
$L7:
.set noreorder
.set nomacro
jr $31
li $2,1
.set macro
.set reorder
$L8:
.set noreorder
.set nomacro
jr $31
li $2,2
.set macro
.set reorder
.align 2
$L11:
.word j.1474
.end foo
.size foo, .-foo
.local j.1474
.comm j.1474,4,4
.ident "GCC: (GNU) 7.0.0 20160810 (experimental)"
$ as -o switch16-0.o switch16-0.s
$ readelf -s switch16-0.o
Symbol table '.symtab' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS switch16.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 9
6: 00000000 4 OBJECT LOCAL DEFAULT 4 j.1474
7: 00000000 0 SECTION LOCAL DEFAULT 5
8: 00000000 0 SECTION LOCAL DEFAULT 6
9: 00000000 0 SECTION LOCAL DEFAULT 7
10: 00000000 0 SECTION LOCAL DEFAULT 10
11: 00000000 0 SECTION LOCAL DEFAULT 11
12: 00000000 80 FUNC GLOBAL DEFAULT [MIPS16] 1 foo
$ objdump -dr switch16-0.o
switch16-0.o: file format elf32-tradbigmips
Disassembly of section .text:
00000000 <foo>:
0: b313 lw v1,4c <foo+0x4c>
2: 9b40 lw v0,0(v1)
4: e449 addu v0,a0,v0
6: db40 sw v0,0(v1)
8: 4465 addiu v1,a0,5
a: 5b0b sltiu v1,11
c: 6014 bteqz 36 <foo+0x36>
e: 3564 sll a1,v1,1
10: 0b03 la v1,1c <foo+0x1c>
12: e3b5 addu a1,v1,a1
14: 8da0 lh a1,0(a1)
16: e3ad addu v1,a1
18: eb80 jrc v1
1a: 6500 nop
1c: 0017 addiu s0,sp,92
1e: 001b addiu s0,sp,108
20: 001d addiu s0,sp,116
22: 001b addiu s0,sp,108
24: 001b addiu s0,sp,108
26: 0023 addiu s0,sp,140
28: 001b addiu s0,sp,108
2a: 001b addiu s0,sp,108
2c: 0027 addiu s0,sp,156
2e: 001b addiu s0,sp,108
30: 002b addiu s0,sp,172
32: 6a02 li v0,2
34: ea4b neg v0
36: e8a0 jrc ra
38: 6a01 li v0,1
3a: e820 jr ra
3c: ea4b neg v0
3e: e820 jr ra
40: 6744 move v0,a0
42: e820 jr ra
44: 6a01 li v0,1
46: e820 jr ra
48: 6a02 li v0,2
4a: 6500 nop
4c: 0000 addiu s0,sp,0
4c: R_MIPS_32 .bss
...
$
As you can see the assembly source generated has code interspersed with
data, all within the span of the `foo' function definition, and
consequently all the binary contents of the function in the object file
produced are interpreted as instructions by the disassembler.
Now with appropriate markers added we get these results instead:
$ gcc -mips16 -O2 -S switch16.c -o switch16-1.s
$ cat switch16-1.s
.file 1 "switch16.c"
.section .mdebug.abi32
.previous
.nan legacy
.module fp=xx
.module nooddspreg
.abicalls
.option pic0
.text
.align 2
.globl foo
.set mips16
.set nomicromips
.ent foo
.type foo, @function
foo:
.frame $sp,0,$31 # vars= 0, regs= 0/0, args= 0, gp= 0
.mask 0x00000000,0
.fmask 0x00000000,0
lw $3,$L11
lw $2,0($3)
addu $2,$4,$2
sw $2,0($3)
addiu $3,$4,5
sltu $3, 11
bteqz $L1
sll $5, $3, 1
la $3, $L4
addu $5, $3, $5
lh $5, 0($5)
addu $3, $3, $5
j $3
.align 1
.align 2
.type __jump_foo_4, @object
__jump_foo_4:
$L4:
.half $L9-$L4
.half $L1-$L4
.half $L5-$L4
.half $L1-$L4
.half $L1-$L4
.half $L6-$L4
.half $L1-$L4
.half $L1-$L4
.half $L7-$L4
.half $L1-$L4
.half $L8-$L4
.type __jend_foo_4, @function
__jend_foo_4:
.insn
$L9:
li $2,2
neg $2,$2
$L1:
jr $31
$L5:
li $2,1
.set noreorder
.set nomacro
jr $31
neg $2,$2
.set macro
.set reorder
$L6:
.set noreorder
.set nomacro
jr $31
move $2,$4
.set macro
.set reorder
$L7:
.set noreorder
.set nomacro
jr $31
li $2,1
.set macro
.set reorder
$L8:
.set noreorder
.set nomacro
jr $31
li $2,2
.set macro
.set reorder
.type __pool_foo_11, @object
__pool_foo_11:
.align 2
$L11:
.word j.1474
.type __pend_foo_11, @function
__pend_foo_11:
.insn
.end foo
.size foo, .-foo
.local j.1474
.comm j.1474,4,4
.ident "GCC: (GNU) 7.0.0 20160810 (experimental)"
$ as -o switch16-1.o switch16-1.s
$ readelf -s switch16-1.o
Symbol table '.symtab' contains 17 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS switch16.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 9
6: 0000001c 0 OBJECT LOCAL DEFAULT 1 __jump_foo_4
7: 00000032 0 FUNC LOCAL DEFAULT [MIPS16] 1 __jend_foo_4
8: 0000004c 0 OBJECT LOCAL DEFAULT 1 __pool_foo_11
9: 00000000 4 OBJECT LOCAL DEFAULT 4 j.1474
10: 00000050 0 FUNC LOCAL DEFAULT [MIPS16] 1 __pend_foo_11
11: 00000000 0 SECTION LOCAL DEFAULT 5
12: 00000000 0 SECTION LOCAL DEFAULT 6
13: 00000000 0 SECTION LOCAL DEFAULT 7
14: 00000000 0 SECTION LOCAL DEFAULT 10
15: 00000000 0 SECTION LOCAL DEFAULT 11
16: 00000000 80 FUNC GLOBAL DEFAULT [MIPS16] 1 foo
$ objdump -dr switch16-1.o
switch16-1.o: file format elf32-tradbigmips
Disassembly of section .text:
00000000 <foo>:
0: b313 lw v1,4c <__pool_foo_11>
2: 9b40 lw v0,0(v1)
4: e449 addu v0,a0,v0
6: db40 sw v0,0(v1)
8: 4465 addiu v1,a0,5
a: 5b0b sltiu v1,11
c: 6014 bteqz 36 <__jend_foo_4+0x4>
e: 3564 sll a1,v1,1
10: 0b03 la v1,1c <__jump_foo_4>
12: e3b5 addu a1,v1,a1
14: 8da0 lh a1,0(a1)
16: e3ad addu v1,a1
18: eb80 jrc v1
1a: 6500 nop
0000001c <__jump_foo_4>:
1c: 0017 001b 001d 001b 001b 0023 001b 001b ...........#....
2c: 0027 001b 002b .'...+
00000032 <__jend_foo_4>:
32: 6a02 li v0,2
34: ea4b neg v0
36: e8a0 jrc ra
38: 6a01 li v0,1
3a: e820 jr ra
3c: ea4b neg v0
3e: e820 jr ra
40: 6744 move v0,a0
42: e820 jr ra
44: 6a01 li v0,1
46: e820 jr ra
48: 6a02 li v0,2
4a: 6500 nop
0000004c <__pool_foo_11>:
4c: 0000 0000 ....
4c: R_MIPS_32 .bss
$
Now we have an `__jump_foo_4' and `__pool_foo_11' symbols marking the
beginning of data and corresponding `__jend_foo_4' and `__pend_foo_11'
symbols marking the end of data. The type of these symbols, either
`object' or `function' is what drives the dissasembler and makes it
interpret binary contents as data or code respectively.
Internally we track the beginning and the end of MIPS16 constant pools
with the use of dummy `consttable' and `consttable_end' insns, which are
inserted at the beginning and the end of each pool created. As there
can be multiple pools within one function, these insns carry the number,
which is guaranteed to be unique across the whole compilation unit, of
the first local label within the pool, used to refer to its first
element.
This number is then used, along with the name of the containing
function, and fixed `__pool_' and `__pend_' prefixes, to construct
unique local symbols, which are output in `mips_final_prescan_insn' and
`mips_final_postscan_insn' as assembly code is produced for the insn.
There is a `.insn' pseudo-op included in the assembly generated for the
ending symbol so that the ISA mode is also correctly recorded for the
disassembly of any padding following if there are no further actual
instructions after the pool.
For jump tables we already have hooks provided by the middle end so we
use them instead and don't have to produce any extra insns. The
middle-end hooks are ASM_OUTPUT_CASE_LABEL and ASM_OUTPUT_CASE_END,
although in the former case we use the ASM_OUTPUT_BEFORE_CASE_LABEL
helper macro used by `config/elfos.h' instead. We can only set the
symbol type for ELF targets, so the use of this helper macro is
appropriate and avoids the problem of changing the behaviour with
respect to jump table alignment for targets which do not use
`config/elfos.h' as we now have ASM_OUTPUT_ALIGN carried over from there
to the target-wide `config/mips/mips.h' header. By using
ASM_OUTPUT_BEFORE_CASE_LABEL which is only referred by `config/elfos.h'
we avoid this problem.
As with MIPS16 constant pools there can be multiple jump tables within
one function so again we take a unique number of the jump table label,
already provided as an argument to ASM_OUTPUT_BEFORE_CASE_LABEL and
ASM_OUTPUT_CASE_END, and we join it with the name of the containing
function and fixed `__jump_' and `__jend_' prefixes, ensuring this way
that local symbols constructed this way are unique. Like with the pools
a `.insn' pseudo-op is included with the ending symbol in case no
further actual code follows.
Finally the names of the prefixes have been chosen to mimic ones already
used for the various MIPS16 floating-point stubs, therefore keeping the
naming convention consistent.
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.
---
There is a slight assymetry between ASM_OUTPUT_BEFORE_CASE_LABEL and
ASM_OUTPUT_CASE_END in that with any configurations not using
`config/elfos.h' `mips_set_text_contents_type' won't be called from
ASM_OUTPUT_CASE_LABEL at all, whereas in the case of ASM_OUTPUT_CASE_END
the function will be called although is expected to be empty as
ASM_OUTPUT_TYPE_DIRECTIVE is expected not to be defined with such
configurations.
I suspect this slight imperfection in the arrangement of the
configuration macros is not worth further effort though as the semantics
for configurations not using `config/elfos.h' is expected to be right,
with just an unnecessary dummy call to `mips_set_text_contents_type',
while indeed we may not have any such configuration supported anymore
anyway.
I have successfully regression-tested it with the `mips-mti-linux-gnu'
target, with a big-endian o32 regular MIPS multilib and a little-endian
o32 MIPS16 multilib, with no regressions.
OK to apply?
Maciej
gcc-mips-data-sym.diff
Index: gcc/gcc/config/mips/mips-protos.h
===================================================================
--- gcc.orig/gcc/config/mips/mips-protos.h 2016-11-09 18:56:34.412202878 +0000
+++ gcc/gcc/config/mips/mips-protos.h 2016-11-09 18:57:01.571953223 +0000
@@ -271,6 +271,8 @@ extern void mips_declare_object (FILE *,
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: gcc/gcc/config/mips/mips.c
===================================================================
--- gcc.orig/gcc/config/mips/mips.c 2016-11-09 18:56:34.423849203 +0000
+++ gcc/gcc/config/mips/mips.c 2016-11-09 18:57:01.752162039 +0000
@@ -9742,6 +9742,37 @@ mips_finish_declare_object (FILE *stream
}
}
#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. */
@@ -17124,17 +17155,22 @@ mips16_emit_constants_1 (machine_mode mo
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. */
@@ -17151,6 +17187,8 @@ mips16_emit_constants (struct mips16_con
next = c->next;
free (c);
}
+ if (constants)
+ insn = emit_insn_after (gen_consttable_end (GEN_INT (label_num)), insn);
emit_barrier_after (insn);
}
@@ -20261,16 +20299,32 @@ mips_need_noat_wrapper_p (rtx_insn *insn
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,
@@ -20278,6 +20332,13 @@ mips_final_postscan_insn (FILE *file ATT
{
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: gcc/gcc/config/mips/mips.h
===================================================================
--- gcc.orig/gcc/config/mips/mips.h 2016-11-09 18:56:34.445992594 +0000
+++ gcc/gcc/config/mips/mips.h 2016-11-09 18:57:01.804444614 +0000
@@ -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: gcc/gcc/config/mips/mips.md
===================================================================
--- gcc.orig/gcc/config/mips/mips.md 2016-11-09 18:56:34.458515411 +0000
+++ gcc/gcc/config/mips/mips.md 2016-11-09 20:54:38.794831645 +0000
@@ -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")
Index: gcc/gcc/testsuite/gcc.target/mips/data-sym-jump.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/data-sym-jump.c 2016-11-09 20:57:25.850097225 +0000
@@ -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" } } */
Index: gcc/gcc/testsuite/gcc.target/mips/data-sym-pool.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/data-sym-pool.c 2016-11-09 20:57:25.880515516 +0000
@@ -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: gcc/gcc/testsuite/gcc.target/mips/insn-pseudo-4.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/mips/insn-pseudo-4.c 2016-11-09 20:57:21.901118536 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/insn-pseudo-4.c 2016-11-09 20:57:25.890641344 +0000
@@ -18,10 +18,12 @@ unreachable (void)
$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" } } */