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