Add detailed recursion report with call chains
Applied path from https://github.com/Zeex/pawn/tree/recursion branch. Example: f1() { f2(); } f2() { f3(); } f3() { f4(); } f4() { f1(); } will output: recursion detected: function f1 indirectly calls itself: f1 <- f4 <- f3 <- f2 <- f1 recursion detected: function f2 indirectly calls itself: f2 <- f1 <- f4 <- f3 <- f2 recursion detected: function f3 indirectly calls itself: f3 <- f2 <- f1 <- f4 <- f3 recursion detected: function f4 indirectly calls itself: f4 <- f3 <- f2 <- f1 <- f4
This commit is contained in:
parent
a0f4a4dce8
commit
56ef450a24
@ -4501,7 +4501,7 @@ static void reduce_referrers(symbol *root)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !defined SC_LIGHT
|
#if !defined SC_LIGHT
|
||||||
static long max_stacksize_recurse(symbol **sourcesym,symbol *sym,long basesize,int *pubfuncparams,int *recursion)
|
static long max_stacksize_recurse(symbol **sourcesym,symbol *sym,symbol **rsourcesym,long basesize,int *pubfuncparams,int *recursion)
|
||||||
{
|
{
|
||||||
long size,maxsize;
|
long size,maxsize;
|
||||||
int i,stkpos;
|
int i,stkpos;
|
||||||
@ -4517,6 +4517,8 @@ static long max_stacksize_recurse(symbol **sourcesym,symbol *sym,long basesize,i
|
|||||||
if (sym->refer[i]!=NULL) {
|
if (sym->refer[i]!=NULL) {
|
||||||
assert(sym->refer[i]->ident==iFUNCTN);
|
assert(sym->refer[i]->ident==iFUNCTN);
|
||||||
assert((sym->refer[i]->usage & uNATIVE)==0); /* a native function cannot refer to a user-function */
|
assert((sym->refer[i]->usage & uNATIVE)==0); /* a native function cannot refer to a user-function */
|
||||||
|
*(rsourcesym)=sym;
|
||||||
|
*(rsourcesym+1)=NULL;
|
||||||
for (stkpos=0; sourcesym[stkpos]!=NULL; stkpos++) {
|
for (stkpos=0; sourcesym[stkpos]!=NULL; stkpos++) {
|
||||||
if (sym->refer[i]==sourcesym[stkpos]) { /* recursion detection */
|
if (sym->refer[i]==sourcesym[stkpos]) { /* recursion detection */
|
||||||
*recursion=1;
|
*recursion=1;
|
||||||
@ -4527,7 +4529,7 @@ static long max_stacksize_recurse(symbol **sourcesym,symbol *sym,long basesize,i
|
|||||||
sourcesym[stkpos]=sym;
|
sourcesym[stkpos]=sym;
|
||||||
sourcesym[stkpos+1]=NULL;
|
sourcesym[stkpos+1]=NULL;
|
||||||
/* check size of callee */
|
/* check size of callee */
|
||||||
size=max_stacksize_recurse(sourcesym,sym->refer[i],sym->x.stacksize,pubfuncparams,recursion);
|
size=max_stacksize_recurse(sourcesym,sym->refer[i],rsourcesym+1,sym->x.stacksize,pubfuncparams,recursion);
|
||||||
if (maxsize<size)
|
if (maxsize<size)
|
||||||
maxsize=size;
|
maxsize=size;
|
||||||
/* remove this symbol from the stack */
|
/* remove this symbol from the stack */
|
||||||
@ -4570,7 +4572,7 @@ static long max_stacksize(symbol *root,int *recursion)
|
|||||||
long size,maxsize;
|
long size,maxsize;
|
||||||
int maxparams,numfunctions;
|
int maxparams,numfunctions;
|
||||||
symbol *sym;
|
symbol *sym;
|
||||||
symbol **symstack;
|
symbol **symstack,**rsymstack;
|
||||||
|
|
||||||
assert(root!=NULL);
|
assert(root!=NULL);
|
||||||
assert(recursion!=NULL);
|
assert(recursion!=NULL);
|
||||||
@ -4585,27 +4587,46 @@ static long max_stacksize(symbol *root,int *recursion)
|
|||||||
} /* if */
|
} /* if */
|
||||||
/* allocate function symbol stack */
|
/* allocate function symbol stack */
|
||||||
symstack=(symbol **)malloc((numfunctions+1)*sizeof(symbol*));
|
symstack=(symbol **)malloc((numfunctions+1)*sizeof(symbol*));
|
||||||
if (symstack==NULL)
|
rsymstack=(symbol **)malloc((numfunctions+1)*sizeof(symbol*));
|
||||||
|
if (symstack==NULL || rsymstack==NULL)
|
||||||
error(103); /* insufficient memory (fatal error) */
|
error(103); /* insufficient memory (fatal error) */
|
||||||
memset(symstack,0,(numfunctions+1)*sizeof(symbol*));
|
memset(symstack,0,(numfunctions+1)*sizeof(symbol*));
|
||||||
|
memset(rsymstack,0,(numfunctions+1)*sizeof(symbol*));
|
||||||
|
|
||||||
maxsize=0;
|
maxsize=0;
|
||||||
maxparams=0;
|
maxparams=0;
|
||||||
*recursion=0; /* assume no recursion */
|
*recursion=0; /* assume no recursion */
|
||||||
for (sym=root->next; sym!=NULL; sym=sym->next) {
|
for (sym=root->next; sym!=NULL; sym=sym->next) {
|
||||||
|
int recursion_detected;
|
||||||
/* drop out if this is not a user-implemented function */
|
/* drop out if this is not a user-implemented function */
|
||||||
if (sym->ident!=iFUNCTN || (sym->usage & uNATIVE)!=0)
|
if (sym->ident!=iFUNCTN || (sym->usage & uNATIVE)!=0)
|
||||||
continue;
|
continue;
|
||||||
/* accumulate stack size for this symbol */
|
/* accumulate stack size for this symbol */
|
||||||
symstack[0]=sym;
|
symstack[0]=sym;
|
||||||
assert(symstack[1]==NULL);
|
assert(symstack[1]==NULL);
|
||||||
size=max_stacksize_recurse(symstack,sym,0L,&maxparams,recursion);
|
recursion_detected=0;
|
||||||
|
size=max_stacksize_recurse(symstack,sym,rsymstack,0L,&maxparams,&recursion_detected);
|
||||||
|
if (recursion_detected) {
|
||||||
|
if (rsymstack[1]==NULL) {
|
||||||
|
pc_printf("recursion detected: function %s directly calls itself\n", sym->name);
|
||||||
|
} else {
|
||||||
|
int i;
|
||||||
|
pc_printf("recursion detected: function %s indirectly calls itself:\n", sym->name);
|
||||||
|
pc_printf("%s ", sym->name);
|
||||||
|
for (i=1; rsymstack[i]!=NULL; i++) {
|
||||||
|
pc_printf("<- %s ", rsymstack[i]->name);
|
||||||
|
}
|
||||||
|
pc_printf("<- %s\n", sym->name);
|
||||||
|
}
|
||||||
|
*recursion=recursion_detected;
|
||||||
|
}
|
||||||
assert(size>=0);
|
assert(size>=0);
|
||||||
if (maxsize<size)
|
if (maxsize<size)
|
||||||
maxsize=size;
|
maxsize=size;
|
||||||
} /* for */
|
} /* for */
|
||||||
|
|
||||||
free((void*)symstack);
|
free((void*)symstack);
|
||||||
|
free((void*)rsymstack);
|
||||||
maxsize++; /* +1 because a zero cell is always pushed on top
|
maxsize++; /* +1 because a zero cell is always pushed on top
|
||||||
* of the stack to catch stack overwrites */
|
* of the stack to catch stack overwrites */
|
||||||
return maxsize+(maxparams+1);/* +1 because # of parameters is always pushed on entry */
|
return maxsize+(maxparams+1);/* +1 because # of parameters is always pushed on entry */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user