diff options
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config/avr/avr-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/avr/avr.c | 39 | ||||
-rw-r--r-- | gcc/config/avr/avr.h | 6 |
4 files changed, 55 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e8ed5eb..0ee4395 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h index c39b97b..e014085 100644 --- a/gcc/config/avr/avr-protos.h +++ b/gcc/config/avr/avr-protos.h @@ -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); diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index cb2d709..b1713a8 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -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); } diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index 782ad11..4e07a2e 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -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; }; |