initial changes - fixed a code generation bug
--HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%4069
This commit is contained in:
parent
c4d0088573
commit
c0f7e0b579
@ -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;
|
||||||
|
|
||||||
|
@ -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.
|
||||||
*
|
*
|
||||||
|
@ -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--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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++ */
|
||||||
|
@ -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 },
|
||||||
|
Loading…
Reference in New Issue
Block a user