Source: gcc-7 Version: 7.2.0-16 Severity: important Tags: patch User: debian-sup...@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 - glaub...@debian.org `. `' Freie Universitaet Berlin - glaub...@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.