Compiler: Fix runtime error in variadic functions that return strings.
Imported from SM-AM: 1d1244c2f0
.
"This fixes a bug where returning a string from a variadic function caused
an invalid memory access error during runtime. It seems like they forgot
to update existing string return code for variadic functions."
This commit is contained in:
parent
1866afd80b
commit
17114347d1
|
@ -575,6 +575,7 @@ SC_FUNC void startfunc(char *fname);
|
||||||
SC_FUNC void endfunc(void);
|
SC_FUNC void endfunc(void);
|
||||||
SC_FUNC void alignframe(int numbytes);
|
SC_FUNC void alignframe(int numbytes);
|
||||||
SC_FUNC void rvalue(value *lval);
|
SC_FUNC void rvalue(value *lval);
|
||||||
|
SC_FUNC void dereference(void);
|
||||||
SC_FUNC void address(symbol *ptr,regid reg);
|
SC_FUNC void address(symbol *ptr,regid reg);
|
||||||
SC_FUNC void store(value *lval);
|
SC_FUNC void store(value *lval);
|
||||||
SC_FUNC void storereg(cell address,regid reg);
|
SC_FUNC void storereg(cell address,regid reg);
|
||||||
|
@ -595,6 +596,7 @@ SC_FUNC void ffabort(int reason);
|
||||||
SC_FUNC void ffbounds(cell size);
|
SC_FUNC void ffbounds(cell size);
|
||||||
SC_FUNC void jumplabel(int number);
|
SC_FUNC void jumplabel(int number);
|
||||||
SC_FUNC void defstorage(void);
|
SC_FUNC void defstorage(void);
|
||||||
|
SC_FUNC void getfrm(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);
|
||||||
|
|
|
@ -5288,6 +5288,22 @@ static symbol *fetchlab(char *name)
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* isvariadic
|
||||||
|
*
|
||||||
|
* Checks if the function is variadic.
|
||||||
|
*/
|
||||||
|
static int isvariadic(symbol *sym)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i=0; curfunc->dim.arglist[i].ident!=0; i++) {
|
||||||
|
/* check whether this is a variadic function */
|
||||||
|
if (curfunc->dim.arglist[i].ident==iVARARGS) {
|
||||||
|
return TRUE;
|
||||||
|
} /* if */
|
||||||
|
} /* for */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* doreturn
|
/* doreturn
|
||||||
*
|
*
|
||||||
* Global references: rettype (altered)
|
* Global references: rettype (altered)
|
||||||
|
@ -5392,7 +5408,19 @@ static void doreturn(void)
|
||||||
* it stays on the heap for the moment, and it is removed -usually- at
|
* it stays on the heap for the moment, and it is removed -usually- at
|
||||||
* the end of the expression/statement, see expression() in SC3.C)
|
* the end of the expression/statement, see expression() in SC3.C)
|
||||||
*/
|
*/
|
||||||
|
if (isvariadic(sub)) {
|
||||||
|
pushreg(sPRI); /* save source address stored in PRI */
|
||||||
|
sub->addr=2*sizeof(cell);
|
||||||
|
address(sub,sALT); /* get the number of arguments */
|
||||||
|
getfrm();
|
||||||
|
addconst(3*sizeof(cell));
|
||||||
|
ob_add();
|
||||||
|
dereference();
|
||||||
|
swap1();
|
||||||
|
popreg(sALT); /* ALT = destination */
|
||||||
|
} else {
|
||||||
address(sub,sALT); /* ALT = destination */
|
address(sub,sALT); /* ALT = destination */
|
||||||
|
} /* if */
|
||||||
arraysize=calc_arraysize(dim,numdim,0);
|
arraysize=calc_arraysize(dim,numdim,0);
|
||||||
memcopy(arraysize*sizeof(cell)); /* source already in PRI */
|
memcopy(arraysize*sizeof(cell)); /* source already in PRI */
|
||||||
/* moveto1(); is not necessary, callfunction() does a popreg() */
|
/* moveto1(); is not necessary, callfunction() does a popreg() */
|
||||||
|
|
|
@ -410,6 +410,16 @@ SC_FUNC void rvalue(value *lval)
|
||||||
} /* if */
|
} /* if */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* dereference
|
||||||
|
*
|
||||||
|
* Get a cell from a memory address stored in the primary register
|
||||||
|
*/
|
||||||
|
SC_FUNC void dereference(void)
|
||||||
|
{
|
||||||
|
stgwrite("\tload.i\n");
|
||||||
|
code_idx+=opcodes(1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the address of a symbol into the primary or alternate register (used
|
/* Get the address of a symbol into the primary or alternate register (used
|
||||||
* for arrays, and for passing arguments by reference).
|
* for arrays, and for passing arguments by reference).
|
||||||
*/
|
*/
|
||||||
|
@ -829,6 +839,18 @@ SC_FUNC void defstorage(void)
|
||||||
stgwrite("dump ");
|
stgwrite("dump ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copies frame address to primary register
|
||||||
|
*/
|
||||||
|
|
||||||
|
SC_FUNC void getfrm(void)
|
||||||
|
{
|
||||||
|
stgwrite("\tlctrl 5\n");
|
||||||
|
code_idx+=opcodes(1)+opargs(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inclrement/decrement stack pointer. Note that this routine does
|
* Inclrement/decrement stack pointer. Note that this routine does
|
||||||
* nothing if the delta is zero.
|
* nothing if the delta is zero.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user