From patchwork Fri Nov 11 17:05:18 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Maciej W. Rozycki" X-Patchwork-Id: 693811 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3tFmX948hQz9t0t for ; Sat, 12 Nov 2016 04:06:00 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="joX9xEpp"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:mime-version:content-type; q=dns; s=default; b=IYosPxkEMirax9d+V3Nijr13V5tutheD+riBKPBV8u3j02kORO LAJY4y+IQhrqHUG45vNXLZ7vjXZxluPlPXRePA6JP8KR37dIK1Y98C5nS0tNhnZP eRVah/HgK+W1AgnkQC3ach53Ie3eAI+EGGrbqzzt0lXhu0sYSY0uz4BaM= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:mime-version:content-type; s= default; bh=7f1EQkwfRr0siql3kFoU2h88GmM=; b=joX9xEppTHmzEZg8goJ4 PT6FOfzAOIhe4A4UcVMTw0gfO1TTE4k0V6ag06PTQ5DL9CRz8fPetYncRjhqrS/F CQhgpZRk2iKokEcO7Jx7Ii92/Zrw3scIS/fYeizRtg/wLXgx0POktkc5/oHAh870 h02d0CF7rH8jRVfcfu9809s= Received: (qmail 116526 invoked by alias); 11 Nov 2016 17:05:44 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 116500 invoked by uid 89); 11 Nov 2016 17:05:43 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.8 required=5.0 tests=AWL, BAYES_00, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy=UD:L, 0017, tl, LOCAL X-HELO: mailapp01.imgtec.com Received: from mailapp01.imgtec.com (HELO mailapp01.imgtec.com) (195.59.15.196) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 11 Nov 2016 17:05:33 +0000 Received: from HHMAIL01.hh.imgtec.org (unknown [10.100.10.19]) by Forcepoint Email with ESMTPS id 1E97779645DAF; Fri, 11 Nov 2016 17:05:25 +0000 (GMT) Received: from [10.20.78.79] (10.20.78.79) by HHMAIL01.hh.imgtec.org (10.100.10.21) with Microsoft SMTP Server id 14.3.294.0; Fri, 11 Nov 2016 17:05:27 +0000 Date: Fri, 11 Nov 2016 17:05:18 +0000 From: "Maciej W. Rozycki" To: CC: Catherine Moore , Matthew Fortune Subject: [PATCH] MIPS/GCC: Mark text contents as code or data Message-ID: User-Agent: Alpine 2.20.17 (DEB 179 2016-10-28) MIME-Version: 1.0 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 : 0: b313 lw v1,4c 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 e: 3564 sll a1,v1,1 10: 0b03 la v1,1c 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 : 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 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" } } */