On Mon, Apr 22, 2019 at 10:15 AM Jakub Jelinek <ja...@redhat.com> wrote:
>
> Hi!
>
> As detailed in the PR, unlike most other targets, on ARM EABI the floating
> point registers are saved lazily, when EH personality routine calls
> __gnu_unwind_frame (usually in the CONTINUE_UNWINDING macro).
> That means the unwinder itself and the personality routines (and whatever
> other functions those call in the path to CONTINUE_UNWINDING) must be
> compiled so that it doesn't use floating point registers.  Calling some
> function that saves those on entry and restores on exit is fine, but calling
> some function which saves those on entry and then calls __gnu_unwind_frame
> and then restores on exit is not fine.
> In 8.x and earlier we were just lucky that the RA when compiling those
> didn't decide to use any of those registers, but starting with the combiner
> hard register changes we are no longer so lucky.
>
> The following patch introduces -mgeneral-regs-only option and
> general-regs-only target attribute for ARM (similarly to how other targets
> like AArch64 and x86), changes the ARM unwinder to be compiled with that
> and changes the personality routines of all languages so that either just
> the personality routine, or whatever other routines called by personality
> routines that call directly or indirectly __gnu_unwind_frame to be compiled
> that way.
>
> Bootstrapped/regtested on armv7hl-linux-gnueabi (and x86_64-linux to make
> sure it compiles on other targets too).
>
> Ok for trunk?

Ok. Thanks a lot for working on this and fixing the rest of this up.
I've been busy with a few other things.


> While the libgo changes are included in the patch, I think those need to go
> through go upstream and will likely need some changes if that code can be
> compiled by earlier GCC versions or other compilers.
>




> Not sure about libphobos D stuff, does it need to go through upstream and
> is libdruntime/gcc/deh.d compiled by compilers other than GDC?
>
> The Ada changes need those guards because the file is compiled by both
> the system compiler and by the newly built compilers; when compiled by
> system compiler, as the FE is built with -fno-exceptions I'd hope the EH
> stuff isn't really used there and at least until GCC 9.1 is released we have
> the issue that the system compiler could be some earlier GCC 9.0.1 snapshot
> which doesn't support general-regs-only.

I don't grok enough ada to approve this and will leave that part to
Eric or others.

Ramana

