This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: ARM/Thumb backend and CAN_DEBUG_WITHOUT_FP


> > What was wrong with this patch that I committed some time back?  It was 
> > supposed to have addressed the different requirements of ARM/Thumb code.
> 
> Aaarrgh.  I was under the impression that the Cygnus internal version of
> that backend didn't differ significantly from the egcs one.  I was working
> with the former.
> However, I have trouble finding the patch in the mailing list archives,
> and the CVS logs aren't too helpful either.  Could you send me that patch
> again?

Probably because since it was a backend patch on the branch I didn't send 
it to the main list.  I did mail Nick, however.

Here's the original message I sent to Nick





As I mentioned before, merging the arm & thumb back ends means that we 
really need to set the compiler up to work with CAN_DEBUG_WITHOUT_FP 
defined, but this is just an ifdef, not something that can have a variable 
definition.  In order to support frames correctly on ARM platforms we need 
to correctly implement the -mapcs-frame option (AKA -mapcs), which for too 
long now has been non-functional.  Below is a patch to do this (this has 
been on my to-do list for donkey's ages -- but I've been too lazy to do 
anything about it before now).

What the patch does:

Internally, it renames TARGET_APCS to TARGET_APCS_FRAME (mainly cosmetic).

Fixes checks in various places which decide whether a stack frame should 
be pushed or not.

Allows r11 (fp) to become a normal register when compiling -mno-apcs-frame.

When -mapcs-frame, allows elimination of the frame-pointer in leaf 
functions, but not in non-leaf functions.  This is reasonable, gdb should 
be able to give a descent stack backtrace for this, even if it gets 
confused with more complex frameless stack frames.

Makes several ports default to -mapcs-frame.  There may be others for 
which it would be a good idea as well, but I've no direct access to these 
ports to be sure.  We need to go around and check all the different arm 
configs to see that we have this right.  Adding -mapcs-frame makes the 
behaviour nearly compatible with gcc-2.95 (the deviation is in the 
handling of leaf functions).

Fixes the warning about debugging without a frame-pointer so that it now 
reflects reality -- the warning is only generated if the compiler is 
configured to normally use -mapcs-frame and this has been turned off and 
-g turned on.  The check doesn't re-enable the option, since this is 
proscribed by the gcc porting manual.

I still need to update the docs to reflect the changes, I'll do that 
separately.

There are a couple of other minor nits fixed as well.  I've checked this 
with a bootstraps with both -mapcs-frame and -mno-apcs-frame.

R.


Mon Oct 25 15:42:09 1999  Richard Earnshaw (rearnsha@arm.com)

	* arm.h (TARGET_APCS_FRAME): Renamed from TARGET_APCS -- all uses
	updated.
	(CAN_DEBUG_WITHOUT_FP): Define.
	(FIXED_REGISTERS): Make r11 call-saved.
	(CALL_USED_REGISTERS): Likewise.
	(CONDITIONAL_REGISTER_USAGE): Fix r11 if TARGET_APCS_FRAME.
	(FRAME_POINTER_REQUIRED): Correct logic for determining when a 
	frame-pointer is required.
	(TARGET_DEFAULT): Make default setting include ARM_FLAG_APCS_FRAME.
	* arm.c (arm_override_options): Warn about -mno-apcs-frame and -g
	if the target normally needs a stack frame in non-leaf functions.
	(use_return_insn): Correct logic for determining when a return
	instruction can be used.
	(output_return_instruction): Handle the frame-pointer register as
	a normal register when not TARGET_APCS_FRAME.
	(arm_output_prologue): Likewise.
	(arm_output_epilogue): Likewise.
	(output_func_epilogue): Likewise.
	(arm_expand_prologue): Likewise.
	* netbsd.h semi.h (TARGET_DEFAULT): Add ARM_FLAG_APCS_FRAME.

	* arm.c (use_return_insn): No need to check floating point regs if
	TARGET_SOFT_FLOAT.
	(arm_find_minipool_constant): Correct typo; use GET_CODE to get
	the code of value stored in the minipool array.
	(arm_add_minipool_constant): Likewise.


Index: arm.c
===================================================================
RCS file: /home/rearnsha/gnusrc/new-arm/cvs/arm/arm.c,v
retrieving revision 1.3
diff -p -r1.3 arm.c
*** arm.c	1999/10/23 15:28:19	1.3
--- arm.c	1999/10/25 11:00:38
*************** arm_override_options ()
*** 514,520 ****
        target_flags |= ARM_FLAG_APCS_32;
      }
    
