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_ND,
|
||||
/* ----- */
|
||||
OP_HEAP_I,
|
||||
OP_NUM_OPCODES
|
||||
} OPCODE;
|
||||
|
||||
|
@ -602,6 +602,7 @@ SC_FUNC void defstorage(void);
|
||||
SC_FUNC void modstk(int delta);
|
||||
SC_FUNC void setstk(cell value);
|
||||
SC_FUNC void modheap(int delta);
|
||||
SC_FUNC void modheap_i();
|
||||
SC_FUNC void setheap_pri(void);
|
||||
SC_FUNC void setheap(cell value);
|
||||
SC_FUNC void cell2addr(void);
|
||||
@ -610,6 +611,7 @@ SC_FUNC void addr2cell(void);
|
||||
SC_FUNC void char2addr(void);
|
||||
SC_FUNC void charalign(void);
|
||||
SC_FUNC void addconst(cell value);
|
||||
SC_FUNC void setheap_save(cell value);
|
||||
|
||||
/* 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 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 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 */
|
||||
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)
|
||||
{
|
||||
int locheap=decl_heap;
|
||||
value lval={0};
|
||||
pushheaplist();
|
||||
|
||||
if (hier14(&lval))
|
||||
rvalue(&lval);
|
||||
/* scrap any arrays left on the heap */
|
||||
assert(decl_heap>=locheap);
|
||||
modheap((locheap-decl_heap)*sizeof(cell)); /* remove heap space, so negative delta */
|
||||
decl_heap=locheap;
|
||||
popheaplist();
|
||||
|
||||
if (lval.ident==iCONSTEXPR && val!=NULL) /* constant expression */
|
||||
*val=lval.constval;
|
||||
@ -1047,6 +1140,34 @@ static int hier14(value *lval1)
|
||||
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)
|
||||
{
|
||||
int lvalue=plnge1(hier12,lval);
|
||||
@ -1055,7 +1176,9 @@ static int hier13(value *lval)
|
||||
int flab2=getlabel();
|
||||
value lval2={0};
|
||||
int array1,array2;
|
||||
|
||||
heapuse_list_t *heap;
|
||||
|
||||
pushheaplist();
|
||||
if (lvalue) {
|
||||
rvalue(lval);
|
||||
} else if (lval->ident==iCONSTEXPR) {
|
||||
@ -1072,6 +1195,9 @@ static int hier13(value *lval)
|
||||
sc_allowtags=(short)POPSTK_I(); /* restore */
|
||||
jumplabel(flab2);
|
||||
setlabel(flab1);
|
||||
heap=popsaveheaplist();
|
||||
dynarray_from_heaplist(heap);
|
||||
pushheaplist();
|
||||
needtoken(':');
|
||||
if (hier13(&lval2))
|
||||
rvalue(&lval2);
|
||||
@ -1090,6 +1216,11 @@ static int hier13(value *lval)
|
||||
if (!matchtag(lval->tag,lval2.tag,FALSE))
|
||||
error(213); /* tagname mismatch ('true' and 'false' expressions) */
|
||||
setlabel(flab2);
|
||||
heap=popsaveheaplist();
|
||||
dynarray_from_heaplist(heap);
|
||||
if (array1 && array2) {
|
||||
markheap(HEAPUSE_DYNAMIC, 0);
|
||||
}
|
||||
if (lval->ident==iARRAY)
|
||||
lval->ident=iREFARRAY; /* iARRAY becomes 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);
|
||||
modheap((int)array_sz*sizeof(cell));
|
||||
markheap(HEAPUSE_STATIC, array_sz);
|
||||
/* ??? should perhaps fill with zeros first */
|
||||
memcopy(size*sizeof(cell));
|
||||
moveto1();
|
||||
@ -1914,7 +2046,6 @@ static void callfunction(symbol *sym,value *lval_result,int matchparanthesis)
|
||||
{
|
||||
static long nest_stkusage=0L;
|
||||
static int nesting=0;
|
||||
int locheap;
|
||||
int close,lvalue;
|
||||
int argpos; /* index in the output stream (argpos==nargs if positional parameters) */
|
||||
int argidx=0; /* index in "arginfo" list */
|
||||
@ -1946,12 +2077,12 @@ static int nesting=0;
|
||||
assert(retsize>0);
|
||||
modheap(retsize*sizeof(cell));/* address is in ALT */
|
||||
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" */
|
||||
lval_result->ident=iREFARRAY;
|
||||
lval_result->sym=symret;
|
||||
} /* if */
|
||||
locheap=decl_heap;
|
||||
pushheaplist();
|
||||
|
||||
nesting++;
|
||||
assert(nest_stkusage>=0);
|
||||
@ -2054,14 +2185,14 @@ static int nesting=0;
|
||||
} else {
|
||||
rvalue(&lval); /* get value in PRI */
|
||||
setheap_pri(); /* address of the value on the heap in PRI */
|
||||
heapalloc++;
|
||||
heapalloc+=markheap(HEAPUSE_STATIC, 1);
|
||||
nest_stkusage++;
|
||||
} /* if */
|
||||
} else if (lvalue) {
|
||||
address(lval.sym,sPRI);
|
||||
} else {
|
||||
setheap_pri(); /* address of the value on the heap in PRI */
|
||||
heapalloc++;
|
||||
heapalloc+=markheap(HEAPUSE_STATIC, 1);
|
||||
nest_stkusage++;
|
||||
} /* if */
|
||||
} 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
|
||||
* value (already in PRI) there */
|
||||
setheap_pri(); /* address of the value on the heap in PRI */
|
||||
heapalloc++;
|
||||
heapalloc+=markheap(HEAPUSE_STATIC, 1);
|
||||
nest_stkusage++;
|
||||
} /* if */
|
||||
/* ??? handle const array passed by reference */
|
||||
@ -2111,7 +2242,7 @@ static int nesting=0;
|
||||
address(lval.sym,sPRI);
|
||||
} else {
|
||||
setheap_pri(); /* address of the value on the heap in PRI */
|
||||
heapalloc++;
|
||||
heapalloc+=markheap(HEAPUSE_STATIC, 1);
|
||||
nest_stkusage++;
|
||||
} /* if */
|
||||
} /* if */
|
||||
@ -2258,7 +2389,7 @@ static int nesting=0;
|
||||
} else if (arg[argidx].ident==iREFERENCE) {
|
||||
setheap(arg[argidx].defvalue.val);
|
||||
/* address of the value on the heap in PRI */
|
||||
heapalloc++;
|
||||
heapalloc+=markheap(HEAPUSE_STATIC, 1);
|
||||
nest_stkusage++;
|
||||
} else {
|
||||
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 */
|
||||
if ((sym->usage & uNATIVE)!=0 &&sym->x.lib!=NULL)
|
||||
sym->x.lib->value += 1; /* increment "usage count" of the library */
|
||||
modheap(-heapalloc*sizeof(cell));
|
||||
if (symret!=NULL)
|
||||
popreg(sPRI); /* pop hidden parameter as function result */
|
||||
sideeffect=TRUE; /* assume functions carry out a side-effect */
|
||||
@ -2339,7 +2469,7 @@ static int nesting=0;
|
||||
/* maintain max. amount of memory used */
|
||||
{
|
||||
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 */
|
||||
if (lval_result->ident==iREFARRAY)
|
||||
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
|
||||
* heap that caused by expressions in the function arguments)
|
||||
*/
|
||||
assert(decl_heap>=locheap);
|
||||
modheap((locheap-decl_heap)*sizeof(cell)); /* remove heap space, so negative delta */
|
||||
decl_heap=locheap;
|
||||
popheaplist();
|
||||
nesting--;
|
||||
}
|
||||
|
||||
|
@ -844,6 +844,26 @@ SC_FUNC void modheap(int delta)
|
||||
} /* 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)
|
||||
{
|
||||
stgwrite("\theap "); /* ALT = HEA++ */
|
||||
|
@ -493,6 +493,7 @@ static OPCODEC opcodelist[] = {
|
||||
{ 99, "grtr", sIN_CSEG, parm0 },
|
||||
{120, "halt", sIN_CSEG, parm1 },
|
||||
{ 45, "heap", sIN_CSEG, parm1 },
|
||||
{160, "heap.i", sIN_CSEG, parm0 },
|
||||
{ 27, "idxaddr", sIN_CSEG, parm0 },
|
||||
{ 28, "idxaddr.b", sIN_CSEG, parm1 },
|
||||
{109, "inc", sIN_CSEG, parm1 },
|
||||
|
Loading…
Reference in New Issue
Block a user