/* * code for the beginning of a function; a is an array of * indices in symtab for the arguments; n is the number */ void bfcode(struct symtab **sp, int cnt) { struct symtab *sp2; NODE *n; int i; if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { /* Function returns struct, adjust arg offset */ for (i = 0; i < cnt; i++) sp[i]->soffset += SZPOINT(INT); } if (xtemps == 0) return; /* put arguments in temporaries */ for (i = 0; i < cnt; i++) { if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY || cisreg(sp[i]->stype) == 0) continue; sp2 = sp[i]; n = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->sap); n = buildtree(ASSIGN, n, nametree(sp2)); sp[i]->soffset = regno(n->n_left); sp[i]->sflags |= STNODE; ecomp(n); } }
void bfcode(struct symtab **sp, int n) { struct symtab *sp2; NODE *p, *q; int i; if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { /* Move return address into temporary */ p = tempnode(0, INT, 0, 0); strtemp = regno(p); q = block(REG, 0, 0, INT, 0, 0); regno(q) = R1; ecomp(buildtree(ASSIGN, p, q)); } if (xtemps == 0) return; /* put arguments in temporaries */ for (i = 0; i < n; i++) { if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY || cisreg(sp[i]->stype) == 0) continue; if (cqual(sp[i]->stype, sp[i]->squal) & VOL) continue; sp2 = sp[i]; p = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->sap); p = buildtree(ASSIGN, p, nametree(sp2)); sp[i]->soffset = regno(p->n_left); sp[i]->sflags |= STNODE; ecomp(p); } }
void bfcode(struct symtab **sp, int n) { struct symtab *sp2; NODE *p, *q; int i, argbase, sz; if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { /* Move return address into temporary */ p = tempnode(0, INT, 0, 0); strtemp = regno(p); q = block(REG, 0, 0, INT, 0, 0); regno(q) = R1; ecomp(buildtree(ASSIGN, p, q)); } /* correct arg alignment XXX should be done somewhere else */ argbase = ARGINIT; for (i = 0; i < n; i++) { sp2 = sp[i]; sz = tsize(sp2->stype, sp2->sdf, sp2->sap); SETOFF(sz, SZINT); sp2->soffset = argbase; argbase += sz; } if (xtemps == 0) return; /* put arguments in temporaries */ for (i = 0; i < n; i++) { if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY || cisreg(sp[i]->stype) == 0) continue; if (cqual(sp[i]->stype, sp[i]->squal) & VOL) continue; sp2 = sp[i]; p = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->sap); p = buildtree(ASSIGN, p, nametree(sp2)); sp[i]->soffset = regno(p->n_left); sp[i]->sflags |= STNODE; ecomp(p); } }
/* * code for the beginning of a function; a is an array of * indices in symtab for the arguments; n is the number * * Classifying args on i386; not simple: * - Args may be on stack or in registers (regparm) * - There may be a hidden first arg, unless OpenBSD struct return. * - Regparm syntax is not well documented. * - There may be stdcall functions, where the called function pops stack * - ...probably more */ void bfcode(struct symtab **sp, int cnt) { extern int argstacksize; #ifdef GCC_COMPAT struct attr *ap; #endif struct symtab *sp2; extern int gotnr; NODE *n, *p; int i, regparmarg; int argbase, nrarg, sz; argbase = ARGINIT; nrarg = regparmarg = 0; #ifdef GCC_COMPAT if (attr_find(cftnsp->sap, GCC_ATYP_STDCALL) != NULL) cftnsp->sflags |= SSTDCALL; if ((ap = attr_find(cftnsp->sap, GCC_ATYP_REGPARM))) regparmarg = ap->iarg(0); #endif /* Function returns struct, create return arg node */ if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { { if (regparmarg) { n = block(REG, 0, 0, INT, 0, 0); regno(n) = regpregs[nrarg++]; } else { n = block(OREG, 0, 0, INT, 0, 0); n->n_lval = argbase/SZCHAR; argbase += SZINT; regno(n) = FPREG; } p = tempnode(0, INT, 0, 0); structrettemp = regno(p); p = buildtree(ASSIGN, p, n); ecomp(p); } } /* * Find where all params are so that they end up at the right place. * At the same time recalculate their arg offset on stack. * We also get the "pop size" for stdcall. */ for (i = 0; i < cnt; i++) { sp2 = sp[i]; sz = tsize(sp2->stype, sp2->sdf, sp2->sap); SETOFF(sz, SZINT); if (cisreg(sp2->stype) == 0 || ((regparmarg - nrarg) * SZINT < sz)) { /* not in reg */ sp2->soffset = argbase; argbase += sz; nrarg = regparmarg; /* no more in reg either */ } else { /* in reg */ sp2->soffset = nrarg; nrarg += sz/SZINT; sp2->sclass = REGISTER; } } /* * Now (argbase - ARGINIT) is used space on stack. * Move (if necessary) the args to something new. */ for (i = 0; i < cnt; i++) { int reg, j; sp2 = sp[i]; if (ISSOU(sp2->stype) && sp2->sclass == REGISTER) { /* must move to stack */ sz = tsize(sp2->stype, sp2->sdf, sp2->sap); SETOFF(sz, SZINT); SETOFF(autooff, SZINT); reg = sp2->soffset; sp2->sclass = AUTO; sp2->soffset = NOOFFSET; oalloc(sp2, &autooff); for (j = 0; j < sz/SZCHAR; j += 4) { p = block(OREG, 0, 0, INT, 0, 0); p->n_lval = sp2->soffset/SZCHAR + j; regno(p) = FPREG; n = block(REG, 0, 0, INT, 0, 0); regno(n) = regpregs[reg++]; p = block(ASSIGN, p, n, INT, 0, 0); ecomp(p); } } else if (cisreg(sp2->stype) && !ISSOU(sp2->stype) && ((cqual(sp2->stype, sp2->squal) & VOL) == 0)) { /* just put rest in temps */ if (sp2->sclass == REGISTER) { n = block(REG, 0, 0, sp2->stype, sp2->sdf, sp2->sap); if (ISLONGLONG(sp2->stype)|| sp2->stype == LONG || sp2->stype == ULONG) regno(n) = longregs[sp2->soffset]; else if (DEUNSIGN(sp2->stype) == CHAR || sp2->stype == BOOL) regno(n) = charregs[sp2->soffset]; else regno(n) = regpregs[sp2->soffset]; } else { n = block(OREG, 0, 0, sp2->stype, sp2->sdf, sp2->sap); n->n_lval = sp2->soffset/SZCHAR; regno(n) = FPREG; } p = tempnode(0, sp2->stype, sp2->sdf, sp2->sap); sp2->soffset = regno(p); sp2->sflags |= STNODE; n = buildtree(ASSIGN, p, n); ecomp(n); } } argstacksize = 0; if (cftnsp->sflags & SSTDCALL) { argstacksize = (argbase - ARGINIT)/SZCHAR; } }