OSDN Git Service

PR target/21078, 21080
authorhutchinsonandy <hutchinsonandy@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 15 Nov 2009 04:10:20 +0000 (04:10 +0000)
committerhutchinsonandy <hutchinsonandy@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 15 Nov 2009 04:10:20 +0000 (04:10 +0000)
* config/avr/avr.c (avr_return_addr_rtx): New function for
builtin_return_address.
(expand_prologue): Calculate stack usage.
(avr_asm_function_end_prologue): Output stack size and offset label.
* config/avr/avr.h (RETURN_ADDR_RTX): Replace.
(machine_function): Add stack_usage.
* config/avr/avr-protos.h (avr_return_addr_rtx): New function.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@154188 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/avr/avr-protos.h
gcc/config/avr/avr.c
gcc/config/avr/avr.h

index e8ed5eb..0ee4395 100644 (file)
@@ -1,3 +1,14 @@
+2009-11-14  Andy Hutchinson   <hutchinsonandy@gcc.gnu.org>
+
+       PR target/21078, 21080
+       * config/avr/avr.c (avr_return_addr_rtx): New function for
+       builtin_return_address.
+       (expand_prologue): Calculate stack usage.
+       (avr_asm_function_end_prologue): Output stack size and offset label.
+       * config/avr/avr.h (RETURN_ADDR_RTX): Replace.
+       (machine_function): Add stack_usage.
+       * config/avr/avr-protos.h (avr_return_addr_rtx): New function.
+
 2009-11-14  Anatoly Sokolov  <aesok@post.ru>
 
        * config/iq2000/iq2000.c (iq2000_function_value): Make static, add
index c39b97b..e014085 100644 (file)
@@ -39,6 +39,7 @@ extern int avr_simple_epilogue (void);
 extern void gas_output_limited_string (FILE *file, const char *str);
 extern void gas_output_ascii (FILE *file, const char *str, size_t length);
 extern int avr_hard_regno_rename_ok (unsigned int, unsigned int);
+extern rtx avr_return_addr_rtx (int count, const_rtx tem);
 
 #ifdef TREE_CODE
 extern void asm_output_external (FILE *file, tree decl, char *name);
index cb2d709..b1713a8 100644 (file)
@@ -461,6 +461,31 @@ rtx avr_builtin_setjmp_frame_value (void)
                         gen_int_mode (STARTING_FRAME_OFFSET, Pmode));
 }
 
+/* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3 byte PC).
+   This is return address of function.  */
+rtx 
+avr_return_addr_rtx (int count, const_rtx tem)
+{
+  rtx r;
+    
+  /* Can only return this functions return address. Others not supported.  */
+  if (count)
+     return NULL;
+
+  if (AVR_3_BYTE_PC)
+    {
+      r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
+      warning (0, "'builtin_return_address' contains only 2 bytes of address");
+    }
+  else
+    r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
+
+  r = gen_rtx_PLUS (Pmode, tem, r);
+  r = gen_frame_mem (Pmode, memory_address (Pmode, r));
+  r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
+  return  r;
+}
+
 /* Return 1 if the function epilogue is just a single "ret".  */
 
 int
@@ -560,6 +585,7 @@ expand_prologue (void)
   cfun->machine->is_signal = signal_function_p (current_function_decl);
   cfun->machine->is_OS_task = avr_OS_task_function_p (current_function_decl);
   cfun->machine->is_OS_main = avr_OS_main_function_p (current_function_decl);
+  cfun->machine->stack_usage = 0;
   
   /* Prologue: naked.  */
   if (cfun->machine->is_naked)
@@ -588,10 +614,12 @@ expand_prologue (void)
       /* Push zero reg.  */
       insn = emit_move_insn (pushbyte, zero_reg_rtx);
       RTX_FRAME_RELATED_P (insn) = 1;
+      cfun->machine->stack_usage++;
 
       /* Push tmp reg.  */
       insn = emit_move_insn (pushbyte, tmp_reg_rtx);
       RTX_FRAME_RELATED_P (insn) = 1;
+      cfun->machine->stack_usage++;
 
       /* Push SREG.  */
       insn = emit_move_insn (tmp_reg_rtx, 
@@ -599,6 +627,7 @@ expand_prologue (void)
       RTX_FRAME_RELATED_P (insn) = 1;
       insn = emit_move_insn (pushbyte, tmp_reg_rtx);
       RTX_FRAME_RELATED_P (insn) = 1;
+      cfun->machine->stack_usage++;
 
       /* Push RAMPZ.  */
       if(AVR_HAVE_RAMPZ 
@@ -609,6 +638,7 @@ expand_prologue (void)
           RTX_FRAME_RELATED_P (insn) = 1;
           insn = emit_move_insn (pushbyte, tmp_reg_rtx);
           RTX_FRAME_RELATED_P (insn) = 1;
+          cfun->machine->stack_usage++;
         }
        
       /* Clear zero reg.  */
@@ -630,6 +660,7 @@ expand_prologue (void)
         emit_insn (gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
                                            gen_int_mode (size + live_seq, HImode)));
       RTX_FRAME_RELATED_P (insn) = 1;
+      cfun->machine->stack_usage += size + live_seq;
     }
   else
     {
@@ -641,6 +672,7 @@ expand_prologue (void)
               /* Emit push of register to save.  */
               insn=emit_move_insn (pushbyte, gen_rtx_REG (QImode, reg));
               RTX_FRAME_RELATED_P (insn) = 1;
+              cfun->machine->stack_usage++;
             }
         }
       if (frame_pointer_needed)
@@ -650,6 +682,7 @@ expand_prologue (void)
               /* Push frame pointer.  */
              insn = emit_move_insn (pushword, frame_pointer_rtx);
               RTX_FRAME_RELATED_P (insn) = 1;
+             cfun->machine->stack_usage += 2;
            }
 
           if (!size)
@@ -756,6 +789,7 @@ expand_prologue (void)
                emit_insn (sp_plus_insns);
               else
                emit_insn (fp_plus_insns);
+             cfun->machine->stack_usage += size;
             }
         }
     }
@@ -785,6 +819,11 @@ avr_asm_function_end_prologue (FILE *file)
     }
   fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
                  get_frame_size());
+  fprintf (file, "/* stack size = %d */\n",
+                 cfun->machine->stack_usage);
+  /* Create symbol stack offset here so all functions have it. Add 1 to stack
+     usage for offset so that SP + .L__stack_offset = return address.  */
+  fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
 }
 
 
index 782ad11..4e07a2e 100644 (file)
@@ -367,8 +367,7 @@ enum reg_class {
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                   \
   OFFSET = avr_initial_elimination_offset (FROM, TO)
 
-#define RETURN_ADDR_RTX(count, x) \
-  gen_rtx_MEM (Pmode, memory_address (Pmode, plus_constant (tem, 1)))
+#define RETURN_ADDR_RTX(count, tem) avr_return_addr_rtx (count, tem)
 
 /* Don't use Push rounding. expr.c: emit_single_push_insn is broken 
    for POST_DEC targets (PR27386).  */
@@ -857,4 +856,7 @@ struct GTY(()) machine_function
   /* 'true' - if current function is a 'main' function 
      as specified by the "OS_main" attribute.  */
   int is_OS_main;
+  
+  /* Current function stack size.  */
+  int stack_usage;
 };