From ea6e82d79a051ff25a42e79b271c700b4816077b Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 15 Oct 2006 23:31:09 +0000 Subject: [PATCH] committed new stack modification method --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40122 --- sourcepawn/compiler/sc1.c | 33 +++++++----- sourcepawn/compiler/sctracker.c | 90 +++++++++++++++++++++++++++++++-- sourcepawn/compiler/sctracker.h | 12 +++++ 3 files changed, 119 insertions(+), 16 deletions(-) diff --git a/sourcepawn/compiler/sc1.c b/sourcepawn/compiler/sc1.c index cc656799..145b5e21 100644 --- a/sourcepawn/compiler/sc1.c +++ b/sourcepawn/compiler/sc1.c @@ -1972,6 +1972,7 @@ static int declloc(int fstatic) } /* if */ markexpr(sLDECL,name,-declared*sizeof(cell)); /* mark for better optimization */ modstk(-(int)size*sizeof(cell)); + markstack(MEMUSE_STATIC, size); assert(curfunc!=NULL); assert((curfunc->usage & uNATIVE)==0); if (curfunc->x.stacksizeusage & uRETVALUE); /* set "return type" variable */ curfunc=sym; define_args(); /* add the symbolic info for the function arguments */ @@ -3361,7 +3363,7 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc * has only a single statement in its body (no compound block) and that * statement declares a new variable */ - modstk((int)declared*sizeof(cell)); /* remove all local variables */ + popstacklist(); declared=0; } /* if */ if ((lastst!=tRETURN) && (lastst!=tGOTO)){ @@ -4770,6 +4772,7 @@ static void compound(int stmt_sameline,int starttok) int block_start=fline; /* save line where the compound block started */ int endtok; + pushstacklist(); /* if there is more text on this line, we should adjust the statement indent */ if (stmt_sameline) { int i; @@ -4808,8 +4811,9 @@ static void compound(int stmt_sameline,int starttok) } /* while */ if (lastst!=tRETURN) destructsymbols(&loctab,nestlevel); - if (lastst!=tRETURN && lastst!=tGOTO) - modstk((int)(declared-save_decl)*sizeof(cell)); /* delete local variable space */ + if (lastst!=tRETURN && lastst!=tGOTO) { + popstacklist(); + } testsymbols(&loctab,nestlevel,FALSE,TRUE); /* look for unused block locals */ declared=save_decl; delete_symbols(&loctab,nestlevel,FALSE,TRUE); /* erase local symbols, but @@ -5069,7 +5073,8 @@ static int dofor(void) save_decl=declared; save_nestlevel=nestlevel; save_endlessloop=endlessloop; - + pushstacklist(); + addwhile(wq); skiplab=getlabel(); endtok= matchtoken('(') ? ')' : tDO; @@ -5094,8 +5099,11 @@ static int dofor(void) */ ptr=readwhile(); assert(ptr!=NULL); - ptr[wqBRK]=(int)declared; - ptr[wqCONT]=(int)declared; + /*ptr[wqBRK]=(int)declared; + *ptr[wqCONT]=(int)declared; + */ + ptr[wqBRK] = stackusage->list_id; + ptr[wqCONT] = stackusage->list_id; jumplabel(skiplab); /* skip expression 3 1st time */ setlabel(wq[wqLOOP]); /* "continue" goes to this label: expr3 */ setline(TRUE); @@ -5135,7 +5143,7 @@ static int dofor(void) * variable in "expr1". */ destructsymbols(&loctab,nestlevel); - modstk((int)(declared-save_decl)*sizeof(cell)); + popstacklist(); testsymbols(&loctab,nestlevel,FALSE,TRUE); /* look for unused block locals */ declared=save_decl; delete_symbols(&loctab,nestlevel,FALSE,TRUE); @@ -5152,7 +5160,7 @@ static int dofor(void) * 2. only one instruction may appear below each case, use a compound * instruction to execute multiple instructions * 3. the "case" keyword accepts a comma separated list of values to - * match, it also accepts a range using the syntax "1 .. 4" + * match * * SWITCH param * PRI = expression result @@ -5349,6 +5357,8 @@ static void dolabel(void) /* since one can jump around variable declarations or out of compound * blocks, the stack must be manually adjusted */ + //:TODO: This is actually generated, egads! + //We have to support this and LCTRL/SCTRL setstk(-declared*sizeof(cell)); sym->usage|=uDEFINE; /* label is now defined */ } @@ -5496,8 +5506,7 @@ static void doreturn(void) rettype|=uRETNONE; /* function does not return anything */ } /* if */ destructsymbols(&loctab,0); /* call destructor for *all* locals */ - modstk((int)declared*sizeof(cell)); /* end of function, remove *all* - * local variables */ + genstackfree(-1); /* free everything on the stack */ ffret(strcmp(curfunc->name,uENTRYFUNC)!=0); } @@ -5511,7 +5520,7 @@ static void dobreak(void) if (ptr==NULL) return; destructsymbols(&loctab,nestlevel); - modstk(((int)declared-ptr[wqBRK])*sizeof(cell)); + genstackfree(ptr[wqBRK]); jumplabel(ptr[wqEXIT]); } @@ -5524,7 +5533,7 @@ static void docont(void) if (ptr==NULL) return; destructsymbols(&loctab,nestlevel); - modstk(((int)declared-ptr[wqCONT])*sizeof(cell)); + genstackfree(ptr[wqCONT]); jumplabel(ptr[wqLOOP]); } diff --git a/sourcepawn/compiler/sctracker.c b/sourcepawn/compiler/sctracker.c index e2df4d92..a5aa3127 100644 --- a/sourcepawn/compiler/sctracker.c +++ b/sourcepawn/compiler/sctracker.c @@ -12,8 +12,14 @@ memuse_list_t *stackusage = NULL; void _push_memlist(memuse_list_t **head) { memuse_list_t *newlist = (memuse_list_t *)malloc(sizeof(memuse_list_t)); - (*head)->prev = *head; - (*head)->head = NULL; + if (*head != NULL) + { + newlist->list_id = (*head)->list_id + 1; + } else { + newlist->list_id = 0; + } + newlist->prev = *head; + newlist->head = NULL; *head = newlist; } @@ -52,6 +58,26 @@ int _mark_memlist(memuse_list_t *head, int type, int size) return size; } +void _reset_memlist(memuse_list_t **head) +{ + memuse_list_t *curlist = *head; + memuse_list_t *tmplist; + while (curlist) { + memuse_t *curuse = curlist->head; + memuse_t *tmpuse; + while (curuse) { + tmpuse = curuse->prev; + free(curuse); + curuse = tmpuse; + } + tmplist = curlist->prev; + free(curlist); + curlist = tmplist; + } + *head = NULL; +} + + /** * Wrapper for pushing the heap list */ @@ -99,8 +125,10 @@ void _heap_freeusage(memuse_list_t *heap) { memuse_t *cur=heap->head; memuse_t *tmp; - while (cur) { - if (cur->type == MEMUSE_STATIC) { + while (cur) + { + if (cur->type == MEMUSE_STATIC) + { modheap((-1)*cur->size*sizeof(cell)); } else { modheap_i(); @@ -112,6 +140,34 @@ void _heap_freeusage(memuse_list_t *heap) heap->head=NULL; } +void _stack_genusage(memuse_list_t *stack, int dofree) +{ + memuse_t *cur = stack->head; + memuse_t *tmp; + while (cur) + { + if (cur->type == MEMUSE_DYNAMIC) + { + /* no idea yet */ + assert(0); + } else { + modstk(cur->size * sizeof(cell)); + } + if (dofree) + { + tmp = cur->prev; + free(cur); + cur = tmp; + } else { + cur = cur->prev; + } + } + if (dofree) + { + stack->head = NULL; + } +} + /** * Pops a heap list and frees it. */ @@ -128,4 +184,30 @@ void popheaplist() heapusage=oldlist; } +void genstackfree(int stop_id) +{ + memuse_list_t *curlist = stackusage; + while (curlist && curlist->list_id > stop_id) + { + _stack_genusage(curlist, 0); + curlist = curlist->prev; + } +} +void popstacklist() +{ + memuse_list_t *oldlist; + assert(stackusage != NULL); + + _stack_genusage(stackusage, 1); + assert(stackusage->head==NULL); + + oldlist = stackusage->prev; + free(stackusage); + stackusage = oldlist; +} + +void resetstacklist() +{ + _reset_memlist(&stackusage); +} diff --git a/sourcepawn/compiler/sctracker.h b/sourcepawn/compiler/sctracker.h index 4f79d11d..25be54ab 100644 --- a/sourcepawn/compiler/sctracker.h +++ b/sourcepawn/compiler/sctracker.h @@ -12,6 +12,7 @@ typedef struct memuse_s { typedef struct memuse_list_s { struct memuse_list_s *prev; /* last used list */ + int list_id; memuse_t *head; /* head of the current list */ } memuse_list_t; @@ -29,6 +30,17 @@ int markheap(int type, int size); void pushstacklist(); void popstacklist(); int markstack(int type, int size); +/** + * Generates code to free stack usage, but does not pop the list. + * This is used for code like dobreak()/docont()/doreturn(). + * stop_id is the list at which to stop generating. + */ +void genstackfree(int stop_id); + +/** + * Resets the stack list by freeing everything + */ +void resetstacklist(); extern memuse_list_t *heapusage; extern memuse_list_t *stackusage;