committed new stack modification method
--HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40122
This commit is contained in:
		
							parent
							
								
									2c65e42379
								
							
						
					
					
						commit
						ea6e82d79a
					
				@ -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.stacksize<declared+1)
 | 
			
		||||
@ -3334,6 +3335,7 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc
 | 
			
		||||
    sc_alignnext=FALSE;
 | 
			
		||||
  } /* if */
 | 
			
		||||
  declared=0;           /* number of local cells */
 | 
			
		||||
  resetstacklist();
 | 
			
		||||
  rettype=(sym->usage & 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,6 +5073,7 @@ static int dofor(void)
 | 
			
		||||
  save_decl=declared;
 | 
			
		||||
  save_nestlevel=nestlevel;
 | 
			
		||||
  save_endlessloop=endlessloop;
 | 
			
		||||
  pushstacklist();
 | 
			
		||||
  
 | 
			
		||||
  addwhile(wq);
 | 
			
		||||
  skiplab=getlabel();
 | 
			
		||||
@ -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]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user