initial changes - fixed a code generation bug

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%4069
This commit is contained in:
David Anderson 2006-09-14 05:34:02 +00:00
parent c4d0088573
commit c0f7e0b579
5 changed files with 171 additions and 19 deletions

View File

@ -619,6 +619,7 @@ typedef enum {
OP_SYSREQ_D, OP_SYSREQ_D,
OP_SYSREQ_ND, OP_SYSREQ_ND,
/* ----- */ /* ----- */
OP_HEAP_I,
OP_NUM_OPCODES OP_NUM_OPCODES
} OPCODE; } OPCODE;

View File

@ -602,6 +602,7 @@ SC_FUNC void defstorage(void);
SC_FUNC void modstk(int delta); SC_FUNC void modstk(int delta);
SC_FUNC void setstk(cell value); SC_FUNC void setstk(cell value);
SC_FUNC void modheap(int delta); SC_FUNC void modheap(int delta);
SC_FUNC void modheap_i();
SC_FUNC void setheap_pri(void); SC_FUNC void setheap_pri(void);
SC_FUNC void setheap(cell value); SC_FUNC void setheap(cell value);
SC_FUNC void cell2addr(void); SC_FUNC void cell2addr(void);
@ -610,6 +611,7 @@ SC_FUNC void addr2cell(void);
SC_FUNC void char2addr(void); SC_FUNC void char2addr(void);
SC_FUNC void charalign(void); SC_FUNC void charalign(void);
SC_FUNC void addconst(cell value); SC_FUNC void addconst(cell value);
SC_FUNC void setheap_save(cell value);
/* Code generation functions for arithmetic operators. /* Code generation functions for arithmetic operators.
* *

View File

@ -60,9 +60,104 @@ static int dbltest(void (*oper)(),value *lval1,value *lval2);
static int commutative(void (*oper)()); static int commutative(void (*oper)());
static int constant(value *lval); static int constant(value *lval);
#define HEAPUSE_STATIC 0
#define HEAPUSE_DYNAMIC 1
typedef struct heapuse_s {
int type; /* HEAPUSE_STATIC or HEAPUSE_DYNAMIC */
int size; /* size of array for static (0 for dynamic) */
struct heapuse_s *prev; /* previous array on the list */
} heapuse_t;
typedef struct heapuse_list_s {
struct heapuse_list_s *prev; /* last used list */
heapuse_t *head; /* head of the current list */
} heapuse_list_t;
static char lastsymbol[sNAMEMAX+1]; /* name of last function/variable */ static char lastsymbol[sNAMEMAX+1]; /* name of last function/variable */
static int bitwise_opercount; /* count of bitwise operators in an expression */ static int bitwise_opercount; /* count of bitwise operators in an expression */
static int decl_heap=0; //static int decl_heap=0;
static heapuse_list_t *heapusage = NULL;
/**
* Creates a new heap allocation tracker entry
*/
void pushheaplist()
{
heapuse_list_t *newlist=(heapuse_list_t *)malloc(sizeof(heapuse_list_t));
newlist->prev=heapusage;
newlist->head=NULL;
heapusage=newlist;
}
/**
* Generates code to free all heap allocations on a tracker
*/
void freeheapusage(heapuse_list_t *heap)
{
heapuse_t *cur=heap->head;
heapuse_t *tmp;
while (cur) {
if (cur->type == HEAPUSE_STATIC) {
modheap((-1)*cur->size*sizeof(cell));
} else {
modheap_i();
}
tmp=cur->prev;
free(cur);
cur=tmp;
}
heap->head=NULL;
}
/**
* Pops a heap list but does not free it.
*/
heapuse_list_t *popsaveheaplist()
{
heapuse_list_t *oldlist=heapusage;
heapusage=heapusage->prev;
return oldlist;
}
/**
* Pops a heap list and frees it.
*/
void popheaplist()
{
heapuse_list_t *oldlist;
assert(heapusage!=NULL);
freeheapusage(heapusage);
assert(heapusage->head==NULL);
oldlist=heapusage->prev;
free(heapusage);
heapusage=oldlist;
}
/*
* Returns the size passed in
*/
int markheap(int type, int size)
{
heapuse_t *use;
if (type==HEAPUSE_STATIC && size==0)
return 0;
use=heapusage->head;
if (use && (type==HEAPUSE_STATIC)
&& (use->type == type))
{
use->size += size;
} else {
use=(heapuse_t *)malloc(sizeof(heapuse_t));
use->type=type;
use->size=size;
use->prev=heapusage->head;
heapusage->head=use;
}
return size;
}
/* Function addresses of binary operators for signed operations */ /* Function addresses of binary operators for signed operations */
static void (*op1[17])(void) = { static void (*op1[17])(void) = {
@ -684,15 +779,13 @@ static cell calc(cell left,void (*oper)(),cell right,char *boolresult)
SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult) SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult)
{ {
int locheap=decl_heap;
value lval={0}; value lval={0};
pushheaplist();
if (hier14(&lval)) if (hier14(&lval))
rvalue(&lval); rvalue(&lval);
/* scrap any arrays left on the heap */ /* scrap any arrays left on the heap */
assert(decl_heap>=locheap); popheaplist();
modheap((locheap-decl_heap)*sizeof(cell)); /* remove heap space, so negative delta */
decl_heap=locheap;
if (lval.ident==iCONSTEXPR && val!=NULL) /* constant expression */ if (lval.ident==iCONSTEXPR && val!=NULL) /* constant expression */
*val=lval.constval; *val=lval.constval;
@ -1047,6 +1140,34 @@ static int hier14(value *lval1)
return FALSE; /* expression result is never an lvalue */ return FALSE; /* expression result is never an lvalue */
} }
/**
* Sums up array usage in the current heap tracer and convert it into a dynamic array.
* This is used for the ternary operator, which needs to convert its array usage into
* something dynamically managed.
* !Note:
* This might break if expressions can ever return dynamic arrays.
* Thus, we assert() if something is non-static here.
* Right now, this poses no problem because this type of expression is impossible:
* (a() ? return_array() : return_array()) ? return_array() : return_array()
*/
void dynarray_from_heaplist(heapuse_list_t *heap)
{
heapuse_t *use=heap->head;
heapuse_t *tmp;
long total=0;
while (use) {
assert(use->type==HEAPUSE_STATIC);
total+=use->size;
tmp=use->prev;
free(use);
use=tmp;
}
free(heap);
if (total)
setheap_save(total);
}
static int hier13(value *lval) static int hier13(value *lval)
{ {
int lvalue=plnge1(hier12,lval); int lvalue=plnge1(hier12,lval);
@ -1055,7 +1176,9 @@ static int hier13(value *lval)
int flab2=getlabel(); int flab2=getlabel();
value lval2={0}; value lval2={0};
int array1,array2; int array1,array2;
heapuse_list_t *heap;
pushheaplist();
if (lvalue) { if (lvalue) {
rvalue(lval); rvalue(lval);
} else if (lval->ident==iCONSTEXPR) { } else if (lval->ident==iCONSTEXPR) {
@ -1072,6 +1195,9 @@ static int hier13(value *lval)
sc_allowtags=(short)POPSTK_I(); /* restore */ sc_allowtags=(short)POPSTK_I(); /* restore */
jumplabel(flab2); jumplabel(flab2);
setlabel(flab1); setlabel(flab1);
heap=popsaveheaplist();
dynarray_from_heaplist(heap);
pushheaplist();
needtoken(':'); needtoken(':');
if (hier13(&lval2)) if (hier13(&lval2))
rvalue(&lval2); rvalue(&lval2);
@ -1090,6 +1216,11 @@ static int hier13(value *lval)
if (!matchtag(lval->tag,lval2.tag,FALSE)) if (!matchtag(lval->tag,lval2.tag,FALSE))
error(213); /* tagname mismatch ('true' and 'false' expressions) */ error(213); /* tagname mismatch ('true' and 'false' expressions) */
setlabel(flab2); setlabel(flab2);
heap=popsaveheaplist();
dynarray_from_heaplist(heap);
if (array1 && array2) {
markheap(HEAPUSE_DYNAMIC, 0);
}
if (lval->ident==iARRAY) if (lval->ident==iARRAY)
lval->ident=iREFARRAY; /* iARRAY becomes iREFARRAY */ lval->ident=iREFARRAY; /* iARRAY becomes iREFARRAY */
else if (lval->ident!=iREFARRAY) else if (lval->ident!=iREFARRAY)
@ -1871,6 +2002,7 @@ static void setdefarray(cell *string,cell size,cell array_sz,cell *dataaddr,int
*/ */
assert(array_sz>=size); assert(array_sz>=size);
modheap((int)array_sz*sizeof(cell)); modheap((int)array_sz*sizeof(cell));
markheap(HEAPUSE_STATIC, array_sz);
/* ??? should perhaps fill with zeros first */ /* ??? should perhaps fill with zeros first */
memcopy(size*sizeof(cell)); memcopy(size*sizeof(cell));
moveto1(); moveto1();
@ -1914,7 +2046,6 @@ static void callfunction(symbol *sym,value *lval_result,int matchparanthesis)
{ {
static long nest_stkusage=0L; static long nest_stkusage=0L;
static int nesting=0; static int nesting=0;
int locheap;
int close,lvalue; int close,lvalue;
int argpos; /* index in the output stream (argpos==nargs if positional parameters) */ int argpos; /* index in the output stream (argpos==nargs if positional parameters) */
int argidx=0; /* index in "arginfo" list */ int argidx=0; /* index in "arginfo" list */
@ -1946,12 +2077,12 @@ static int nesting=0;
assert(retsize>0); assert(retsize>0);
modheap(retsize*sizeof(cell));/* address is in ALT */ modheap(retsize*sizeof(cell));/* address is in ALT */
pushreg(sALT); /* pass ALT as the last (hidden) parameter */ pushreg(sALT); /* pass ALT as the last (hidden) parameter */
decl_heap+=retsize; markheap(HEAPUSE_STATIC, retsize);
/* also mark the ident of the result as "array" */ /* also mark the ident of the result as "array" */
lval_result->ident=iREFARRAY; lval_result->ident=iREFARRAY;
lval_result->sym=symret; lval_result->sym=symret;
} /* if */ } /* if */
locheap=decl_heap; pushheaplist();
nesting++; nesting++;
assert(nest_stkusage>=0); assert(nest_stkusage>=0);
@ -2054,14 +2185,14 @@ static int nesting=0;
} else { } else {
rvalue(&lval); /* get value in PRI */ rvalue(&lval); /* get value in PRI */
setheap_pri(); /* address of the value on the heap in PRI */ setheap_pri(); /* address of the value on the heap in PRI */
heapalloc++; heapalloc+=markheap(HEAPUSE_STATIC, 1);
nest_stkusage++; nest_stkusage++;
} /* if */ } /* if */
} else if (lvalue) { } else if (lvalue) {
address(lval.sym,sPRI); address(lval.sym,sPRI);
} else { } else {
setheap_pri(); /* address of the value on the heap in PRI */ setheap_pri(); /* address of the value on the heap in PRI */
heapalloc++; heapalloc+=markheap(HEAPUSE_STATIC, 1);
nest_stkusage++; nest_stkusage++;
} /* if */ } /* if */
} else if (lval.ident==iCONSTEXPR || lval.ident==iEXPRESSION } else if (lval.ident==iCONSTEXPR || lval.ident==iEXPRESSION
@ -2073,7 +2204,7 @@ static int nesting=0;
/* allocate a cell on the heap and store the /* allocate a cell on the heap and store the
* value (already in PRI) there */ * value (already in PRI) there */
setheap_pri(); /* address of the value on the heap in PRI */ setheap_pri(); /* address of the value on the heap in PRI */
heapalloc++; heapalloc+=markheap(HEAPUSE_STATIC, 1);
nest_stkusage++; nest_stkusage++;
} /* if */ } /* if */
/* ??? handle const array passed by reference */ /* ??? handle const array passed by reference */
@ -2111,7 +2242,7 @@ static int nesting=0;
address(lval.sym,sPRI); address(lval.sym,sPRI);
} else { } else {
setheap_pri(); /* address of the value on the heap in PRI */ setheap_pri(); /* address of the value on the heap in PRI */
heapalloc++; heapalloc+=markheap(HEAPUSE_STATIC, 1);
nest_stkusage++; nest_stkusage++;
} /* if */ } /* if */
} /* if */ } /* if */
@ -2258,7 +2389,7 @@ static int nesting=0;
} else if (arg[argidx].ident==iREFERENCE) { } else if (arg[argidx].ident==iREFERENCE) {
setheap(arg[argidx].defvalue.val); setheap(arg[argidx].defvalue.val);
/* address of the value on the heap in PRI */ /* address of the value on the heap in PRI */
heapalloc++; heapalloc+=markheap(HEAPUSE_STATIC, 1);
nest_stkusage++; nest_stkusage++;
} else { } else {
int dummytag=arg[argidx].tags[0]; int dummytag=arg[argidx].tags[0];
@ -2329,7 +2460,6 @@ static int nesting=0;
markusage(sym,uREAD); /* do not mark as "used" when this call itself is skipped */ markusage(sym,uREAD); /* do not mark as "used" when this call itself is skipped */
if ((sym->usage & uNATIVE)!=0 &&sym->x.lib!=NULL) if ((sym->usage & uNATIVE)!=0 &&sym->x.lib!=NULL)
sym->x.lib->value += 1; /* increment "usage count" of the library */ sym->x.lib->value += 1; /* increment "usage count" of the library */
modheap(-heapalloc*sizeof(cell));
if (symret!=NULL) if (symret!=NULL)
popreg(sPRI); /* pop hidden parameter as function result */ popreg(sPRI); /* pop hidden parameter as function result */
sideeffect=TRUE; /* assume functions carry out a side-effect */ sideeffect=TRUE; /* assume functions carry out a side-effect */
@ -2339,7 +2469,7 @@ static int nesting=0;
/* maintain max. amount of memory used */ /* maintain max. amount of memory used */
{ {
long totalsize; long totalsize;
totalsize=declared+decl_heap+1; /* local variables & return value size, totalsize=declared+heapalloc+1; /* local variables & return value size,
* +1 for PROC opcode */ * +1 for PROC opcode */
if (lval_result->ident==iREFARRAY) if (lval_result->ident==iREFARRAY)
totalsize++; /* add hidden parameter (on the stack) */ totalsize++; /* add hidden parameter (on the stack) */
@ -2361,9 +2491,7 @@ static int nesting=0;
* this function has as a result (in other words, scrap all arrays on the * this function has as a result (in other words, scrap all arrays on the
* heap that caused by expressions in the function arguments) * heap that caused by expressions in the function arguments)
*/ */
assert(decl_heap>=locheap); popheaplist();
modheap((locheap-decl_heap)*sizeof(cell)); /* remove heap space, so negative delta */
decl_heap=locheap;
nesting--; nesting--;
} }

View File

@ -844,6 +844,26 @@ SC_FUNC void modheap(int delta)
} /* if */ } /* if */
} }
SC_FUNC void modheap_i()
{
stgwrite("\theap.i\n");
code_idx+=opcodes(1);
}
SC_FUNC void setheap_save(cell value)
{
pushreg(sPRI);
pushreg(sALT);
stgwrite("\tconst.pri ");
outval(value, TRUE);
code_idx+=opcodes(1)+opargs(1);
stgwrite("\theap ");
outval(sizeof(cell), TRUE);
stgwrite("\tstor.pri\n");
popreg(sALT);
popreg(sPRI);
}
SC_FUNC void setheap_pri(void) SC_FUNC void setheap_pri(void)
{ {
stgwrite("\theap "); /* ALT = HEA++ */ stgwrite("\theap "); /* ALT = HEA++ */

View File

@ -493,6 +493,7 @@ static OPCODEC opcodelist[] = {
{ 99, "grtr", sIN_CSEG, parm0 }, { 99, "grtr", sIN_CSEG, parm0 },
{120, "halt", sIN_CSEG, parm1 }, {120, "halt", sIN_CSEG, parm1 },
{ 45, "heap", sIN_CSEG, parm1 }, { 45, "heap", sIN_CSEG, parm1 },
{160, "heap.i", sIN_CSEG, parm0 },
{ 27, "idxaddr", sIN_CSEG, parm0 }, { 27, "idxaddr", sIN_CSEG, parm0 },
{ 28, "idxaddr.b", sIN_CSEG, parm1 }, { 28, "idxaddr.b", sIN_CSEG, parm1 },
{109, "inc", sIN_CSEG, parm1 }, {109, "inc", sIN_CSEG, parm1 },