Fix reglap for procedures that use both sizes of reg_float.
After the RA phase of ego, a procedure may put single-word and double-word values in the same reg_float. Then ncg will use both LOCAL and DLOCAL tokens at the same offset. I add isregvar_size() to ncg. It receives the size of the LOCAL or DLOCAL token, and picks the register of the correct size. This fixes a problem where ncg got the wrong-size register and corrupted the stack. This problem caused one of my test programs to segfault from stack underflow. Also adjust how fixregvars() handles both sizes.
This commit is contained in:
parent
b342b83d28
commit
aa876ff4c2
|
@ -102,40 +102,44 @@ tryreg(struct regvar *rvlp, int typ) {
|
||||||
|
|
||||||
void
|
void
|
||||||
fixregvars(int saveall) {
|
fixregvars(int saveall) {
|
||||||
register struct regvar *rv;
|
struct reginfo *rp, *rp2;
|
||||||
register rvtyp,i;
|
struct regvar *rv;
|
||||||
|
int i, regno, rvtyp;
|
||||||
|
|
||||||
swtxt();
|
swtxt();
|
||||||
i_regsave(); /* machine dependent initialization */
|
i_regsave(); /* machine dependent initialization */
|
||||||
for (rvtyp=reg_any;rvtyp<=reg_float;rvtyp++) {
|
for (rvtyp=reg_any;rvtyp<=reg_float;rvtyp++) {
|
||||||
for(i=0;i<nregvar[rvtyp];i++)
|
for(i=0;i<nregvar[rvtyp];i++)
|
||||||
if (saveall) {
|
if (saveall) {
|
||||||
struct reginfo *rp;
|
|
||||||
rp= &machregs[rvnumbers[rvtyp][i]];
|
rp= &machregs[rvnumbers[rvtyp][i]];
|
||||||
|
#ifdef REGLAP
|
||||||
|
/*
|
||||||
|
* A reg_float may have two sizes. If so,
|
||||||
|
* only save the larger size.
|
||||||
|
*/
|
||||||
|
if ((regno = rp->r_members[0]) != 0 &&
|
||||||
|
machregs[regno].r_size > rp->r_size)
|
||||||
|
rp= &machregs[regno];
|
||||||
|
#endif
|
||||||
regsave(codestrings[rp->r_repr],
|
regsave(codestrings[rp->r_repr],
|
||||||
(long)-TEM_WSIZE,rp->r_size);
|
(long)-TEM_WSIZE,rp->r_size);
|
||||||
#ifdef REGLAP
|
|
||||||
/* reg_float may have one subregister */
|
|
||||||
if (rp->r_members[0]!=0) {
|
|
||||||
rp= &machregs[rp->r_members[0]];
|
|
||||||
regsave(codestrings[rp->r_repr],
|
|
||||||
(long)-TEM_WSIZE,rp->r_size);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else if(regassigned[rvtyp][i].ra_score>0) {
|
} else if(regassigned[rvtyp][i].ra_score>0) {
|
||||||
rv=regassigned[rvtyp][i].ra_rv;
|
rv=regassigned[rvtyp][i].ra_rv;
|
||||||
rv->rv_reg=rvnumbers[rvtyp][i];
|
rv->rv_reg = regno = rvnumbers[rvtyp][i];
|
||||||
rv->rv_type = rvtyp;
|
rv->rv_type = rvtyp;
|
||||||
#ifdef REGLAP
|
#ifdef REGLAP
|
||||||
/* reg_float may have alternate size */
|
/*
|
||||||
if (machregs[rv->rv_reg].r_size != rv->rv_size) {
|
* Change regno to match rv->rv_size, but
|
||||||
rv->rv_reg = machregs[rv->rv_reg].r_members[0];
|
* leave old regno in rv->rv_reg so that
|
||||||
assert(rv->rv_reg != 0);
|
* isregvar_size() can handle both sizes.
|
||||||
assert(machregs[rv->rv_reg].r_size ==
|
*/
|
||||||
rv->rv_size);
|
if (machregs[regno].r_size != rv->rv_size) {
|
||||||
|
regno = machregs[regno].r_members[0];
|
||||||
|
assert(regno != 0);
|
||||||
|
assert(machregs[regno].r_size == rv->rv_size);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
regsave(codestrings[machregs[rv->rv_reg].r_repr],
|
regsave(codestrings[machregs[regno].r_repr],
|
||||||
rv->rv_off,rv->rv_size);
|
rv->rv_off,rv->rv_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,6 +156,26 @@ isregvar(long off) {
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef REGLAP
|
||||||
|
int
|
||||||
|
isregvar_size(long off, int size) {
|
||||||
|
int regno = isregvar(off);
|
||||||
|
/*
|
||||||
|
* A reg_float may have two sizes. If this register has the
|
||||||
|
* wrong size, then use the overlapping register. A register
|
||||||
|
* may switch sizes in the middle of a procedure.
|
||||||
|
*/
|
||||||
|
if (regno > 0 && machregs[regno].r_size != size) {
|
||||||
|
if (machregs[regno].r_size != size) {
|
||||||
|
regno = machregs[regno].r_members[0];
|
||||||
|
assert(regno != 0);
|
||||||
|
assert(machregs[regno].r_size == size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return regno;
|
||||||
|
}
|
||||||
|
#endif /* REGLAP */
|
||||||
|
|
||||||
int
|
int
|
||||||
isregtyp(long off) {
|
isregtyp(long off) {
|
||||||
register struct regvar *rvlp;
|
register struct regvar *rvlp;
|
||||||
|
|
|
@ -26,5 +26,10 @@ struct regvar *linkreg(long, int, int, int);
|
||||||
void tryreg(struct regvar *, int);
|
void tryreg(struct regvar *, int);
|
||||||
void fixregvars(int);
|
void fixregvars(int);
|
||||||
int isregvar(long);
|
int isregvar(long);
|
||||||
|
#ifdef REGLAP
|
||||||
|
int isregvar_size(long, int);
|
||||||
|
#else
|
||||||
|
#define isregvar_size(off, size) isregvar(off)
|
||||||
|
#endif
|
||||||
int isregtyp(long);
|
int isregtyp(long);
|
||||||
void unlinkregs(void);
|
void unlinkregs(void);
|
||||||
|
|
|
@ -121,7 +121,9 @@ instance(instno,token) register token_p token; {
|
||||||
case IN_D_DESCR:
|
case IN_D_DESCR:
|
||||||
compute(&enodes[inp->in_info[1]], &result);
|
compute(&enodes[inp->in_info[1]], &result);
|
||||||
assert(result.e_typ==EV_INT);
|
assert(result.e_typ==EV_INT);
|
||||||
if ((regno=isregvar(result.e_v.e_con)) > 0) {
|
regno = isregvar_size(result.e_v.e_con,
|
||||||
|
tokens[inp->in_info[0]].t_size);
|
||||||
|
if (regno > 0) {
|
||||||
token->t_token = -1;
|
token->t_token = -1;
|
||||||
token->t_att[0].ar = regno;
|
token->t_att[0].ar = regno;
|
||||||
for (i=TOKENSIZE-1;i>0;i--)
|
for (i=TOKENSIZE-1;i>0;i--)
|
||||||
|
|
Loading…
Reference in a new issue