NODE * funarg(NODE *p, int *n) { NODE *r; int sz; if (p->n_op == CM) { p->n_left = funarg(p->n_left, n); p->n_right = funarg(p->n_right, n); return p; } sz = szty(p->n_type); if (*n % sz) (*n)++; /* XXX LDOUBLE */ if (*n >= 4) { *n += sz; r = block(OREG, NIL, NIL, p->n_type|PTR, 0, 0); r->n_rval = SP; r->n_lval = -(32 + *n * 4); } else { r = block(REG, NIL, NIL, p->n_type, 0, 0); r->n_lval = 0; r->n_rval = argreg(p->n_type, n); } p = block(ASSIGN, r, p, p->n_type, 0, 0); clocal(p); return p; }
/* * 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 **a, int cnt) { struct symtab *sp; NODE *p, *q; int i, n, sz; if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { /* Function returns struct, adjust arg offset */ for (i = 0; i < n; i++) a[i]->soffset += SZPOINT(LONG); } /* recalculate the arg offset and create TEMP moves */ for (n = 0, i = 0; i < cnt; i++) { sp = a[i]; sz = szty(sp->stype); if (n % sz) n++; /* XXX LDOUBLE */ if (n < 4) { p = tempnode(0, sp->stype, sp->sdf, sp->ssue); /* TODO p->n_left->n_lval = -(32 + n * 4); */ q = block(REG, NIL, NIL, sp->stype, sp->sdf, sp->ssue); q->n_rval = argreg(sp->stype, &n); p = buildtree(ASSIGN, p, q); sp->soffset = regno(p->n_left); sp->sflags |= STNODE; ecomp(p); } else { sp->soffset += SZINT * n; if (xtemps) { /* put stack args in temps if optimizing */ p = tempnode(0, sp->stype, sp->sdf, sp->ssue); p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0)); sp->soffset = regno(p->n_left); sp->sflags |= STNODE; ecomp(p); } } } }
//function(..) module saved jan 1 2013 as part of prep for scrt integration static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { int i, saved, sizefsave, sizeisave, varargs; Symbol r, argregs[NUM_ARG_REGS]; usedmask[0] = usedmask[1] = 0; freemask[0] = freemask[1] = ~(unsigned)0; offset = maxoffset = maxargoffset = 0; for (i = 0; callee[i]; i++) //find last argument ; varargs = variadic(f->type) //see if variable arguments by type or by name of final argument || i > 0 && strcmp(callee[i-1]->name, "va_alist") == 0; for (i = 0; callee[i]; i++) { //for each argument Symbol p = callee[i]; Symbol q = caller[i]; assert(q); offset = roundup(offset, q->type->align); //calculate the offset from the caller's sp p->x.offset = q->x.offset = offset; p->x.name = q->x.name = stringd(offset); r = argreg(i, offset, optype(ttob(q->type)), q->type->size, optype(ttob(caller[0]->type))); if (i < NUM_ARG_REGS) argregs[i] = r; offset = roundup(offset + q->type->size, 2); //i dunno if (varargs) p->sclass = AUTO; //variable args are always auto? else if (r && ncalls == 0 && //I dunno !isstruct(q->type) && !p->addressed && !(isfloat(q->type) && r->x.regnode->set == IREG)) { p->sclass = q->sclass = REGISTER; askregvar(p, r); assert(p->x.regnode && p->x.regnode->vbl == p); q->x = p->x; q->type = p->type; } else if (askregvar(p, rmap(ttob(p->type))) && r != NULL && (isint(p->type) || p->type == q->type)) { assert(q->sclass != REGISTER); p->sclass = q->sclass = REGISTER; q->type = p->type; } } assert(!caller[i]); //done with arguments, their individual offsets and maxargoffset have been set offset = 0; gencode(caller, callee); if (ncalls) //prepare to save return address if necessary(i.e. we do calls of our own) usedmask[IREG] |= ((unsigned)1)<<REG_RETADDR; usedmask[IREG] &= INT_CALLEE_SAVE; //limit saving to those we're responsible for usedmask[FREG] &= 0xfff00000; maxargoffset = roundup(maxargoffset, usedmask[FREG] ? 8 : 2); if (ncalls && maxargoffset < NUM_ARG_REGS*2) maxargoffset = NUM_ARG_REGS*2; sizefsave = 4*bitcount(usedmask[FREG]); //space needed to save the float regs sizeisave = 2*bitcount(usedmask[IREG]); //space needed to save the int regs framesize = roundup(maxargoffset + sizefsave //space for outgoing arguments, space for saving floats, + sizeisave + maxoffset, 2); //space for saving ints, space for locals //segment(CODE); //printf("\talign 16\n"); printf("%s:\n", f->x.name); i = maxargoffset + sizefsave - framesize; //I dunno but it's -v and it's never used! if (framesize > 0) print("\talu2I sp,sp,%d,smi,smbi\n", framesize); saved = maxargoffset; /space needed for outgoing arguments