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); } }
/* * Evaluate AND/OR/ER. p1 and p2 are pointers to ti struct. */ static NODE * gcc_andorer(int op, NODE *p1, NODE *p2) { char *n = tistack(); NODE *p, *t1, *t2, *p3; t1 = tempnode(0, p1->n_type, p1->n_df, p1->n_ap); t2 = tempnode(0, p2->n_type, p2->n_df, p2->n_ap); p1 = buildtree(ASSIGN, ccopy(t1), p1); p2 = buildtree(ASSIGN, ccopy(t2), p2); p = buildtree(COMOP, p1, p2); p3 = buildtree(ADDROF, eve(bdty(NAME, n)), NIL); p1 = buildtree(ASSIGN, structref(ccopy(p3), STREF, hiti), buildtree(op, structref(ccopy(t1), STREF, hiti), structref(ccopy(t2), STREF, hiti))); p = buildtree(COMOP, p, p1); p1 = buildtree(ASSIGN, structref(ccopy(p3), STREF, loti), buildtree(op, structref(t1, STREF, loti), structref(t2, STREF, loti))); p = buildtree(COMOP, p, p1); p = buildtree(COMOP, p, buildtree(UMUL, p3, NIL)); return p; }
/* setup a float param on the stack * used by bfcode() */ static void param_float(struct symtab *sym, int *argofsp, int dotemps) { NODE *p, *q, *t; int tmpnr; /* * we have to dump the float from the general register * into a temp, since the register allocator doesn't like * floats to be in CLASSA. This may not work for -xtemps. */ t = tempnode(0, INT, 0, 0); tmpnr = regno(t); q = block(REG, NIL, NIL, INT, 0, 0); q->n_rval = R0 + (*argofsp)++; p = buildtree(ASSIGN, t, q); ecomp(p); if (dotemps) { sym->soffset = tmpnr; sym->sflags |= STNODE; } else { q = tempnode(tmpnr, sym->stype, sym->sdf, sym->sap); p = nametree(sym); p = buildtree(ASSIGN, p, q); ecomp(p); } }
void efcode(void) { TWORD t; NODE *p, *q; /* code for the end of a function */ if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) return; t = PTR+BTYPE(cftnsp->stype); /* Create struct assignment */ q = tempnode(strtemp, t, 0, cftnsp->sap); q = buildtree(UMUL, q, NIL); p = block(REG, NIL, NIL, t, 0, cftnsp->sap); regno(p) = R0; p = buildtree(UMUL, p, NIL); p = buildtree(ASSIGN, q, p); ecomp(p); /* put hidden arg in r0 on return */ q = tempnode(strtemp, INT, 0, 0); p = block(REG, NIL, NIL, INT, 0, 0); regno(p) = R0; ecomp(buildtree(ASSIGN, p, q)); }
/* * code for the beginning of a function; a is an array of * indices in stab for the arguments; n is the number */ void bfcode(struct symtab **sp, int cnt) { NODE *p, *q; int i, n; if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { uerror("no struct return yet"); } /* recalculate the arg offset and create TEMP moves */ for (n = 1, i = 0; i < cnt; i++) { if (n < 8) { p = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->ssue); q = block(REG, NIL, NIL, sp[i]->stype, sp[i]->sdf, sp[i]->ssue); q->n_rval = n; p = buildtree(ASSIGN, p, q); sp[i]->soffset = regno(p->n_left); sp[i]->sflags |= STNODE; ecomp(p); } else { sp[i]->soffset += SZINT * n; if (xtemps) { /* put stack args in temps if optimizing */ p = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->ssue); p = buildtree(ASSIGN, p, nametree(sp[i])); sp[i]->soffset = regno(p->n_left); sp[i]->sflags |= STNODE; ecomp(p); } } n += szty(sp[i]->stype); } }
static NODE * builtin_va_arg(const struct bitable *bt, NODE *a) { NODE *p, *q, *r, *rv; int sz, nodnum; /* create a copy to a temp node of current ap */ p = ccopy(a->n_left); q = tempnode(0, p->n_type, p->n_df, p->n_ap); nodnum = regno(q); rv = buildtree(ASSIGN, q, p); r = a->n_right; sz = (int)tsize(r->n_type, r->n_df, r->n_ap)/SZCHAR; /* add one to ap */ #ifdef BACKAUTO rv = buildtree(COMOP, rv , buildtree(PLUSEQ, a->n_left, bcon(sz))); #else #error fix wrong eval order in builtin_va_arg ecomp(buildtree(MINUSEQ, a->n_left, bcon(sz))); #endif nfree(a->n_right); nfree(a); r = tempnode(nodnum, INCREF(r->n_type), r->n_df, r->n_ap); return buildtree(COMOP, rv, buildtree(UMUL, r, NIL)); }
void bfcode(struct symtab **sp, int cnt) { int i, off; NODE *p, *q; struct symtab *sym; /* Process the first six arguments. */ for (i=0; i < cnt && i < 6; i++) { sym = sp[i]; q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->sap); q->n_rval = RETREG_PRE(sym->stype) + i; p = tempnode(0, sym->stype, sym->sdf, sym->sap); sym->soffset = regno(p); sym->sflags |= STNODE; p = buildtree(ASSIGN, p, q); ecomp(p); } /* Process the remaining arguments. */ for (off = V9RESERVE; i < cnt; i++) { sym = sp[i]; p = tempnode(0, sym->stype, sym->sdf, sym->sap); off = ALIGN(off, (tlen(p) - 1)); sym->soffset = off * SZCHAR; off += tlen(p); p = buildtree(ASSIGN, p, nametree(sym)); sym->soffset = regno(p->n_left); sym->sflags |= STNODE; ecomp(p); } }
/* * code for the end of a function * deals with struct return here */ void efcode(void) { NODE *p, *q; int tempnr; int ty; if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) return; ty = cftnsp->stype - FTN; q = block(REG, NIL, NIL, INCREF(ty), 0, cftnsp->sap); q->n_rval = V0; p = tempnode(0, INCREF(ty), 0, cftnsp->sap); tempnr = regno(p); p = buildtree(ASSIGN, p, q); ecomp(p); q = tempnode(tempnr, INCREF(ty), 0, cftnsp->sap); q = buildtree(UMUL, q, NIL); p = tempnode(rvnr, INCREF(ty), 0, cftnsp->sap); p = buildtree(UMUL, p, NIL); p = buildtree(ASSIGN, p, q); ecomp(p); q = tempnode(rvnr, INCREF(ty), 0, cftnsp->sap); p = block(REG, NIL, NIL, INCREF(ty), 0, cftnsp->sap); p->n_rval = V0; p = buildtree(ASSIGN, p, q); ecomp(p); }
static NODE * moveargs(NODE *p, int *regp) { NODE *r, **rp; int lastreg; int reg; if (p->n_op == CM) { p->n_left = moveargs(p->n_left, regp); r = p->n_right; rp = &p->n_right; } else { r = p; rp = &p; } lastreg = A0 + nargregs - 1; reg = *regp; if (reg > lastreg && r->n_op != STARG) *rp = block(FUNARG, r, NIL, r->n_type, r->n_df, r->n_ap); else if (r->n_op == STARG) { *rp = movearg_struct(r, p, regp); } else if (DEUNSIGN(r->n_type) == LONGLONG) { *rp = movearg_64bit(r, regp); } else if (r->n_type == DOUBLE || r->n_type == LDOUBLE) { /* XXX bounce in and out of temporary to change to longlong */ NODE *t1 = tempnode(0, LONGLONG, 0, 0); int tmpnr = regno(t1); NODE *t2 = tempnode(tmpnr, r->n_type, r->n_df, r->n_ap); t1 = movearg_64bit(t1, regp); r = block(ASSIGN, t2, r, r->n_type, r->n_df, r->n_ap); if (p->n_op == CM) { p->n_left = buildtree(CM, p->n_left, t1); p->n_right = r; } else { p = buildtree(CM, t1, r); } } else if (r->n_type == FLOAT) { /* XXX bounce in and out of temporary to change to int */ NODE *t1 = tempnode(0, INT, 0, 0); int tmpnr = regno(t1); NODE *t2 = tempnode(tmpnr, r->n_type, r->n_df, r->n_ap); t1 = movearg_32bit(t1, regp); r = block(ASSIGN, t2, r, r->n_type, r->n_df, r->n_ap); if (p->n_op == CM) { p->n_left = buildtree(CM, p->n_left, t1); p->n_right = r; } else { p = buildtree(CM, t1, r); } } else { *rp = movearg_32bit(r, regp); } return p; }
/* * code for the end of a function * deals with struct return here * The return value is in (or pointed to by) RETREG. */ void efcode(void) { struct symtab *sp; extern int gotnr; TWORD t; NODE *p, *r, *l; int typ, ssz, rno; gotnr = 0; /* new number for next fun */ sp = cftnsp; t = DECREF(sp->stype); if (t != STRTY && t != UNIONTY) return; /* XXX should have one routine for this */ ngpr = nsse = 0; if ((typ = argtyp(t, sp->sdf, sp->sap)) == STRREG || typ == STRCPX) { /* Cast to long pointer and move to the registers */ /* XXX can overrun struct size */ /* XXX check carefully for SSE members */ if ((ssz = tsize(t, sp->sdf, sp->sap)) > SZLONG*2) cerror("efcode1"); if (typ == STRCPX) { t = DOUBLE; rno = XMM0; } else { t = LONG; rno = RAX; } if (ssz > SZLONG) { p = block(REG, NIL, NIL, INCREF(t), 0, 0); regno(p) = RAX; p = buildtree(UMUL, buildtree(PLUS, p, bcon(1)), NIL); ecomp(movtoreg(p, rno+1)); } p = block(REG, NIL, NIL, INCREF(t), 0, 0); regno(p) = RAX; p = buildtree(UMUL, p, NIL); ecomp(movtoreg(p, rno)); } else if (typ == STRMEM) { r = block(REG, NIL, NIL, INCREF(t), sp->sdf, sp->sap); regno(r) = RAX; r = buildtree(UMUL, r, NIL); l = tempnode(stroffset, INCREF(t), sp->sdf, sp->sap); l = buildtree(UMUL, l, NIL); ecomp(buildtree(ASSIGN, l, r)); l = block(REG, NIL, NIL, LONG, 0, 0); regno(l) = RAX; r = tempnode(stroffset, LONG, 0, 0); ecomp(buildtree(ASSIGN, l, r)); } else cerror("efcode"); }
NODE * mips_builtin_va_arg(NODE *f, NODE *a, TWORD t) { NODE *p, *q, *r; int sz, tmpnr; /* check num args and type */ if (a == NULL || a->n_op != CM || a->n_left->n_op == CM || !ISPTR(a->n_left->n_type) || a->n_right->n_op != TYPE) goto bad; r = a->n_right; /* get type size */ sz = tsize(r->n_type, r->n_df, r->n_ap) / SZCHAR; if (sz < SZINT/SZCHAR) { werror("%s%s promoted to int when passed through ...", r->n_type & 1 ? "unsigned " : "", DEUNSIGN(r->n_type) == SHORT ? "short" : "char"); sz = SZINT/SZCHAR; } /* alignment */ p = tcopy(a->n_left); if (sz > SZINT/SZCHAR && r->n_type != UNIONTY && r->n_type != STRTY) { p = buildtree(PLUS, p, bcon(7)); p = block(AND, p, bcon(-8), p->n_type, p->n_df, p->n_ap); } /* create a copy to a temp node */ q = tempnode(0, p->n_type, p->n_df, p->n_ap); tmpnr = regno(q); p = buildtree(ASSIGN, q, p); q = tempnode(tmpnr, p->n_type, p->n_df,p->n_ap); q = buildtree(PLUS, q, bcon(sz)); q = buildtree(ASSIGN, a->n_left, q); q = buildtree(COMOP, p, q); nfree(a->n_right); nfree(a); nfree(f); p = tempnode(tmpnr, INCREF(r->n_type), r->n_df, r->n_ap); p = buildtree(UMUL, p, NIL); p = buildtree(COMOP, q, p); return p; bad: uerror("bad argument to __builtin_va_arg"); return bcon(0); }
/* * Sort arglist so that register assignments ends up last. */ static int argsort(NODE *p) { NODE *q, *r; int rv = 0; if (p->n_op != CM) { if (p->n_op == ASSIGN && p->n_left->n_op == REG && coptype(p->n_right->n_op) != LTYPE) { q = tempnode(0, p->n_type, p->n_df, p->n_ap); r = ccopy(q); p->n_right = buildtree(COMOP, buildtree(ASSIGN, q, p->n_right), r); } return rv; } if (p->n_right->n_op == CM) { /* fixup for small structs in regs */ q = p->n_right->n_left; p->n_right->n_left = p->n_left; p->n_left = p->n_right; p->n_right = p->n_left->n_right; p->n_left->n_right = q; } if (p->n_right->n_op == ASSIGN && p->n_right->n_left->n_op == REG && coptype(p->n_right->n_right->n_op) != LTYPE) { /* move before everything to avoid reg trashing */ q = tempnode(0, p->n_right->n_type, p->n_right->n_df, p->n_right->n_ap); r = ccopy(q); p->n_right->n_right = buildtree(COMOP, buildtree(ASSIGN, q, p->n_right->n_right), r); } if (p->n_right->n_op == ASSIGN && p->n_right->n_left->n_op == REG) { if (p->n_left->n_op == CM && p->n_left->n_right->n_op == STASG) { q = p->n_left->n_right; p->n_left->n_right = p->n_right; p->n_right = q; rv = 1; } else if (p->n_left->n_op == STASG) { q = p->n_left; p->n_left = p->n_right; p->n_right = q; rv = 1; } } return rv | argsort(p->n_left); }
/* * replace an alloca function with direct allocation on stack. * return a destination temp node. */ static NODE * builtin_alloca(const struct bitable *bt, NODE *a) { NODE *t, *u; #ifdef notyet if (xnobuiltins) return NULL; #endif t = tempnode(0, VOID|PTR, 0, 0); u = tempnode(regno(t), VOID|PTR, 0, 0); spalloc(t, a, SZCHAR); return u; }
/* * The "initial exec" tls model. */ static NODE * tlsinitialexec(NODE *p) { NODE *q, *r, *s; char *s1, *s2; /* * movq %fs:0,%rax * addq x@GOTTPOFF(%rip),%rax */ q = bcon(0); q->n_type = STRTY; s = ccopy(r = tempnode(0, INCREF(p->n_type), p->n_df, p->n_ap)); r = mkx("=r", r); r = block(XASM, r, q, INT, 0, 0); s1 = "movq %%fs:0,%0\n\taddq "; s2 = "@GOTTPOFF(%%rip),%0"; if (attr_find(p->n_sp->sap, ATTR_SONAME) == NULL) { p->n_sp->sap = attr_add(p->n_sp->sap, attr_new(ATTR_SONAME, 1)); p->n_sp->sap->sarg(0) = p->n_sp->sname; } r->n_name = mk3str(s1, attr_find(p->n_sp->sap, ATTR_SONAME)->sarg(0), s2); r = block(COMOP, r, s, INCREF(p->n_type), p->n_df, p->n_ap); r = buildtree(UMUL, r, NIL); tfree(p); return r; }
/* * code for the end of a function * deals with struct return here */ void efcode(void) { NODE *p, *q; // int sz; #if 0 /* restore ac3 */ p = block(REG, 0, 0, INT, 0, 0); regno(p) = 3; q = tempnode(ac3temp, INT, 0, 0); ecomp(buildtree(ASSIGN, p, q)); #endif if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) return; cerror("efcode"); /* address of return struct is in eax */ /* create a call to memcpy() */ /* will get the result in eax */ p = block(REG, NIL, NIL, CHAR+PTR, 0, 0); // p->n_rval = EAX; q = block(OREG, NIL, NIL, CHAR+PTR, 0, 0); // q->n_rval = EBP; q->n_lval = 8; /* return buffer offset */ p = block(CM, q, p, INT, 0, 0); // sz = (tsize(STRTY, cftnsp->sdf, cftnsp->ssue)+SZCHAR-1)/SZCHAR; // p = block(CM, p, bcon(sz), INT, 0, 0); p->n_right->n_name = ""; p = block(CALL, bcon(0), p, CHAR+PTR, 0, 0); p->n_left->n_name = "memcpy"; p = clocal(p); send_passt(IP_NODE, p); }
/* * Fixup arguments to pass pointer-to-struct as first argument. * * called from funcode(). */ static NODE * retstruct(NODE *p) { NODE *l, *r, *t, *q; TWORD ty; l = p->n_left; r = p->n_right; ty = DECREF(l->n_type) - FTN; // assert(tsize(ty, l->n_df, l->n_ap) == SZINT); /* structure assign */ q = tempnode(0, ty, l->n_df, l->n_ap); q = buildtree(ADDROF, q, NIL); /* insert hidden assignment at beginning of list */ if (r->n_op != CM) { p->n_right = block(CM, q, r, INCREF(ty), l->n_df, l->n_ap); } else { for (t = r; t->n_left->n_op == CM; t = t->n_left) ; t->n_left = block(CM, q, t->n_left, INCREF(ty), l->n_df, l->n_ap); } return p; }
/* * Called with a function call with arguments as argument. * This is done early in buildtree() and only done once. */ NODE * funcode(NODE *p) { int regnum = A0; NODE *l, *r, *t, *q; int ty; l = p->n_left; r = p->n_right; /* * if returning a structure, make the first argument * a hidden pointer to return structure. */ ty = DECREF(l->n_type); if (ty == STRTY+FTN || ty == UNIONTY+FTN) { ty = DECREF(l->n_type) - FTN; q = tempnode(0, ty, l->n_df, l->n_ap); q = buildtree(ADDROF, q, NIL); if (r->n_op != CM) { p->n_right = block(CM, q, r, INCREF(ty), l->n_df, l->n_ap); } else { for (t = r; t->n_left->n_op == CM; t = t->n_left) ; t->n_left = block(CM, q, t->n_left, INCREF(ty), l->n_df, l->n_ap); } } p->n_right = moveargs(p->n_right, ®num); 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 **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); } }
/* * The "initial exec" tls model. */ static NODE * tlsinitialexec(NODE *p) { NODE *q, *r, *s; char *s1, *s2; /* * movq %fs:0,%rax * addq x@GOTTPOFF(%rip),%rax */ q = bcon(0); q->n_type = STRTY; s = ccopy(r = tempnode(0, INCREF(p->n_type), p->n_df, p->n_ap)); r = mkx("=r", r); r = block(XASM, r, q, INT, 0, 0); s1 = "movq %%fs:0,%0\n\taddq "; s2 = "@GOTTPOFF(%%rip),%0"; if (p->n_sp->soname == NULL) p->n_sp->soname = p->n_sp->sname; r->n_name = mk3str(s1, p->n_sp->soname, s2); r = block(COMOP, r, s, INCREF(p->n_type), p->n_df, p->n_ap); r = buildtree(UMUL, r, NIL); tfree(p); return r; }
/* * Create a reference for an extern variable. */ static NODE * picext(NODE *p) { NODE *q, *r; struct symtab *sp; char *name; q = tempnode(gotnr, PTR|VOID, 0, 0); name = getexname(p->n_sp); #ifdef notdef struct attr *ga; if ((ga = attr_find(p->n_sp->sap, GCC_ATYP_VISIBILITY)) && strcmp(ga->sarg(0), "hidden") == 0) { /* For hidden vars use GOTOFF */ sp = picsymtab("", name, "@GOTOFF"); r = xbcon(0, sp, INT); q = buildtree(PLUS, q, r); q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); q->n_sp = p->n_sp; /* for init */ nfree(p); return q; } #endif sp = picsymtab("", name, "@GOT"); r = xbcon(0, sp, INT); q = buildtree(PLUS, q, r); q = block(UMUL, q, 0, PTR|VOID, 0, 0); q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); q->n_sp = p->n_sp; /* for init */ nfree(p); return q; }
/* * replace an alloca function with direct allocation on stack. * return a destination temp node. */ static NODE * builtin_alloca(NODE *f, NODE *a, TWORD rt) { NODE *t, *u; #ifdef notyet if (xnobuiltins) return NULL; #endif t = tempnode(0, VOID|PTR, 0, 0); u = tempnode(regno(t), VOID|PTR, 0, 0); spalloc(t, a, SZCHAR); tfree(f); return u; }
static NODE * picstatic(NODE *p) { NODE *q, *r; struct symtab *sp; q = tempnode(gotnr, PTR|VOID, 0, 0); if (p->n_sp->slevel > 0) { char buf[32]; if ((p->n_sp->sflags & SMASK) == SSTRING) p->n_sp->sflags |= SASG; snprintf(buf, 32, LABFMT, (int)p->n_sp->soffset); sp = picsymtab("", buf, "@GOT"); } else { sp = picsymtab("", getsoname(p->n_sp), "@GOT"); } sp->sclass = STATIC; sp->stype = p->n_sp->stype; r = xbcon(0, sp, INT); q = buildtree(PLUS, q, r); q = block(UMUL, q, 0, PTR|VOID, 0, 0); q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); q->n_sp = p->n_sp; /* for init */ nfree(p); return q; }
/* * Find number of beginning 0's in a word of type t. * t should be deunsigned. */ static NODE * builtin_ff(NODE *f, NODE *a, TWORD t) { NODE *t101, *t102; NODE *rn, *p; int l15, l16, l17; int sz; tfree(f); t = ctype(t); sz = (int)tsize(t, 0, 0)+1; t101 = tempnode(0, INT, 0, 0); t102 = tempnode(0, t, 0, 0); l15 = getlab(); l16 = getlab(); l17 = getlab(); rn = buildtree(ASSIGN, ccopy(t101), bcon(0)); rn = cmop(rn, buildtree(ASSIGN, ccopy(t102), a)); p = buildtree(CBRANCH, buildtree(EQ, ccopy(t102), bcon(0)), bcon(l15)); rn = cmop(rn, p); rn = cmop(rn, buildtree(INCR, ccopy(t101), bcon(1))); rn = cmop(rn, lblnod(l16)); p = buildtree(CBRANCH, buildtree(GE, ccopy(t101), bcon(sz)), bcon(l15)); rn = cmop(rn, p); p = buildtree(CBRANCH, buildtree(EQ, buildtree(AND, ccopy(t102), bcon(1)), bcon(0)), bcon(l17)); rn = cmop(rn, p); rn = cmop(rn, block(GOTO, bcon(l15), NIL, INT, 0, 0)); rn = cmop(rn, lblnod(l17)); rn = cmop(rn, buildtree(RSEQ, t102, bcon(1))); rn = cmop(rn, buildtree(INCR, ccopy(t101), bcon(1))); rn = cmop(rn, block(GOTO, bcon(l16), NIL, INT, 0, 0)); rn = cmop(rn, lblnod(l15)); return cmop(rn, t101); }
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); } }
/* called from moveargs() */ static NODE * movearg_float(NODE *p, int *regp) { NODE *q, *r; TWORD ty = INCREF(p->n_type); int tmpnr; /* * Floats are passed in the general registers for * compatibily with libraries compiled to handle soft-float. */ if (xtemps) { /* bounce on TOS */ r = block(REG, NIL, NIL, ty, p->n_df, p->n_ap); regno(r) = SP; r = block(PLUS, r, bcon(-4), ty, p->n_df, p->n_ap); r = block(UMUL, r, NIL, p->n_type, p->n_df, p->n_ap); r = buildtree(ASSIGN, r, p); ecomp(r); /* bounce into temp */ r = block(REG, NIL, NIL, PTR+INT, 0, 0); regno(r) = SP; r = block(PLUS, r, bcon(-8), PTR+INT, 0, 0); r = block(UMUL, r, NIL, INT, 0, 0); q = tempnode(0, INT, 0, 0); tmpnr = regno(q); r = buildtree(ASSIGN, q, r); ecomp(r); } else { /* copy directly into temp */ q = tempnode(0, p->n_type, p->n_df, p->n_ap); tmpnr = regno(q); r = buildtree(ASSIGN, q, p); ecomp(r); } /* copy from temp to register parameter */ r = tempnode(tmpnr, INT, 0, 0); q = block(REG, NIL, NIL, INT, 0, 0); regno(q) = (*regp)++; p = buildtree(ASSIGN, q, r); return p; }
/* * replace an alloca function with direct allocation on stack. * return a destination temp node. */ static NODE * builtin_alloca(NODE *f, NODE *a, TWORD rt) { struct symtab *sp; NODE *t, *u; #ifdef notyet if (xnobuiltins) return NULL; #endif sp = f->n_sp; t = tempnode(0, VOID|PTR, 0, MKAP(INT) /* XXX */); u = tempnode(regno(t), VOID|PTR, 0, MKAP(INT) /* XXX */); spalloc(t, a, SZCHAR); tfree(f); return u; }
/* * 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); } } } }
/* Put a symbol in a temporary * used by bfcode() and its helpers */ static void putintemp(struct symtab *sym) { NODE *p; p = tempnode(0, sym->stype, sym->sdf, sym->sap); p = buildtree(ASSIGN, p, nametree(sym)); sym->soffset = regno(p->n_left); sym->sflags |= STNODE; ecomp(p); }
/* called from moveargs() */ static NODE * movearg_double(NODE *p, int *regp) { NODE *q, *r; TWORD ty = INCREF(p->n_type); int tmpnr; if (xtemps) { /* bounce on TOS */ r = block(REG, NIL, NIL, ty, p->n_df, p->n_ap); regno(r) = SP; r = block(PLUS, r, bcon(-8), ty, p->n_df, p->n_ap); r = block(UMUL, r, NIL, p->n_type, p->n_df, p->n_ap); r = buildtree(ASSIGN, r, p); ecomp(r); /* bounce into temp */ r = block(REG, NIL, NIL, PTR+LONGLONG, 0, 0); regno(r) = SP; r = block(PLUS, r, bcon(-8), PTR+LONGLONG, 0, 0); r = block(UMUL, r, NIL, LONGLONG, 0, 0); q = tempnode(0, LONGLONG, 0, 0); tmpnr = regno(q); r = buildtree(ASSIGN, q, r); ecomp(r); } else { /* copy directly into temp */ q = tempnode(0, p->n_type, p->n_df, p->n_ap); tmpnr = regno(q); r = buildtree(ASSIGN, q, p); ecomp(r); } /* copy from temp to register parameter */ r = tempnode(tmpnr, LONGLONG, 0, 0); q = block(REG, NIL, NIL, LONGLONG, 0, 0); regno(q) = R0R1 - R0 + (*regp); p = buildtree(ASSIGN, q, r); (*regp) += 2; return p; }
/* * XXX This is a hack. We cannot have (l)doubles in more than one * register class. So we bounce them in and out of temps to * move them in and out of the right registers. */ static void param_double(struct symtab *sym, int *regp, int dotemps) { int reg = *regp; NODE *p, *q, *t; int navail; int tmpnr; /* alignment */ ++reg; reg &= ~1; navail = nargregs - (reg - A0); if (navail < 2) { /* would have appeared half in registers/half * on the stack, but alignment ensures it * appears on the stack */ if (dotemps) putintemp(sym); *regp = reg; return; } t = tempnode(0, LONGLONG, 0, 0); tmpnr = regno(t); q = block(REG, NIL, NIL, LONGLONG, 0, 0); q->n_rval = A0A1 + (reg - A0); p = buildtree(ASSIGN, t, q); ecomp(p); if (dotemps) { sym->soffset = tmpnr; sym->sflags |= STNODE; } else { q = tempnode(tmpnr, sym->stype, sym->sdf, sym->sap); p = nametree(sym); p = buildtree(ASSIGN, p, q); ecomp(p); } *regp = reg + 2; }