!   if (TARGET_APCS_STACK && ! TARGET_APCS)
      {
        warning ("-mapcs-stack-check incompatible with -mno-apcs-frame");
        target_flags |= ARM_FLAG_APCS_FRAME;
--- 514,520 ----
        target_flags |= ARM_FLAG_APCS_32;
      }
    
!   if (TARGET_APCS_STACK && ! TARGET_APCS_FRAME)
      {
        warning ("-mapcs-stack-check incompatible with -mno-apcs-frame");
        target_flags |= ARM_FLAG_APCS_FRAME;
*************** arm_override_options ()
*** 528,544 ****
    
    if (TARGET_APCS_REENT)
      warning ("APCS reentrant code not supported.  Ignored");
!   
!   if (write_symbols != NO_DEBUG && flag_omit_frame_pointer)
!     {
!       if (TARGET_ARM)
! 	{
! 	  if (optimize >= 1)
! 	    flag_omit_frame_pointer = 0;
! 	  else
! 	    warning ("-g with -fomit-frame-pointer may not give sensible debugging");
! 	}
!     }
    
    /* If stack checking is disabled, we can use r10 as the PIC register,
       which keeps r9 available.  */
--- 528,541 ----
    
    if (TARGET_APCS_REENT)
      warning ("APCS reentrant code not supported.  Ignored");
! 
!   /* If this target is normally configured to use APCS frames, warn if they
!      are turned off and debugging is turned on.  */
!   if (TARGET_ARM
!       && write_symbols != NO_DEBUG
!       && ! TARGET_APCS_FRAME
!       && (TARGET_DEFAULT & ARM_FLAG_APCS_FRAME))
!     warning ("-g with -mno-apcs-frame may not give sensible debugging");
    
    /* If stack checking is disabled, we can use r10 as the PIC register,
       which keeps r9 available.  */
*************** use_return_insn (iscond)
*** 654,664 ****
  {
    int regno;
  
!   if (!reload_completed
        || current_function_pretend_args_size
        || current_function_anonymous_args
        || ((get_frame_size () + current_function_outgoing_args_size != 0)
! 	  && !(TARGET_APCS && frame_pointer_needed)))
      return 0;
  
    /* Can't be done if interworking with Thumb, and any registers have been
--- 651,664 ----
  {
    int regno;
  
!   /* Never use a return instruction before reload has run */
!   if (! reload_completed
!       /* Or if the function is variadic */
        || current_function_pretend_args_size
        || current_function_anonymous_args
+       /* Or if there is no frame pointer and there is a stack adjustment */
        || ((get_frame_size () + current_function_outgoing_args_size != 0)
! 	  && ! frame_pointer_needed))
      return 0;
  
    /* Can't be done if interworking with Thumb, and any registers have been
*************** use_return_insn (iscond)
*** 680,688 ****
        
    /* Can't be done if any of the FPU regs are pushed, since this also
       requires an insn */
!   for (regno = FIRST_ARM_FP_REGNUM; regno <= LAST_ARM_FP_REGNUM; regno++)
!     if (regs_ever_live[regno] && ! call_used_regs[regno])
!       return 0;
  
    /* If a function is naked, don't use the "return" insn.  */
    if (arm_naked_function_p (current_function_decl))
--- 680,689 ----
        
    /* Can't be done if any of the FPU regs are pushed, since this also
       requires an insn */
!   if (TARGET_HARD_FLOAT)
!     for (regno = FIRST_ARM_FP_REGNUM; regno <= LAST_ARM_FP_REGNUM; regno++)
!       if (regs_ever_live[regno] && ! call_used_regs[regno])
! 	return 0;
  
    /* If a function is naked, don't use the "return" insn.  */
    if (arm_naked_function_p (current_function_decl))
*************** arm_find_minipool_constant (x, mode)
*** 4377,4385 ****
    int i;
  
    for (i = 0; i < minipool_size; i++)
!     if (GET_CODE (x) == minipool_vector[i].value->code
  	&& mode == minipool_vector[i].mode
! 	&& (GET_CODE (x) == CODE_LABEL
  	    || XINT (x, 3) == XINT (minipool_vector[i].value, 3))
  	&& rtx_equal_p (x, minipool_vector[i].value))
        return minipool_vector[i].offset;
--- 4378,4386 ----
    int i;
  
    for (i = 0; i < minipool_size; i++)
!     if (GET_CODE (x) == GET_CODE (minipool_vector[i].value)
  	&& mode == minipool_vector[i].mode
! 	&& (GET_CODE (x) != CODE_LABEL
  	    || XINT (x, 3) == XINT (minipool_vector[i].value, 3))
  	&& rtx_equal_p (x, minipool_vector[i].value))
        return minipool_vector[i].offset;
*************** arm_add_minipool_constant (x, mode)
*** 4398,4406 ****
  
    /* First, see if we've already got it.  */
    for (i = 0; i < minipool_size; i++)
!     if (GET_CODE (x) == minipool_vector[i].value->code
  	&& mode == minipool_vector[i].mode
! 	&& (GET_CODE (x) == CODE_LABEL
  	    || XINT (x, 3) == XINT (minipool_vector[i].value, 3))
  	&& rtx_equal_p (x, minipool_vector[i].value))
        {
--- 4399,4407 ----
  
    /* First, see if we've already got it.  */
    for (i = 0; i < minipool_size; i++)
!     if (GET_CODE (x) == GET_CODE (minipool_vector[i].value)
  	&& mode == minipool_vector[i].mode
! 	&& (GET_CODE (x) != CODE_LABEL
  	    || XINT (x, 3) == XINT (minipool_vector[i].value, 3))
  	&& rtx_equal_p (x, minipool_vector[i].value))
        {
*************** output_return_instruction (operand, real
*** 5976,5981 ****
--- 5977,5988 ----
      if (regs_ever_live[reg] && ! call_used_regs[reg])
        live_regs++;
  
+   if (! TARGET_APCS_FRAME
+       && ! frame_pointer_needed
+       && regs_ever_live[HARD_FRAME_POINTER_REGNUM]
+       && ! call_used_regs[HARD_FRAME_POINTER_REGNUM])
+     live_regs++;
+ 
    if (flag_pic && ! TARGET_SINGLE_PIC_BASE
        && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
      live_regs++;
*************** output_return_instruction (operand, real
*** 6024,6029 ****
--- 6031,6044 ----
          }
        else
  	{
+ 	  if (! TARGET_APCS_FRAME
+ 	      && regs_ever_live[HARD_FRAME_POINTER_REGNUM]
+ 	      && ! call_used_regs[HARD_FRAME_POINTER_REGNUM])
+ 	    {
+ 	      strcat (instr, "%|");
+ 	      strcat (instr, reg_names[HARD_FRAME_POINTER_REGNUM]);
+ 	      strcat (instr, ", ");
+ 	    }
  	  strcat (instr, "%|");
  	  if (TARGET_INTERWORK && really_return)
  	    strcat (instr, reg_names[IP_REGNUM]);
*************** output_arm_prologue (f, frame_size)
*** 6162,6167 ****
--- 6177,6188 ----
      if (regs_ever_live[reg] && ! call_used_regs[reg])
        live_regs_mask |= (1 << reg);
  
+   if (! TARGET_APCS_FRAME
+       && ! frame_pointer_needed
+       && regs_ever_live[HARD_FRAME_POINTER_REGNUM]
+       && ! call_used_regs[HARD_FRAME_POINTER_REGNUM])
+     live_regs_mask |= (1 << HARD_FRAME_POINTER_REGNUM);
+ 
    if (flag_pic && ! TARGET_SINGLE_PIC_BASE
        && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
      live_regs_mask |= (1 << PIC_OFFSET_TABLE_REGNUM);
*************** arm_output_epilogue ()
*** 6235,6240 ****
--- 6256,6271 ----
  	floats_offset += 4;
        }
  
+   /* Handle the frame pointer as a special case.  */
+   if (! TARGET_APCS_FRAME
+       && ! frame_pointer_needed
+       && regs_ever_live[HARD_FRAME_POINTER_REGNUM]
+       && ! call_used_regs[HARD_FRAME_POINTER_REGNUM])
+     {
+       live_regs_mask |= (1 << HARD_FRAME_POINTER_REGNUM);
+       floats_offset += 4;
+     }
+ 
    /* If we aren't loading the PIC register, don't stack it even though it may
       be live.  */
    if (flag_pic && ! TARGET_SINGLE_PIC_BASE 
*************** output_func_epilogue (frame_size)
*** 6424,6430 ****
        if (use_return_insn (FALSE)
  	  && return_used_this_function
  	  && (frame_size + current_function_outgoing_args_size) != 0
! 	  && !(frame_pointer_needed && TARGET_APCS))
  	abort ();
  
        /* Reset the ARM-specific per-function variables.  */
--- 6455,6461 ----
        if (use_return_insn (FALSE)
  	  && return_used_this_function
  	  && (frame_size + current_function_outgoing_args_size) != 0
! 	  && ! frame_pointer_needed)
  	abort ();
  
        /* Reset the ARM-specific per-function variables.  */
*************** arm_expand_prologue ()
*** 6530,6535 ****
--- 6561,6572 ----
        for (reg = 0; reg <= 10; reg++)
  	if (regs_ever_live[reg] && ! call_used_regs[reg])
  	  live_regs_mask |= 1 << reg;
+ 
+       if (! TARGET_APCS_FRAME
+ 	  && ! frame_pointer_needed
+ 	  && regs_ever_live[HARD_FRAME_POINTER_REGNUM]
+ 	  && ! call_used_regs[HARD_FRAME_POINTER_REGNUM])
+ 	live_regs_mask |= (1 << HARD_FRAME_POINTER_REGNUM);
  
        if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
  	live_regs_mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
Index: arm.h
===================================================================
RCS file: /home/rearnsha/gnusrc/new-arm/cvs/arm/arm.h,v
retrieving revision 1.3
diff -p -r1.3 arm.h
*** arm.h	1999/10/23 15:28:20	1.3
--- arm.h	1999/10/23 16:23:17
*************** Unrecognized value in TARGET_CPU_DEFAULT
*** 349,355 ****
     destination is non-Thumb aware.  */
  #define THUMB_FLAG_CALLER_SUPER_INTERWORKING	(1 << 20)
  
! #define TARGET_APCS			(target_flags & ARM_FLAG_APCS_FRAME)
  #define TARGET_POKE_FUNCTION_NAME	(target_flags & ARM_FLAG_POKE)
  #define TARGET_FPE			(target_flags & ARM_FLAG_FPE)
  #define TARGET_APCS_32			(target_flags & ARM_FLAG_APCS_32)
--- 349,355 ----
     destination is non-Thumb aware.  */
  #define THUMB_FLAG_CALLER_SUPER_INTERWORKING	(1 << 20)
  
! #define TARGET_APCS_FRAME		(target_flags & ARM_FLAG_APCS_FRAME)
  #define TARGET_POKE_FUNCTION_NAME	(target_flags & ARM_FLAG_POKE)
  #define TARGET_FPE			(target_flags & ARM_FLAG_FPE)
  #define TARGET_APCS_32			(target_flags & ARM_FLAG_APCS_32)
*************** extern int arm_is_strong;
*** 538,549 ****
  extern int arm_is_6_or_7;
  
  #ifndef TARGET_DEFAULT
! #define TARGET_DEFAULT  0
  #endif
  
  /* The frame pointer register used in gcc has nothing to do with debugging;
     that is controlled by the APCS-FRAME option.  */
! #define CAN_DEBUG_WITHOUT_FP (TARGET_THUMB)
  
  #define TARGET_MEM_FUNCTIONS 1
  
--- 538,549 ----
  extern int arm_is_6_or_7;
  
  #ifndef TARGET_DEFAULT
! #define TARGET_DEFAULT  (ARM_FLAG_APCS_FRAME)
  #endif
  
  /* The frame pointer register used in gcc has nothing to do with debugging;
     that is controlled by the APCS-FRAME option.  */
! #define CAN_DEBUG_WITHOUT_FP
  
  #define TARGET_MEM_FUNCTIONS 1
  
*************** extern const char * structure_size_strin
*** 755,761 ****
  #define FIXED_REGISTERS  \
  {                        \
    0,0,0,0,0,0,0,0,	 \
!   0,0,0,1,0,1,0,1,	 \
    0,0,0,0,0,0,0,0,	 \
    1,1,1			 \
  }
--- 755,761 ----
  #define FIXED_REGISTERS  \
  {                        \
    0,0,0,0,0,0,0,0,	 \
!   0,0,0,0,0,1,0,1,	 \
    0,0,0,0,0,0,0,0,	 \
    1,1,1			 \
  }
*************** extern const char * structure_size_strin
*** 771,777 ****
  #define CALL_USED_REGISTERS  \
  {                            \
    1,1,1,1,0,0,0,0,	     \
!   0,0,0,1,1,1,1,1,	     \
    1,1,1,1,0,0,0,0,	     \
    1,1,1			     \
  }
--- 771,777 ----
  #define CALL_USED_REGISTERS  \
  {                            \
    1,1,1,1,0,0,0,0,	     \
!   0,0,0,0,1,1,1,1,	     \
    1,1,1,1,0,0,0,0,	     \
    1,1,1			     \
  }
*************** extern const char * structure_size_strin
*** 804,809 ****
--- 804,814 ----
        fixed_regs[10]     = 1;				\
        call_used_regs[10] = 1;				\
      }							\
+   if (TARGET_APCS_FRAME)				\
+     {							\
+       fixed_regs[HARD_FRAME_POINTER_REGNUM] = 1;	\
+       call_used_regs[HARD_FRAME_POINTER_REGNUM] = 1;	\
+     }							\
    SUBTARGET_CONDITIONAL_REGISTER_USAGE 		        \
  }
      
*************** extern const char * structure_size_strin
*** 919,926 ****
     If we have to have a frame pointer we might as well make use of it.
     APCS says that the frame pointer does not need to be pushed in leaf
     functions, or simple tail call functions.  */
! #define FRAME_POINTER_REQUIRED		\
!   (current_function_has_nonlocal_label || (TARGET_APCS && !leaf_function_p ()))
  
  /* Return number of consecutive hard regs needed starting at reg REGNO
     to hold something of mode MODE.
--- 924,932 ----
     If we have to have a frame pointer we might as well make use of it.
     APCS says that the frame pointer does not need to be pushed in leaf
     functions, or simple tail call functions.  */
! #define FRAME_POINTER_REQUIRED				\
!   (current_function_has_nonlocal_label			\
!    || (TARGET_APCS_FRAME && ! leaf_function_p ()))
  
  /* Return number of consecutive hard regs needed starting at reg REGNO
     to hold something of mode MODE.
*************** enum reg_class
*** 1552,1557 ****
--- 1558,1568 ----
            for (regno = 0; regno <= 10; regno++)				\
  	    if (regs_ever_live[regno] && ! call_used_regs[regno])	\
  	      saved_hard_reg = 1, offset += 4;				\
+ 	  if (! TARGET_APCS_FRAME					\
+ 	      && ! frame_pointer_needed					\
+ 	      && regs_ever_live[HARD_FRAME_POINTER_REGNUM]		\
+ 	      && ! call_used_regs[HARD_FRAME_POINTER_REGNUM])		\
+ 	    saved_hard_reg = 1, offset += 4;				\
  	  /* PIC register is a fixed reg, so call_used_regs set.  */	\
  	  if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])	\
  	    saved_hard_reg = 1, offset += 4;				\
Index: netbsd.h
===================================================================
RCS file: /home/rearnsha/gnusrc/new-arm/cvs/arm/netbsd.h,v
retrieving revision 1.1.1.1
diff -p -r1.1.1.1 netbsd.h
*** netbsd.h	1999/10/23 12:13:32	1.1.1.1
--- netbsd.h	1999/10/23 16:17:44
*************** Boston, MA 02111-1307, USA.  */
*** 37,43 ****
  #define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
  
  /* Default is to use APCS-32 mode.  */
! #define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_SOFT_FLOAT)
  
  #include "arm/aout.h"
  
--- 37,44 ----
  #define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
  
  /* Default is to use APCS-32 mode.  */
! #define TARGET_DEFAULT \
! 	(ARM_FLAG_APCS_32 | ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_FRAME)
  
  #include "arm/aout.h"
  
Index: semi.h
===================================================================
RCS file: /home/rearnsha/gnusrc/new-arm/cvs/arm/semi.h,v
retrieving revision 1.1.1.2
diff -p -r1.1.1.2 semi.h
*** semi.h	1999/10/23 12:14:23	1.1.1.2
--- semi.h	1999/10/23 16:20:09
*************** Boston, MA 02111-1307, USA.  */
*** 31,37 ****
  
  #define TARGET_VERSION fputs (" (ARM/semi-hosted)", stderr);
  
! #define TARGET_DEFAULT ARM_FLAG_APCS_32
  
  #include "arm/aout.h"
      
--- 31,37 ----
  
  #define TARGET_VERSION fputs (" (ARM/semi-hosted)", stderr);
  
! #define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME)
  
  #include "arm/aout.h"
      



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]