Introduce #pragma naked

When applied to a function #pragma naked merely disables the "should return
a value" warning for the function. It's intended to be used with functions
that return a value via #emit instead of the normal return statement.

This pragma works only on function definitions, not declarations. It's also
pretty stupid - the function may be defined way after this directive and it
won't stop on things coming in between.

For example, here all declarations between #pragma naked and f() are
effectively ignored:

#pragma naked

new x;       // ignored
forward g(); // ignored
native n();  // ignored

f() {
    // f() becomes naked
}

Note that #pragma naked does not affect generated code in any way, unlike
e.g. __declspec(naked) or __attribute__((naked)) in C/C++ where the compiler
omits the code for the prolog and epilog.
This commit is contained in:
Zeex 2014-01-05 01:16:47 +07:00
parent 6943995219
commit 53221dd2cc
5 changed files with 13 additions and 3 deletions

View File

@ -219,6 +219,7 @@ typedef struct s_symbol {
#define uRETNONE 0x10
#define flgDEPRICATED 0x01 /* symbol is deprecated (avoid use) */
#define flagNAKED 0x10 /* function is naked */
#define uTAGOF 0x40 /* set in the "hasdefault" field of the arginfo struct */
#define uSIZEOF 0x80 /* set in the "hasdefault" field of the arginfo struct */
@ -808,6 +809,7 @@ SC_VDECL char *pc_deprecate; /* if non-NULL, mark next declaration as deprecate
SC_VDECL int sc_curstates; /* ID of the current state list */
SC_VDECL int pc_optimize; /* (peephole) optimization level */
SC_VDECL int pc_memflags; /* special flags for the stack/heap usage */
SC_VDECL int pc_naked; /* if true mark following function as naked */
SC_VDECL constvalue sc_automaton_tab; /* automaton table */
SC_VDECL constvalue sc_state_tab; /* state table */

View File

@ -843,6 +843,7 @@ static void resetglobals(void)
pc_deprecate=NULL;
sc_curstates=0;
pc_memflags=0;
pc_naked=FALSE;
}
static void initglobals(void)
@ -3513,6 +3514,10 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc
char *ptr= (sym->documentation!=NULL) ? sym->documentation : "";
error(234,symbolname,ptr); /* deprecated (probably a public function) */
} /* if */
if (pc_naked) {
sym->flags|=flagNAKED;
pc_naked=FALSE;
} /* if */
begcseg();
sym->usage|=uDEFINE; /* set the definition flag */
if (stock)
@ -3572,7 +3577,7 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc
if ((lastst!=tRETURN) && (lastst!=tGOTO)){
ldconst(0,sPRI);
ffret(strcmp(sym->name,uENTRYFUNC)!=0);
if ((sym->usage & uRETVALUE)!=0) {
if ((sym->usage & uRETVALUE)!=0 && (sym->flags & flagNAKED)==0) {
char symname[2*sNAMEMAX+16]; /* allow space for user defined operators */
funcdisplayname(symname,sym->name);
error(209,symname); /* function should return a value */
@ -5748,7 +5753,7 @@ static void doreturn(void)
} else {
/* this return statement contains no expression */
ldconst(0,sPRI);
if ((rettype & uRETVALUE)!=0) {
if ((rettype & uRETVALUE)!=0 && (sym->flags & flagNAKED)==0) {
char symname[2*sNAMEMAX+16]; /* allow space for user defined operators */
assert(curfunc!=NULL);
funcdisplayname(symname,curfunc->name);

View File

@ -1168,6 +1168,8 @@ static int command(void)
if (comma)
lptr++;
} while (comma);
} else if (strcmp(str,"naked")==0) {
pc_naked=TRUE;
} else {
error(207); /* unknown #pragma */
} /* if */

View File

@ -433,7 +433,7 @@ static void checkfunction(value *lval)
/* function is defined, can now check the return value (but make an
* exception for directly recursive functions)
*/
if (sym!=curfunc && (sym->usage & uRETVALUE)==0) {
if (sym!=curfunc && (sym->usage & uRETVALUE)==0 && (sym->flags & flagNAKED)==0) {
char symname[2*sNAMEMAX+16]; /* allow space for user defined operators */
funcdisplayname(symname,sym->name);
error(209,symname); /* function should return a value */

View File

@ -90,6 +90,7 @@ SC_VDEFINE char *pc_deprecate=NULL;/* if non-null, mark next declaration as depr
SC_VDEFINE int sc_curstates=0; /* ID of the current state list */
SC_VDEFINE int pc_optimize=sOPTIMIZE_NOMACRO; /* (peephole) optimization level */
SC_VDEFINE int pc_memflags=0; /* special flags for the stack/heap usage */
SC_VDEFINE int pc_naked=FALSE; /* if true mark following function as naked */
SC_VDEFINE constvalue sc_automaton_tab = { NULL, "", 0, 0}; /* automaton table */
SC_VDEFINE constvalue sc_state_tab = { NULL, "", 0, 0}; /* state table */