>
> 2019-04-22  Ramana Radhakrishnan  <ramana.radhakrish...@arm.com>
>             Bernd Edlinger  <bernd.edlin...@hotmail.de>
>             Jakub Jelinek  <ja...@redhat.com>
>
>         PR target/89093
>         * config/arm/arm.c (aapcs_vfp_is_call_or_return_candidate): Diagnose
>         if used with general-regs-only.
>         (arm_conditional_register_usage): Don't add non-general regs if
>         general-regs-only.
>         (arm_valid_target_attribute_rec): Handle general-regs-only.
>         * config/arm/arm.h (TARGET_HARD_FLOAT): Return false if
>         general-regs-only.
>         (TARGET_HARD_FLOAT_SUB): Define.
>         (TARGET_SOFT_FLOAT): Define as negation of TARGET_HARD_FLOAT_SUB.
>         (TARGET_REALLY_IWMMXT): Add && !TARGET_GENERAL_REGS_ONLY.
>         (TARGET_REALLY_IWMMXT2): Likewise.
>         * config/arm/arm.opt: Add -mgeneral-regs-only.
>         * doc/extend.texi: Document ARM general-regs-only target.
>         * doc/invoke.texi: Document ARM -mgeneral-regs-only.
> gcc/ada/
>         * raise-gcc.c (TARGET_ATTRIBUTE): Define.
>         (continue_unwind, personality_body, PERSONALITY_FUNCTION): Add
>         TARGET_ATTRIBUTE.
> libgcc/
>         * config/arm/pr-support.c: Add #pragma GCC 
> target("general-regs-only").
>         * config/arm/unwind-arm.c: Likewise.
>         * unwind-c.c (PERSONALITY_FUNCTION): Add general-regs-only target
>         attribute for ARM.
> libobjc/
>         * exception.c (PERSONALITY_FUNCTION): Add general-regs-only target
>         attribute for ARM.
> libphobos/
>         * libdruntime/gcc/deh.d: Import gcc.attribute.
>         (personality_fn_attributes): New enum.
>         (scanLSDA, CONTINUE_UNWINDING, gdc_personality, __gdc_personality):
>         Add @personality_fn_attributes.
> libstdc++-v3/
>         * libsupc++/eh_personality.cc (PERSONALITY_FUNCTION): Add
>         general-regs-only target attribute for ARM.
> libgo/
>         * runtime/go-unwind.c (PERSONALITY_FUNCTION,
>         __gccgo_personality_dummy): Add general-regs-only target
>         attribute for ARM.
>
> --- gcc/config/arm/arm.c        (revision 270444)
> +++ gcc/config/arm/arm.c        (working copy)
> @@ -6112,6 +6112,11 @@ aapcs_vfp_is_call_or_return_candidate (enum arm_pc
>      return false;
>
>    *base_mode = new_mode;
> +
> +  if (TARGET_GENERAL_REGS_ONLY)
> +    error ("argument of type %qT not permitted with -mgeneral-regs-only",
> +          type);
> +
>    return true;
>  }
>
> @@ -28404,7 +28409,7 @@ arm_conditional_register_usage (void)
>         }
>      }
>
> -  if (TARGET_REALLY_IWMMXT)
> +  if (TARGET_REALLY_IWMMXT && !TARGET_GENERAL_REGS_ONLY)
>      {
>        regno = FIRST_IWMMXT_GR_REGNUM;
>        /* The 2002/10/09 revision of the XScale ABI has wCG0
> @@ -30878,6 +30883,9 @@ arm_valid_target_attribute_rec (tree args, struct
>        else if (!strcmp (q, "arm"))
>         opts->x_target_flags &= ~MASK_THUMB;
>
> +      else if (!strcmp (q, "general-regs-only"))
> +       opts->x_target_flags |= MASK_GENERAL_REGS_ONLY;
> +
>        else if (!strncmp (q, "fpu=", 4))
>         {
>           int fpu_index;
> --- gcc/config/arm/arm.h        (revision 270444)
> +++ gcc/config/arm/arm.h        (working copy)
> @@ -122,12 +122,18 @@ extern tree arm_fp16_type_node;
>  #define TARGET_32BIT_P(flags)  (TARGET_ARM_P (flags) || TARGET_THUMB2_P 
> (flags))
>
>  /* Run-time Target Specification.  */
> -/* Use hardware floating point instructions. */
> -#define TARGET_HARD_FLOAT      (arm_float_abi != ARM_FLOAT_ABI_SOFT    \
> +/* Use hardware floating point instructions. -mgeneral-regs-only prevents
> +the use of floating point instructions and registers but does not prevent
> +emission of floating point pcs attributes.  */
> +#define TARGET_HARD_FLOAT_SUB  (arm_float_abi != ARM_FLOAT_ABI_SOFT    \
>                                  && bitmap_bit_p (arm_active_target.isa, \
>                                                   isa_bit_vfpv2) \
>                                  && TARGET_32BIT)
> -#define TARGET_SOFT_FLOAT      (!TARGET_HARD_FLOAT)
> +
> +#define TARGET_HARD_FLOAT      (TARGET_HARD_FLOAT_SUB          \
> +                                && !TARGET_GENERAL_REGS_ONLY)
> +
> +#define TARGET_SOFT_FLOAT      (!TARGET_HARD_FLOAT_SUB)
>  /* User has permitted use of FP instructions, if they exist for this
>     target.  */
>  #define TARGET_MAYBE_HARD_FLOAT (arm_float_abi != ARM_FLOAT_ABI_SOFT)
> @@ -135,8 +141,10 @@ extern tree arm_fp16_type_node;
>  #define TARGET_HARD_FLOAT_ABI          (arm_float_abi == ARM_FLOAT_ABI_HARD)
>  #define TARGET_IWMMXT                  (arm_arch_iwmmxt)
>  #define TARGET_IWMMXT2                 (arm_arch_iwmmxt2)
> -#define TARGET_REALLY_IWMMXT           (TARGET_IWMMXT && TARGET_32BIT)
> -#define TARGET_REALLY_IWMMXT2          (TARGET_IWMMXT2 && TARGET_32BIT)
> +#define TARGET_REALLY_IWMMXT           (TARGET_IWMMXT && TARGET_32BIT \
> +                                        && !TARGET_GENERAL_REGS_ONLY)
> +#define TARGET_REALLY_IWMMXT2          (TARGET_IWMMXT2 && TARGET_32BIT \
> +                                        && !TARGET_GENERAL_REGS_ONLY)
>  #define TARGET_IWMMXT_ABI (TARGET_32BIT && arm_abi == ARM_ABI_IWMMXT)
>  #define TARGET_ARM                      (! TARGET_THUMB)
>  #define TARGET_EITHER                  1 /* (TARGET_ARM | TARGET_THUMB) */
> --- gcc/config/arm/arm.opt      (revision 270444)
> +++ gcc/config/arm/arm.opt      (working copy)
> @@ -302,3 +302,7 @@ When linking for big-endian targets, generate a le
>  mbranch-cost=
>  Target RejectNegative Joined UInteger Var(arm_branch_cost) Init(-1)
>  Cost to assume for a branch insn.
> +
> +mgeneral-regs-only
> +Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Save
> +Generate code which uses the core registers only (r0-r14).
> --- gcc/doc/extend.texi (revision 270444)
> +++ gcc/doc/extend.texi (working copy)
> @@ -4190,6 +4190,15 @@ into the @code{sjli} table needs to be passed as a
>  These function attributes are supported for ARM targets:
>
>  @table @code
> +
> +@item general-regs-only
> +@cindex @code{general-regs-only} function attribute, ARM
> +Indicates that no floating-point or Advanced SIMD registers should be
> +used when generating code for this function.  If the function explicitly
> +uses floating-point code, then the compiler gives an error.  This is
> +the same behavior as that of the command-line option
> +@option{-mgeneral-regs-only}.
> +
>  @item interrupt
>  @cindex @code{interrupt} function attribute, ARM
>  Use this attribute to indicate
> --- gcc/doc/invoke.texi (revision 270444)
> +++ gcc/doc/invoke.texi (working copy)
> @@ -674,6 +674,7 @@ Objective-C and Objective-C++ Dialects}.
>  -mabi=@var{name} @gol
>  -mapcs-stack-check  -mno-apcs-stack-check @gol
>  -mapcs-reentrant  -mno-apcs-reentrant @gol
> +-mgeneral-regs-only @gol
>  -msched-prolog  -mno-sched-prolog @gol
>  -mlittle-endian  -mbig-endian @gol
>  -mbe8  -mbe32 @gol
> @@ -17068,6 +17069,12 @@ the hard-float and soft-float ABIs are not link-co
>  compile your entire program with the same ABI, and link with a
>  compatible set of libraries.
>
> +@item -mgeneral-regs-only
> +@opindex mgeneral-regs-only
> +Generate code which uses only the general-purpose registers.  This will 
> prevent
> +the compiler from using floating-point and Advanced SIMD registers but will 
> not
> +impose any restrictions on the assembler.
> +
>  @item -mlittle-endian
>  @opindex mlittle-endian
>  Generate code for a processor running in little-endian mode.  This is
> --- gcc/ada/raise-gcc.c (revision 270444)
> +++ gcc/ada/raise-gcc.c (working copy)
> @@ -1154,10 +1154,18 @@ extern void __gnat_notify_unhandled_exce
>  #define PERSONALITY_FUNCTION    __gnat_personality_v0
>  #endif
>
> +#if defined (__ARM_EABI_UNWINDER__) \
> +    && (defined (IN_RTS) || GCC_VERSION > 9000)
> +#define TARGET_ATTRIBUTE __attribute__((target ("general-regs-only")))
> +#else
> +#define TARGET_ATTRIBUTE
> +#endif
> +
>  /* Code executed to continue unwinding.  With the ARM unwinder, the
>     personality routine must unwind one frame (per EHABI 7.3 4.).  */
>
>  static _Unwind_Reason_Code
> +TARGET_ATTRIBUTE
>  continue_unwind (struct _Unwind_Exception* ue_header ATTRIBUTE_UNUSED,
>                  struct _Unwind_Context* uw_context ATTRIBUTE_UNUSED)
>  {
> @@ -1172,6 +1180,7 @@ continue_unwind (struct _Unwind_Exceptio
>     between all unwinders.  */
>
>  static _Unwind_Reason_Code
> +TARGET_ATTRIBUTE
>  personality_body (_Unwind_Action uw_phases,
>                   _Unwind_Exception *uw_exception,
>                   _Unwind_Context *uw_context)
> @@ -1342,6 +1351,7 @@ PERSONALITY_FUNCTION (_Unwind_State stat
>                       struct _Unwind_Context* uw_context);
>
>  PERSONALITY_STORAGE _Unwind_Reason_Code
> +TARGET_ATTRIBUTE
>  PERSONALITY_FUNCTION (_Unwind_State state,
>                       struct _Unwind_Exception* uw_exception,
>                       struct _Unwind_Context* uw_context)
> --- libgcc/config/arm/pr-support.c      (revision 270444)
> +++ libgcc/config/arm/pr-support.c      (working copy)
> @@ -21,6 +21,7 @@
>     see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
>     <http://www.gnu.org/licenses/>.  */
>
> +#pragma GCC target ("general-regs-only")
>  #include "unwind.h"
>
>  /* We add a prototype for abort here to avoid creating a dependency on
> --- libgcc/config/arm/unwind-arm.c      (revision 270444)
> +++ libgcc/config/arm/unwind-arm.c      (working copy)
> @@ -21,6 +21,7 @@
>     see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
>     <http://www.gnu.org/licenses/>.  */
>
> +#pragma GCC target ("general-regs-only")
>  #include "unwind.h"
>
>  /* Misc constants.  */
> --- libgcc/unwind-c.c   (revision 270444)
> +++ libgcc/unwind-c.c   (working copy)
> @@ -106,6 +106,7 @@ PERSONALITY_FUNCTION (_Unwind_State, struct _Unwin
>                       struct _Unwind_Context *);
>
>  _Unwind_Reason_Code
> +__attribute__((target ("general-regs-only")))
>  PERSONALITY_FUNCTION (_Unwind_State state,
>                       struct _Unwind_Exception * ue_header,
>                       struct _Unwind_Context * context)
> --- libgo/runtime/go-unwind.c   (revision 270444)
> +++ libgo/runtime/go-unwind.c   (working copy)
> @@ -411,7 +411,7 @@ parse_lsda_header (struct _Unwind_Contex
>  _Unwind_Reason_Code
>  PERSONALITY_FUNCTION (_Unwind_State, struct _Unwind_Exception *,
>                       struct _Unwind_Context *)
> -  __attribute__ ((no_split_stack, flatten));
> +  __attribute__ ((no_split_stack, flatten, target ("general-regs-only")));
>
>  _Unwind_Reason_Code
>  PERSONALITY_FUNCTION (_Unwind_State state,
> @@ -604,6 +604,9 @@ __gccgo_personality_dummy (int, _Unwind_
>    __attribute__ ((no_split_stack));
>
>  _Unwind_Reason_Code
> +#ifdef __ARM_EABI_UNWINDER__
> +__attribute__ ((target ("general-regs-only")))
> +#endif
>  __gccgo_personality_dummy (int version __attribute__ ((unused)),
>                       _Unwind_Action actions __attribute__ ((unused)),
>                       _Unwind_Exception_Class exception_class __attribute__ 
> ((unused)),
> --- libobjc/exception.c (revision 270444)
> +++ libobjc/exception.c (working copy)
> @@ -220,6 +220,7 @@ get_ttype_entry (struct lsda_header_info *info, _U
>    while (0)
>
>  _Unwind_Reason_Code
> +__attribute__((target ("general-regs-only")))
>  PERSONALITY_FUNCTION (_Unwind_State state,
>                       struct _Unwind_Exception *ue_header,
>                       struct _Unwind_Context *context)
> --- libphobos/libdruntime/gcc/deh.d     (revision 270444)
> +++ libphobos/libdruntime/gcc/deh.d     (working copy)
> @@ -28,6 +28,7 @@ import gcc.unwind;
>  import gcc.unwind.pe;
>  import gcc.builtins;
>  import gcc.config;
> +import gcc.attribute;
>
>  extern(C)
>  {
> @@ -519,10 +520,19 @@ extern(C) void _d_throw(Throwable object)
>      terminate("unwind error", __LINE__);
>  }
>
> +static if (GNU_ARM_EABI_Unwinder)
> +{
> +    enum personality_fn_attributes = attribute("target", 
> ("general-regs-only"));
> +}
> +else
> +{
> +    enum personality_fn_attributes = "";
> +}
>
>  /**
>   * Read and extract information from the LSDA (.gcc_except_table section).
>   */
> +@personality_fn_attributes
>  _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class 
> exceptionClass,
>                               _Unwind_Action actions, _Unwind_Exception* 
> unwindHeader,
>                               _Unwind_Context* context, _Unwind_Word cfa,
> @@ -772,6 +782,7 @@ int actionTableLookup(_Unwind_Action actions, _Unw
>   * Called when the personality function has found neither a cleanup or 
> handler.
>   * To support ARM EABI personality routines, that must also unwind the stack.
>   */
> +@personality_fn_attributes
>  _Unwind_Reason_Code CONTINUE_UNWINDING(_Unwind_Exception* unwindHeader, 
> _Unwind_Context* context)
>  {
>      static if (GNU_ARM_EABI_Unwinder)
> @@ -814,6 +825,7 @@ else
>  static if (GNU_ARM_EABI_Unwinder)
>  {
>      pragma(mangle, PERSONALITY_FUNCTION)
> +    @personality_fn_attributes
>      extern(C) _Unwind_Reason_Code gdc_personality(_Unwind_State state,
>                                                    _Unwind_Exception* 
> unwindHeader,
>                                                    _Unwind_Context* context)
> @@ -873,6 +885,7 @@ else
>      }
>  }
>
> +@personality_fn_attributes
>  private _Unwind_Reason_Code __gdc_personality(_Unwind_Action actions,
>                                                _Unwind_Exception_Class 
> exceptionClass,
>                                                _Unwind_Exception* 
> unwindHeader,
> --- libstdc++-v3/libsupc++/eh_personality.cc    (revision 270444)
> +++ libstdc++-v3/libsupc++/eh_personality.cc    (working copy)
> @@ -343,6 +343,7 @@ extern "C"
>  #endif
>  _Unwind_Reason_Code
>  #ifdef __ARM_EABI_UNWINDER__
> +__attribute__((target ("general-regs-only")))
>  PERSONALITY_FUNCTION (_Unwind_State state,
>                       struct _Unwind_Exception* ue_header,
>                       struct _Unwind_Context* context)
>
>         Jakub

Reply via email to