From 56ef450a24956aa6aaa3afec439af5195e4aa235 Mon Sep 17 00:00:00 2001 From: Sergei Marochkin Date: Tue, 25 Oct 2016 06:27:56 +0300 Subject: [PATCH] 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 --- source/compiler/sc1.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 61a62f8..63fb705 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -4501,7 +4501,7 @@ static void reduce_referrers(symbol *root) } #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; int i,stkpos; @@ -4517,6 +4517,8 @@ static long max_stacksize_recurse(symbol **sourcesym,symbol *sym,long basesize,i if (sym->refer[i]!=NULL) { assert(sym->refer[i]->ident==iFUNCTN); 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++) { if (sym->refer[i]==sourcesym[stkpos]) { /* recursion detection */ *recursion=1; @@ -4527,7 +4529,7 @@ static long max_stacksize_recurse(symbol **sourcesym,symbol *sym,long basesize,i sourcesym[stkpos]=sym; sourcesym[stkpos+1]=NULL; /* 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 (maxsizenext; sym!=NULL; sym=sym->next) { + int recursion_detected; /* drop out if this is not a user-implemented function */ if (sym->ident!=iFUNCTN || (sym->usage & uNATIVE)!=0) continue; /* accumulate stack size for this symbol */ symstack[0]=sym; 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); if (maxsize