initial changes - fixed a code generation bug
authorDavid Anderson <dvander@alliedmods.net>
Thu Sep 14 05:34:02 2006 +0000 (2006-09-14)
changeset 64cc302adaac00
parent 63 29b9475a8b59
child 65 eaa4964fd916
initial changes - fixed a code generation bug
sourcepawn/compiler/amx.h
sourcepawn/compiler/sc.h
sourcepawn/compiler/sc3.c
sourcepawn/compiler/sc4.c
sourcepawn/compiler/sc6.c
     1.1 --- a/sourcepawn/compiler/amx.h	Mon Aug 28 16:33:01 2006 +0000
     1.2 +++ b/sourcepawn/compiler/amx.h	Thu Sep 14 05:34:02 2006 +0000
     1.3 @@ -619,6 +619,7 @@
     1.4    OP_SYSREQ_D,
     1.5    OP_SYSREQ_ND,
     1.6    /* ----- */
     1.7 +  OP_HEAP_I,
     1.8    OP_NUM_OPCODES
     1.9  } OPCODE;
    1.10  
     2.1 --- a/sourcepawn/compiler/sc.h	Mon Aug 28 16:33:01 2006 +0000
     2.2 +++ b/sourcepawn/compiler/sc.h	Thu Sep 14 05:34:02 2006 +0000
     2.3 @@ -602,6 +602,7 @@
     2.4  SC_FUNC void modstk(int delta);
     2.5  SC_FUNC void setstk(cell value);
     2.6  SC_FUNC void modheap(int delta);
     2.7 +SC_FUNC void modheap_i();
     2.8  SC_FUNC void setheap_pri(void);
     2.9  SC_FUNC void setheap(cell value);
    2.10  SC_FUNC void cell2addr(void);
    2.11 @@ -610,6 +611,7 @@
    2.12  SC_FUNC void char2addr(void);
    2.13  SC_FUNC void charalign(void);
    2.14  SC_FUNC void addconst(cell value);
    2.15 +SC_FUNC void setheap_save(cell value);
    2.16  
    2.17  /*  Code generation functions for arithmetic operators.
    2.18   *
     3.1 --- a/sourcepawn/compiler/sc3.c	Mon Aug 28 16:33:01 2006 +0000
     3.2 +++ b/sourcepawn/compiler/sc3.c	Thu Sep 14 05:34:02 2006 +0000
     3.3 @@ -60,9 +60,104 @@
     3.4  static int commutative(void (*oper)());
     3.5  static int constant(value *lval);
     3.6  
     3.7 +#define HEAPUSE_STATIC	0
     3.8 +#define HEAPUSE_DYNAMIC	1
     3.9 +
    3.10 +typedef struct heapuse_s {
    3.11 +  int type;   /* HEAPUSE_STATIC or HEAPUSE_DYNAMIC */
    3.12 +  int size;   /* size of array for static (0 for dynamic) */
    3.13 +  struct heapuse_s *prev; /* previous array on the list */
    3.14 +} heapuse_t;
    3.15 +
    3.16 +typedef struct heapuse_list_s {
    3.17 +  struct heapuse_list_s *prev;   /* last used list */
    3.18 +  heapuse_t *head;               /* head of the current list */
    3.19 +} heapuse_list_t;
    3.20 +
    3.21  static char lastsymbol[sNAMEMAX+1]; /* name of last function/variable */
    3.22  static int bitwise_opercount;   /* count of bitwise operators in an expression */
    3.23 -static int decl_heap=0;
    3.24 +//static int decl_heap=0;
    3.25 +static heapuse_list_t *heapusage = NULL;
    3.26 +
    3.27 +/**
    3.28 + * Creates a new heap allocation tracker entry
    3.29 + */
    3.30 +void pushheaplist()
    3.31 +{
    3.32 +  heapuse_list_t *newlist=(heapuse_list_t *)malloc(sizeof(heapuse_list_t));
    3.33 +  newlist->prev=heapusage;
    3.34 +  newlist->head=NULL;
    3.35 +  heapusage=newlist;
    3.36 +}
    3.37 +
    3.38 +/**
    3.39 + * Generates code to free all heap allocations on a tracker
    3.40 + */
    3.41 +void freeheapusage(heapuse_list_t *heap)
    3.42 +{
    3.43 +  heapuse_t *cur=heap->head;
    3.44 +  heapuse_t *tmp;
    3.45 +  while (cur) {
    3.46 +	if (cur->type == HEAPUSE_STATIC) {
    3.47 +	  modheap((-1)*cur->size*sizeof(cell));
    3.48 +	} else {
    3.49 +	  modheap_i();
    3.50 +	}
    3.51 +	tmp=cur->prev;
    3.52 +	free(cur);
    3.53 +	cur=tmp;
    3.54 +  }
    3.55 +  heap->head=NULL;
    3.56 +}
    3.57 +
    3.58 +/**
    3.59 + * Pops a heap list but does not free it.
    3.60 + */
    3.61 +heapuse_list_t *popsaveheaplist()
    3.62 +{
    3.63 +  heapuse_list_t *oldlist=heapusage;
    3.64 +  heapusage=heapusage->prev;
    3.65 +  return oldlist;
    3.66 +}
    3.67 +
    3.68 +/**
    3.69 + * Pops a heap list and frees it.
    3.70 + */
    3.71 +void popheaplist()
    3.72 +{
    3.73 +  heapuse_list_t *oldlist;
    3.74 +  assert(heapusage!=NULL);
    3.75 + 
    3.76 +  freeheapusage(heapusage);
    3.77 +  assert(heapusage->head==NULL);
    3.78 +
    3.79 +  oldlist=heapusage->prev;
    3.80 +  free(heapusage);
    3.81 +  heapusage=oldlist;
    3.82 +}
    3.83 +
    3.84 +/*
    3.85 + * Returns the size passed in
    3.86 + */
    3.87 +int markheap(int type, int size)
    3.88 +{
    3.89 +  heapuse_t *use;
    3.90 +  if (type==HEAPUSE_STATIC && size==0)
    3.91 +    return 0;
    3.92 +  use=heapusage->head;
    3.93 +  if (use && (type==HEAPUSE_STATIC) 
    3.94 +      && (use->type == type))
    3.95 +  {
    3.96 +    use->size += size;
    3.97 +  } else {
    3.98 +    use=(heapuse_t *)malloc(sizeof(heapuse_t));
    3.99 +    use->type=type;
   3.100 +    use->size=size;
   3.101 +    use->prev=heapusage->head;
   3.102 +    heapusage->head=use;
   3.103 +  }
   3.104 +  return size;
   3.105 +}
   3.106  
   3.107  /* Function addresses of binary operators for signed operations */
   3.108  static void (*op1[17])(void) = {
   3.109 @@ -684,15 +779,13 @@
   3.110  
   3.111  SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult)
   3.112  {
   3.113 -  int locheap=decl_heap;
   3.114    value lval={0};
   3.115 +  pushheaplist();
   3.116  
   3.117    if (hier14(&lval))
   3.118      rvalue(&lval);
   3.119    /* scrap any arrays left on the heap */
   3.120 -  assert(decl_heap>=locheap);
   3.121 -  modheap((locheap-decl_heap)*sizeof(cell));  /* remove heap space, so negative delta */
   3.122 -  decl_heap=locheap;
   3.123 +  popheaplist();
   3.124  
   3.125    if (lval.ident==iCONSTEXPR && val!=NULL)    /* constant expression */
   3.126      *val=lval.constval;
   3.127 @@ -1047,6 +1140,34 @@
   3.128    return FALSE;         /* expression result is never an lvalue */
   3.129  }
   3.130  
   3.131 +/**
   3.132 + * Sums up array usage in the current heap tracer and convert it into a dynamic array.
   3.133 + * This is used for the ternary operator, which needs to convert its array usage into
   3.134 + * something dynamically managed.
   3.135 + * !Note:
   3.136 + * This might break if expressions can ever return dynamic arrays.
   3.137 + * Thus, we assert() if something is non-static here.
   3.138 + * Right now, this poses no problem because this type of expression is impossible:
   3.139 + *   (a() ? return_array() : return_array()) ? return_array() : return_array()
   3.140 + */
   3.141 +
   3.142 +void dynarray_from_heaplist(heapuse_list_t *heap)
   3.143 +{
   3.144 +  heapuse_t *use=heap->head;
   3.145 +  heapuse_t *tmp;
   3.146 +  long total=0;
   3.147 +  while (use) {
   3.148 +    assert(use->type==HEAPUSE_STATIC);
   3.149 +    total+=use->size;
   3.150 +    tmp=use->prev;
   3.151 +    free(use);
   3.152 +    use=tmp;
   3.153 +  }
   3.154 +  free(heap);
   3.155 +  if (total)
   3.156 +    setheap_save(total);
   3.157 +}
   3.158 +
   3.159  static int hier13(value *lval)
   3.160  {
   3.161    int lvalue=plnge1(hier12,lval);
   3.162 @@ -1055,7 +1176,9 @@
   3.163      int flab2=getlabel();
   3.164      value lval2={0};
   3.165      int array1,array2;
   3.166 -
   3.167 +    heapuse_list_t *heap;
   3.168 +    
   3.169 +    pushheaplist();
   3.170      if (lvalue) {
   3.171        rvalue(lval);
   3.172      } else if (lval->ident==iCONSTEXPR) {
   3.173 @@ -1072,6 +1195,9 @@
   3.174      sc_allowtags=(short)POPSTK_I();     /* restore */
   3.175      jumplabel(flab2);
   3.176      setlabel(flab1);
   3.177 +    heap=popsaveheaplist();
   3.178 +    dynarray_from_heaplist(heap);
   3.179 +    pushheaplist();
   3.180      needtoken(':');
   3.181      if (hier13(&lval2))
   3.182        rvalue(&lval2);
   3.183 @@ -1090,6 +1216,11 @@
   3.184      if (!matchtag(lval->tag,lval2.tag,FALSE))
   3.185        error(213);               /* tagname mismatch ('true' and 'false' expressions) */
   3.186      setlabel(flab2);
   3.187 +    heap=popsaveheaplist();
   3.188 +    dynarray_from_heaplist(heap);
   3.189 +	if (array1 && array2) {
   3.190 +      markheap(HEAPUSE_DYNAMIC, 0);
   3.191 +	}
   3.192      if (lval->ident==iARRAY)
   3.193        lval->ident=iREFARRAY;    /* iARRAY becomes iREFARRAY */
   3.194      else if (lval->ident!=iREFARRAY)
   3.195 @@ -1871,6 +2002,7 @@
   3.196       */
   3.197      assert(array_sz>=size);
   3.198      modheap((int)array_sz*sizeof(cell));
   3.199 +	markheap(HEAPUSE_STATIC, array_sz);
   3.200      /* ??? should perhaps fill with zeros first */
   3.201      memcopy(size*sizeof(cell));
   3.202      moveto1();
   3.203 @@ -1914,7 +2046,6 @@
   3.204  {
   3.205  static long nest_stkusage=0L;
   3.206  static int nesting=0;
   3.207 -  int locheap;
   3.208    int close,lvalue;
   3.209    int argpos;       /* index in the output stream (argpos==nargs if positional parameters) */
   3.210    int argidx=0;     /* index in "arginfo" list */
   3.211 @@ -1946,12 +2077,12 @@
   3.212      assert(retsize>0);
   3.213      modheap(retsize*sizeof(cell));/* address is in ALT */
   3.214      pushreg(sALT);                /* pass ALT as the last (hidden) parameter */
   3.215 -    decl_heap+=retsize;
   3.216 +    markheap(HEAPUSE_STATIC, retsize);
   3.217      /* also mark the ident of the result as "array" */
   3.218      lval_result->ident=iREFARRAY;
   3.219      lval_result->sym=symret;
   3.220    } /* if */
   3.221 -  locheap=decl_heap;
   3.222 +  pushheaplist();
   3.223  
   3.224    nesting++;
   3.225    assert(nest_stkusage>=0);
   3.226 @@ -2054,14 +2185,14 @@
   3.227                } else {
   3.228                  rvalue(&lval);    /* get value in PRI */
   3.229                  setheap_pri();    /* address of the value on the heap in PRI */
   3.230 -                heapalloc++;
   3.231 +                heapalloc+=markheap(HEAPUSE_STATIC, 1);
   3.232                  nest_stkusage++;
   3.233                } /* if */
   3.234              } else if (lvalue) {
   3.235                address(lval.sym,sPRI);
   3.236              } else {
   3.237                setheap_pri();      /* address of the value on the heap in PRI */
   3.238 -              heapalloc++;
   3.239 +              heapalloc+=markheap(HEAPUSE_STATIC, 1);
   3.240                nest_stkusage++;
   3.241              } /* if */
   3.242            } else if (lval.ident==iCONSTEXPR || lval.ident==iEXPRESSION
   3.243 @@ -2073,7 +2204,7 @@
   3.244              /* allocate a cell on the heap and store the
   3.245               * value (already in PRI) there */
   3.246              setheap_pri();        /* address of the value on the heap in PRI */
   3.247 -            heapalloc++;
   3.248 +            heapalloc+=markheap(HEAPUSE_STATIC, 1);
   3.249              nest_stkusage++;
   3.250            } /* if */
   3.251            /* ??? handle const array passed by reference */
   3.252 @@ -2111,7 +2242,7 @@
   3.253                address(lval.sym,sPRI);
   3.254              } else {
   3.255                setheap_pri();      /* address of the value on the heap in PRI */
   3.256 -              heapalloc++;
   3.257 +              heapalloc+=markheap(HEAPUSE_STATIC, 1);
   3.258                nest_stkusage++;
   3.259              } /* if */
   3.260            } /* if */
   3.261 @@ -2258,7 +2389,7 @@
   3.262        } else if (arg[argidx].ident==iREFERENCE) {
   3.263          setheap(arg[argidx].defvalue.val);
   3.264          /* address of the value on the heap in PRI */
   3.265 -        heapalloc++;
   3.266 +        heapalloc+=markheap(HEAPUSE_STATIC, 1);
   3.267          nest_stkusage++;
   3.268        } else {
   3.269          int dummytag=arg[argidx].tags[0];
   3.270 @@ -2329,7 +2460,6 @@
   3.271      markusage(sym,uREAD);       /* do not mark as "used" when this call itself is skipped */
   3.272    if ((sym->usage & uNATIVE)!=0 &&sym->x.lib!=NULL)
   3.273      sym->x.lib->value += 1;     /* increment "usage count" of the library */
   3.274 -  modheap(-heapalloc*sizeof(cell));
   3.275    if (symret!=NULL)
   3.276      popreg(sPRI);               /* pop hidden parameter as function result */
   3.277    sideeffect=TRUE;              /* assume functions carry out a side-effect */
   3.278 @@ -2339,7 +2469,7 @@
   3.279    /* maintain max. amount of memory used */
   3.280    {
   3.281      long totalsize;
   3.282 -    totalsize=declared+decl_heap+1;   /* local variables & return value size,
   3.283 +    totalsize=declared+heapalloc+1;   /* local variables & return value size,
   3.284                                         * +1 for PROC opcode */
   3.285      if (lval_result->ident==iREFARRAY)
   3.286        totalsize++;                    /* add hidden parameter (on the stack) */
   3.287 @@ -2361,9 +2491,7 @@
   3.288     * this function has as a result (in other words, scrap all arrays on the
   3.289     * heap that caused by expressions in the function arguments)
   3.290     */
   3.291 -  assert(decl_heap>=locheap);
   3.292 -  modheap((locheap-decl_heap)*sizeof(cell));  /* remove heap space, so negative delta */
   3.293 -  decl_heap=locheap;
   3.294 +  popheaplist();
   3.295    nesting--;
   3.296  }
   3.297  
     4.1 --- a/sourcepawn/compiler/sc4.c	Mon Aug 28 16:33:01 2006 +0000
     4.2 +++ b/sourcepawn/compiler/sc4.c	Thu Sep 14 05:34:02 2006 +0000
     4.3 @@ -844,6 +844,26 @@
     4.4    } /* if */
     4.5  }
     4.6  
     4.7 +SC_FUNC void modheap_i()
     4.8 +{
     4.9 +  stgwrite("\theap.i\n");
    4.10 +  code_idx+=opcodes(1);
    4.11 +}
    4.12 +
    4.13 +SC_FUNC void setheap_save(cell value)
    4.14 +{
    4.15 +  pushreg(sPRI);
    4.16 +  pushreg(sALT);
    4.17 +  stgwrite("\tconst.pri ");
    4.18 +  outval(value, TRUE);
    4.19 +  code_idx+=opcodes(1)+opargs(1);
    4.20 +  stgwrite("\theap ");
    4.21 +  outval(sizeof(cell), TRUE);
    4.22 +  stgwrite("\tstor.pri\n");
    4.23 +  popreg(sALT);
    4.24 +  popreg(sPRI);
    4.25 +}
    4.26 +
    4.27  SC_FUNC void setheap_pri(void)
    4.28  {
    4.29    stgwrite("\theap ");          /* ALT = HEA++ */
     5.1 --- a/sourcepawn/compiler/sc6.c	Mon Aug 28 16:33:01 2006 +0000
     5.2 +++ b/sourcepawn/compiler/sc6.c	Thu Sep 14 05:34:02 2006 +0000
     5.3 @@ -493,6 +493,7 @@
     5.4    { 99, "grtr",       sIN_CSEG, parm0 },
     5.5    {120, "halt",       sIN_CSEG, parm1 },
     5.6    { 45, "heap",       sIN_CSEG, parm1 },
     5.7 +  {160, "heap.i",     sIN_CSEG, parm0 },
     5.8    { 27, "idxaddr",    sIN_CSEG, parm0 },
     5.9    { 28, "idxaddr.b",  sIN_CSEG, parm1 },
    5.10    {109, "inc",        sIN_CSEG, parm1 },