[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[avr-gcc-list] noreturn, naked & nonret function attributes
From: |
Kang Tin LAI |
Subject: |
[avr-gcc-list] noreturn, naked & nonret function attributes |
Date: |
Sun, 17 Feb 2002 16:43:11 +0800 |
Dear all,
A) With or without "noreturn" function attribute, no change of prologue
and epilogue, nothing help to the code size. Attempted to add a codes to
test the "noreturn" attribute from avr.c, but always return failed, GCC
traps all the test of "noreturn" inside the share portion codes, so
nothing can be done in machine specific codes with "noreturn" attribute.
B) With "naked" function attribute, it saves quite lot of codes, but
there is a problem, if you have local variables and you access the
address of them, example:
__attribute__ ((naked)) void func(void)
{
int i;
while (1) {
fxn(&i);
}
}
then you will get a problem. To access address of i, you need the frame
pointer, prologue codes setup the frame pointer for you. But with
"naked" attribute, no prologue at all.
For certain scenario, such as some rtos, task is a endless loop function
actually, never return. As in AvrX, task is a "naked" attribute
function, so no frame pointer is setup for the task. (ie., inside the
task of AvrX, you may not have any code dealing with address or playing
with frame pointer).
There is no problem using "naked" if you have only FEW automatics (autos
will be put in the registers) with simple data type and no lvalve access
of automatics. Anyway, it should not be here with this restriction.
C) I attempted to make a change to gcc by adding a new attribute -
"nonret" (non-return). Attached is the patch for this. Patch is based on
lastest release gcc 3.0.3., however, any other version should be no
problem, patch only acts on avr.c only. (actually, file date of avr.c is
last year June in 3.0.3 release).
With the "nonret" attribute:
1) no register will be preserved onto the stack, because we never
return,
saving any register is meaningless and code space consuming.
2) local var frame and frame pointer will be setup as usual.
3) no epilogue (save code space).
Unpack gcc, cd to ./gcc-3.0.3/gcc/config/avr, patch avr.c directly with
the patch attached with the command: patch < patch-avr.c-20020217, then
recompile gcc.
Layout of function with "nonret" attribute:
__attribute__ ((nonret)) void task1(void)
{
local variables;
....
while (1) {
.......
.......
}
}
If you confirm that your code never touch the frame pointer, choose
"naked" because of the most code space saving, else "nonret" as needs.
Cheers!
Kang Tin LAI
*** avr.c.orig Thu Jun 28 05:35:37 2001
--- avr.c Sun Feb 17 14:18:57 2002
***************
*** 43,48 ****
--- 43,49 ----
#define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
static int avr_naked_function_p PARAMS ((tree));
+ static int nonret_function_p PARAMS ((tree));
static int interrupt_function_p PARAMS ((tree));
static int signal_function_p PARAMS ((tree));
static int sequent_regs_live PARAMS ((void));
*************** avr_naked_function_p (func)
*** 290,300 ****
if (TREE_CODE (func) != FUNCTION_DECL)
abort ();
!
a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
return a != NULL_TREE;
}
/* Return nonzero if FUNC is an interrupt function as specified
by the "interrupt" attribute. */
--- 291,316 ----
if (TREE_CODE (func) != FUNCTION_DECL)
abort ();
!
a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
return a != NULL_TREE;
}
+ /* Return non-zero if FUNC is a noreturn function. */
+
+ static int
+ nonret_function_p (func)
+ tree func;
+ {
+ tree a;
+
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ return 0;
+
+ a = lookup_attribute ("nonret", DECL_MACHINE_ATTRIBUTES (func));
+ return a != NULL_TREE;
+ }
+
/* Return nonzero if FUNC is an interrupt function as specified
by the "interrupt" attribute. */
*************** function_prologue (file, size)
*** 531,536 ****
--- 547,553 ----
int size;
{
int reg;
+ int nonret_func_p;
int interrupt_func_p;
int signal_func_p;
int leaf_func_p;
*************** function_prologue (file, size)
*** 544,549 ****
--- 561,567 ----
return;
}
+ nonret_func_p = nonret_function_p (current_function_decl);
interrupt_func_p = interrupt_function_p (current_function_decl);
signal_func_p = signal_function_p (current_function_decl);
leaf_func_p = leaf_function_p ();
*************** function_prologue (file, size)
*** 555,561 ****
last_insn_address = 0;
jump_tables_size = 0;
prologue_size = 0;
! fprintf (file, "/* prologue: frame size=%d */\n", size);
if (interrupt_func_p)
{
--- 573,580 ----
last_insn_address = 0;
jump_tables_size = 0;
prologue_size = 0;
! fprintf (file, "/* prologue: %sframe size=%d */\n",
! nonret_func_p ? "non-return, " : "", size);
if (interrupt_func_p)
{
*************** function_prologue (file, size)
*** 623,641 ****
&& ! (frame_pointer_needed
&& (reg == REG_Y || reg == (REG_Y+1)))))
{
! fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
! ++prologue_size;
}
}
if (frame_pointer_needed)
{
{
fprintf (file, "\t"
- AS1 (push,r28) CR_TAB
- AS1 (push,r29) CR_TAB
AS2 (in,r28,__SP_L__) CR_TAB
AS2 (in,r29,__SP_H__) "\n");
! prologue_size += 4;
if (size)
{
fputs ("\t", file);
--- 642,668 ----
&& ! (frame_pointer_needed
&& (reg == REG_Y || reg == (REG_Y+1)))))
{
! if (!nonret_func_p)
! {
! fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
! ++prologue_size;
! }
}
}
if (frame_pointer_needed)
{
{
+ if (!nonret_func_p)
+ {
+ fprintf (file, "\t"
+ AS1 (push,r28) CR_TAB
+ AS1 (push,r29) "\n");
+ prologue_size += 2;
+ }
fprintf (file, "\t"
AS2 (in,r28,__SP_L__) CR_TAB
AS2 (in,r29,__SP_H__) "\n");
! prologue_size += 2;
if (size)
{
fputs ("\t", file);
*************** function_epilogue (file, size)
*** 681,686 ****
--- 708,718 ----
fprintf (file, "/* epilogue: naked */\n");
return;
}
+ if (nonret_function_p (current_function_decl))
+ {
+ fprintf (file, "/* epilogue: non-return */\n");
+ return;
+ }
interrupt_func_p = interrupt_function_p (current_function_decl);
signal_func_p = signal_function_p (current_function_decl);
*************** valid_machine_type_attribute(type, attri
*** 4683,4688 ****
--- 4715,4721 ----
prologue interrupts are disabled;
interrupt - make a function to be hardware interrupt. After function
prologue interrupts are enabled;
+ nonret - no register saved in prologue, no epilogue (ie., naked)
naked - don't generate function prologue/epilogue and `ret' command.
*/
int
*************** valid_machine_decl_attribute (decl, attr
*** 4694,4699 ****
--- 4727,4733 ----
{
if (is_attribute_p ("interrupt", attr)
|| is_attribute_p ("signal", attr)
+ || is_attribute_p ("nonret", attr)
|| is_attribute_p ("naked", attr))
return TREE_CODE (decl) == FUNCTION_DECL;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [avr-gcc-list] noreturn, naked & nonret function attributes,
Kang Tin LAI <=