Bug#883433: gcc-7: Please include patch to implement __builtin_trap() on SH
Source: gcc-7
Version: 7.2.0-16
Severity: important
Tags: patch
User: debian-superh@lists.debian.org
Usertags: sh4
Hi!
Both src:linux and src:glibc currently FTBFS on sh4 with gcc-7 because
the compiler is missing the implementation of __builtin_trap(). Upstream
has suggested a patch in [1] which I have verified to work.
Since both src:linux and src:glibc are essential packages, I would like
to ask to have this patch merged into src:gcc-7 already even though
upstream has not merged the patch yet in its current form.
I have slightly modified the patch so it applies against src:gcc-7
and I actually tested the patch with Debian's gcc-7 package.
Thanks,
Adrian
> [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70216
--
.''`. John Paul Adrian Glaubitz
: :' : Debian Developer - glaubitz@debian.org
`. `' Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
`- GPG: 62FF 8A75 84E0 2956 9546 0006 7426 3B37 F5B5 F913
Index: a/src/gcc/config/sh/sh-c.c
===================================================================
--- a/src/gcc/config/sh/sh-c.c (revision 234258)
+++ b/src/gcc/config/sh/sh-c.c (working copy)
@@ -147,4 +147,7 @@
cpp_define_formatted (pfile, "__SH_ATOMIC_MODEL_%s__",
selected_atomic_model ().cdef_name);
+
+ if (TARGET_SH4_TRAPA_SLEEP_BUG)
+ builtin_define ("__SH4_TRAPA_SLEEP_BUG__");
}
Index: a/src/gcc/config/sh/sh-protos.h
===================================================================
--- a/src/gcc/config/sh/sh-protos.h (revision 234258)
+++ b/src/gcc/config/sh/sh-protos.h (working copy)
@@ -88,6 +88,46 @@
#define TARGET_ATOMIC_SOFT_IMASK \
(selected_atomic_model ().type == sh_atomic_model::soft_imask)
+/* __builtin_trapa handling options. */
+struct sh_builtin_trap_handler
+{
+ enum enum_type
+ {
+ none = 0,
+ libcall,
+ trapa,
+
+ num_handlers
+ };
+
+ enum_type type;
+ int trapa_imm_val;
+};
+
+extern const sh_builtin_trap_handler& selected_builtin_trap_handler (void);
+
+#define TARGET_BUILTIN_TRAP_NONE \
+ (selected_builtin_trap_handler ().type == sh_builtin_trap_handler::none)
+
+#define TARGET_BUILTIN_TRAP_TRAPA \
+ (selected_builtin_trap_handler ().type == sh_builtin_trap_handler::trapa)
+
+#define TARGET_BUILTIN_TRAP_TRAPA_VAL_RTX \
+ GEN_INT (selected_builtin_trap_handler ().trapa_imm_val)
+
+#define TARGET_BUILTIN_TRAP_LIBCALL \
+ (selected_builtin_trap_handler ().type == sh_builtin_trap_handler::libcall)
+
+#ifdef SH4_TRAPA_SLEEP_BUG_DEFAULT
+#define TARGET_SH4_TRAPA_SLEEP_BUG \
+ (sh4_trapa_sleep_bug_option == -1 ? (SH4_TRAPA_SLEEP_BUG_DEFAULT != 0) \
+ : (sh4_trapa_sleep_bug_option != 0))
+#else
+#define TARGET_SH4_TRAPA_SLEEP_BUG \
+ ((sh4_trapa_sleep_bug_option == -1 && TARGET_SH4 && !TARGET_SH4A) \
+ || sh4_trapa_sleep_bug_option == 1)
+#endif
+
#ifdef RTX_CODE
extern rtx sh_fsca_sf2int (void);
extern rtx sh_fsca_int2sf (void);
Index: a/src/gcc/config/sh/sh.c
===================================================================
--- a/src/gcc/config/sh/sh.c (revision 234258)
+++ b/src/gcc/config/sh/sh.c (working copy)
@@ -785,6 +785,102 @@
#undef err_ret
}
+/* Information on the currently selected __builtin_trap handler. */
+static sh_builtin_trap_handler selected_builtin_trap_handler_;
+
+const sh_builtin_trap_handler&
+selected_builtin_trap_handler (void)
+{
+ return selected_builtin_trap_handler_;
+}
+
+static sh_builtin_trap_handler
+parse_validate_builtin_trap_option (const char* str)
+{
+ const char* names[sh_builtin_trap_handler::num_handlers];
+ names[sh_builtin_trap_handler::none] = "none";
+ names[sh_builtin_trap_handler::libcall] = "libcall";
+ names[sh_builtin_trap_handler::trapa] = "trapa";
+
+ sh_builtin_trap_handler ret;
+
+ #if defined (SH_BUILTIN_TRAP_DEFAULT_TRAPA)
+ #if SH_BUILTIN_TRAP_DEFAULT_TRAPA < 0 || SH_BUILTIN_TRAP_DEFAULT_TRAPA > 255
+ #error default builtin trap trapa handler value out of range
+ #endif
+ ret.type = sh_builtin_trap_handler::trapa;
+ ret.trapa_imm_val = SH_BUILTIN_TRAP_DEFAULT_TRAPA;
+ #elif defined (SH_BUILTIN_TRAP_DEFAULT_LIBCALL)
+ ret.type = sh_builtin_trap_handler::libcall;
+ ret.trapa_imm_val = 0;
+ #else
+ ret.type = sh_builtin_trap_handler::none;
+ ret.trapa_imm_val = 0;
+ #endif
+
+ /* Handle empty string as 'none'. */
+ if (str == NULL || *str == '\0')
+ return ret;
+
+#define err_ret(...) do { error (__VA_ARGS__); return ret; } while (0)
+
+ std::vector<std::string> tokens;
+ for (std::stringstream ss (str); ss.good (); )
+ {
+ tokens.push_back (std::string ());
+ std::getline (ss, tokens.back (), ',');
+ }
+
+ if (tokens.empty ())
+ err_ret ("invalid builtin trap handler option");
+
+ /* The first token must be the handler name. */
+ {
+ for (size_t i = 0; i < sh_builtin_trap_handler::num_handlers; ++i)
+ if (tokens.front () == names[i])
+ {
+ ret.type = (sh_builtin_trap_handler::enum_type)i;
+ goto got_mode_name;
+ }
+
+ err_ret ("invalid builtin trap handler name \"%s\"",
+ tokens.front ().c_str ());
+got_mode_name:;
+ }
+
+ /* Go through the remaining tokens. */
+ bool have_imm = false;
+
+ for (size_t i = 1; i < tokens.size (); ++i)
+ {
+ if (tokens[i].find ("imm=") == 0)
+ {
+ have_imm = true;
+ std::string imm_str = tokens[i].substr (strlen ("imm="));
+ ret.trapa_imm_val = integral_argument (imm_str.c_str ());
+ if (imm_str.empty () || ret.trapa_imm_val == -1)
+ err_ret ("could not parse imm value \"%s\" in builtin trap handler "
+ "option", imm_str.c_str ());
+ }
+ else
+ err_ret ("unknown parameter \"%s\" in builtin trap handler option",
+ tokens[i].c_str ());
+ }
+
+ /* Check that the selection makes sense. */
+ if (ret.type == sh_builtin_trap_handler::trapa && have_imm == false)
+ err_ret ("immediate value not specified for trapa builtin trap handler");
+
+ if (ret.type == sh_builtin_trap_handler::trapa
+ && (ret.trapa_imm_val < 0 || ret.trapa_imm_val > 255))
+ err_ret ("immediate value for trapa builtin trap handler must be in the "
+ "range 0-255");
+
+ return ret;
+
+#undef err_ret
+}
+
/* Register SH specific RTL passes. */
extern opt_pass* make_pass_sh_treg_combine (gcc::context* ctx, bool split_insns,
const char* name);
@@ -1083,6 +1179,10 @@
selected_atomic_model_
= parse_validate_atomic_model_option (sh_atomic_model_str);
+ /* Parse __builtin_trap handler option. */
+ selected_builtin_trap_handler_
+ = parse_validate_builtin_trap_option (sh_builtin_trap_handler_str);
+
register_sh_passes ();
}
Index: a/src/gcc/config/sh/sh.md
===================================================================
--- a/src/gcc/config/sh/sh.md (revision 234258)
+++ b/src/gcc/config/sh/sh.md (working copy)
@@ -13016,6 +13016,55 @@
;; Misc
;; -------------------------------------------------------------------------
+;; __builtin_trap
+(define_expand "trap"
+ [(trap_if (const_int 1) (const_int 0))]
+ "TARGET_SH1 && !TARGET_BUILTIN_TRAP_NONE"
+{
+ if (TARGET_BUILTIN_TRAP_TRAPA)
+ emit_insn (gen_trapa (TARGET_BUILTIN_TRAP_TRAPA_VAL_RTX));
+ else if (TARGET_BUILTIN_TRAP_LIBCALL)
+ {
+ rtx funcaddr = gen_reg_rtx (Pmode);
+ rtx lab = function_symbol (funcaddr, "__builtin_trap", SFUNC_STATIC).lab;
+ emit_insn (gen_trap_call (funcaddr, lab));
+ }
+ else
+ gcc_unreachable ();
+
+ DONE;
+})
+
+(define_insn "trapa"
+ [(trap_if (const_int 1) (match_operand:SI 0 "const_logical_operand"))]
+ "TARGET_SH1"
+{
+ if (TARGET_SH4_TRAPA_SLEEP_BUG)
+ return "trapa %0" "\n"
+ " or r0,r0" "\n"
+ " or r0,r0" "\n"
+ " or r0,r0" "\n"
+ " or r0,r0" "\n"
+ " or r0,r0";
+ else
+ return "trapa %0";
+}
+ [(set (attr "length") (if_then_else (match_test "TARGET_SH4_TRAPA_SLEEP_BUG")
+ (const_int 12) (const_int 2)))
+ (set_attr "in_delay_slot" "no")])
+
+(define_insn "trap_call"
+ [(trap_if (const_int 1) (const_int 0))
+ (use (match_operand:SI 0 "arith_reg_operand" "r,r"))
+ (use (match_operand:SI 1 "" "Z,Ccl"))
+ (clobber (reg:SI PR_REG))]
+ "TARGET_SH1"
+ "@
+ jsr @%0%#
+ bsrf %0\n%01:%#"
+ [(set_attr "type" "sfunc")
+ (set_attr "needs_delay_slot" "yes")])
+
;; String/block move insn.
(define_expand "movmemsi"
Index: gcc/config.gcc
===================================================================
--- a/src/gcc/config.gcc (revision 234258)
+++ b/src/gcc/config.gcc (working copy)
@@ -2644,6 +2644,39 @@
case ${with_endian} in
little*) tm_file="sh/little.h ${tm_file}" ;;
esac
+
+ case ${with_builtin_trap} in
+ "")
+ case ${target} in
+ sh*-*-linux*)
+ tm_defines="$tm_defines SH_BUILTIN_TRAP_DEFAULT_TRAPA=0x54"
+ esac
+ ;;
+ libcall)
+ tm_defines="$tm_defines SH_BUILTIN_TRAP_DEFAULT_LIBCALL=1"
+ ;;
+ trapa-[0123456789]*)
+ trapa_value=`echo $with_builtin_trap | tr -d -c 0-9`
+
+ if [ $trapa_value -gt 255 ]; then
+ echo "Invalid trapa number in --with-builtin-trap=$with_builtin_trap"
+ exit 1
+ fi
+
+ tm_defines="$tm_defines SH_BUILTIN_TRAP_DEFAULT_TRAPA=$trapa_value"
+ ;;
+ *)
+ echo "Invalid builtin trap handler in --with-builtin-trap=$with_builtin_trap"
+ exit 1
+ esac
+
+ if test x$enable_sh4_trapa_sleep_bug = xyes; then
+ tm_defines="$tm_defines SH4_TRAPA_SLEEP_BUG_DEFAULT=1"
+ fi
+ if test x$enable_sh4_trapa_sleep_bug = xno; then
+ tm_defines="$tm_defines SH4_TRAPA_SLEEP_BUG_DEFAULT=0"
+ fi
+
tm_file="${tm_file} dbxelf.h elfos.h sh/elf.h"
case ${target} in
sh*-*-linux*) tmake_file="${tmake_file} sh/t-linux"
Index: a/src/gcc/config/sh/sh.opt
===================================================================
--- a/src/gcc/config/sh/sh.opt 2017-01-01 13:07:43.000000000 +0100
+++ b/src/gcc/config/sh/sh.opt 2017-12-03 11:46:52.813914342 +0100
@@ -301,3 +301,11 @@
mlra
Target Report Var(sh_lra_flag) Init(0) Save
Use LRA instead of reload (transitional).
+
+msh4-trapa-sleep-bug
+Target Report Var(sh4_trapa_sleep_bug_option) Init(-1)
+Handle the trapa/sleep/undefined instruction 0xFFFD bug.
+
+mbuiltin-trap=
+Target Report RejectNegative Joined Var(sh_builtin_trap_handler_str)
+Specify what code to emit for __builtin_trap.
Reply to: