[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: