static NODE * builtin_stdarg_start(const struct bitable *bt, NODE *a) { NODE *p, *q; int sz; /* must first deal with argument size; use int size */ p = a->n_right; if (p->n_type < INT) { sz = (int)(SZINT/tsize(p->n_type, p->n_df, p->n_ap)); } else sz = 1; /* do the real job */ p = buildtree(ADDROF, p, NIL); /* address of last arg */ #ifdef BACKAUTO p = optim(buildtree(PLUS, p, bcon(sz))); /* add one to it (next arg) */ #else p = optim(buildtree(MINUS, p, bcon(sz))); /* add one to it (next arg) */ #endif q = block(NAME, NIL, NIL, PTR+VOID, 0, 0); /* create cast node */ q = buildtree(CAST, q, p); /* cast to void * (for assignment) */ p = q->n_right; nfree(q->n_left); nfree(q); p = buildtree(ASSIGN, a->n_left, p); /* assign to ap */ nfree(a); return p; }
/* * code for the end of a function * deals with struct return here */ void efcode(void) { NODE *p, *q; int sz; if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) return; /* address of return struct is in %ret0 */ /* create a call to memcpy() */ /* will get the result in %ret0 */ p = block(REG, NIL, NIL, CHAR+PTR, 0, 0); p->n_rval = RET0; q = block(OREG, NIL, NIL, CHAR+PTR, 0, 0); q->n_rval = FP; 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); }
NODE * builtin_return_address(const struct bitable *bt, NODE *a) { int nframes; NODE *f; if (a->n_op != ICON) goto bad; nframes = (int)a->n_lval; tfree(a); f = block(REG, NIL, NIL, PTR+VOID, 0, 0); regno(f) = FPREG; while (nframes--) f = block(UMUL, f, NIL, PTR+VOID, 0, 0); f = block(PLUS, f, bcon(2), INCREF(PTR+VOID), 0, 0); f = buildtree(UMUL, f, NIL); return f; bad: uerror("bad argument to __builtin_return_address"); return bcon(0); }
/* * va_start(ap, last) implementation. * * f is the NAME node for this builtin function. * a is the argument list containing: * CM * ap last * * It turns out that this is easy on MIPS. Just write the * argument registers to the stack in va_arg_start() and * use the traditional method of walking the stackframe. */ NODE * mips_builtin_stdarg_start(NODE *f, NODE *a, TWORD t) { NODE *p, *q; int sz = 1; /* check num args and type */ if (a == NULL || a->n_op != CM || a->n_left->n_op == CM || !ISPTR(a->n_left->n_type)) goto bad; /* must first deal with argument size; use int size */ p = a->n_right; if (p->n_type < INT) { /* round up to word */ sz = SZINT / tsize(p->n_type, p->n_df, p->n_ap); } p = buildtree(ADDROF, p, NIL); /* address of last arg */ p = optim(buildtree(PLUS, p, bcon(sz))); q = block(NAME, NIL, NIL, PTR+VOID, 0, 0); q = buildtree(CAST, q, p); p = q->n_right; nfree(q->n_left); nfree(q); p = buildtree(ASSIGN, a->n_left, p); tfree(f); nfree(a); return p; bad: uerror("bad argument to __builtin_stdarg_start"); return bcon(0); }
NODE * builtin_return_address(const struct bitable *bt, NODE *a) { NODE *f; if (a->n_op != ICON) goto bad; if (a->n_lval != 0) werror("unsupported argument"); tfree(a); f = block(REG, NIL, NIL, INCREF(PTR+CHAR), 0, 0); regno(f) = FPREG; f = block(UMUL, block(PLUS, f, bcon(16), INCREF(PTR+CHAR), 0, 0), NIL, PTR+CHAR, 0, 0); f = makety(f, PTR+VOID, 0, 0, 0); return f; bad: uerror("bad argument to __builtin_return_address"); return bcon(0); }
NODE * builtin_frame_address(const struct bitable *bt, NODE *a) { int nframes; NODE *f; if (a->n_op != ICON) goto bad; nframes = a->n_lval; tfree(a); f = block(REG, NIL, NIL, PTR+CHAR, 0, 0); regno(f) = FPREG; while (nframes--) { f = block(UMUL, block(PLUS, f, bcon(12), INCREF(PTR+CHAR), 0, 0), NIL, PTR+CHAR, 0, 0); f = makety(f, PTR+CHAR, 0, 0, 0); } return f; bad: uerror("bad argument to __builtin_frame_address"); return bcon(0); }
/* called by moveargs() */ static NODE * pusharg(NODE *p, int *regp) { NODE *q; int sz; /* convert to register size, if smaller */ sz = tsize(p->n_type, p->n_df, p->n_ap); if (sz < SZINT) p = block(SCONV, p, NIL, INT, 0, 0); q = block(REG, NIL, NIL, INT, 0, 0); regno(q) = SP; if (szty(p->n_type) == 1) { ++(*regp); q = block(MINUSEQ, q, bcon(4), INT, 0, 0); } else { (*regp) += 2; q = block(MINUSEQ, q, bcon(8), INT, 0, 0); } q = block(UMUL, q, NIL, p->n_type, p->n_df, p->n_ap); return buildtree(ASSIGN, q, p); }
/* * Allocate off bits on the stack. p is a tree that when evaluated * is the multiply count for off, t is a storeable node where to write * the allocated address. */ void spalloc(NODE *t, NODE *p, OFFSZ off) { NODE *sp; p = buildtree(MUL, p, bcon(off/SZCHAR)); p = buildtree(PLUS, p, bcon(30)); p = buildtree(AND, p, xbcon(-16, NULL, UNSIGNED)); p = cast(p, UNSIGNED, 0); /* sub the size from sp */ sp = block(REG, NIL, NIL, UNSIGNED+PTR, 0, 0); slval(sp, 0); sp->n_rval = STKREG; p = (buildtree(MINUSEQ, sp, p)); ecomp(p); /* save the address of sp */ sp = block(REG, NIL, NIL, PTR+UNSIGNED, t->n_df, t->n_ap); slval(sp, 0); sp->n_rval = STKREG; t->n_type = sp->n_type; p = (buildtree(ASSIGN, t, sp)); /* Emit! */ ecomp(p); }
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)); }
static NODE * builtin_bswap16(const struct bitable *bt, NODE *a) { NODE *f, *t1, *t2; t1 = buildtree(LS, buildtree(AND, ccopy(a), bcon(255)), bcon(8)); t2 = buildtree(AND, buildtree(RS, a, bcon(8)), bcon(255)); f = buildtree(OR, t1, t2); return f; }
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); }
NODE * funcode(NODE *p) { NODE *r, *l; int reg = 0, stacksize = 0; r = l = 0; p->n_right = moveargs(p->n_right, ®, &stacksize); /* * This is a particularly gross and inefficient way to handle * argument overflows. First, we calculate how much stack space * we need in moveargs(). Then we assign it by moving %sp, make * the function call, and then move %sp back. * * What we should be doing is getting the maximum of all the needed * stacksize values to the prologue and doing it all in the "save" * instruction. */ if (stacksize != 0) { stacksize = V9STEP(stacksize); /* 16-bit alignment. */ r = block(REG, NIL, NIL, INT, 0, 0); r->n_lval = 0; r->n_rval = SP; r = block(MINUS, r, bcon(stacksize), INT, 0, 0); l = block(REG, NIL, NIL, INT, 0, 0); l->n_lval = 0; l->n_rval = SP; r = buildtree(ASSIGN, l, r); p = buildtree(COMOP, r, p); r = block(REG, NIL, NIL, INT, 0, 0); r->n_lval = 0; r->n_rval = SP; r = block(PLUS, r, bcon(stacksize), INT, 0, 0); l = block(REG, NIL, NIL, INT, 0, 0); l->n_lval = 0; l->n_rval = SP; r = buildtree(ASSIGN, l, r); p = buildtree(COMOP, p, r); } return p; }
static NODE * builtin_va_end(NODE *f, NODE *a, TWORD rt) { tfree(f); tfree(a); return bcon(0); /* nothing */ }
/* setup struct parameter * push the registers out to memory * used by bfcode() */ static void param_struct(struct symtab *sym, int *regp) { int reg = *regp; NODE *p, *q; int navail; int sz; int off; int num; int i; navail = nargregs - (reg - A0); sz = tsize(sym->stype, sym->sdf, sym->sap) / SZINT; off = ARGINIT/SZINT + (reg - A0); num = sz > navail ? navail : sz; for (i = 0; i < num; i++) { q = block(REG, NIL, NIL, INT, 0, 0); q->n_rval = reg++; p = block(REG, NIL, NIL, INT, 0, 0); p->n_rval = FP; p = block(PLUS, p, bcon(4*off++), INT, 0, 0); p = block(UMUL, p, NIL, INT, 0, 0); p = buildtree(ASSIGN, p, q); ecomp(p); } *regp = reg; }
static NODE * builtin_prefetch(NODE *f, NODE *a, TWORD rt) { tfree(f); tfree(a); return bcon(0); }
/* setup struct parameter * push the registers out to memory * used by bfcode() */ static void param_struct(struct symtab *sym, int *argofsp) { int argofs = *argofsp; NODE *p, *q; int navail; int sz; int off; int num; int i; navail = NARGREGS - argofs; sz = tsize(sym->stype, sym->sdf, sym->sap) / SZINT; off = ARGINIT/SZINT + argofs; num = sz > navail ? navail : sz; for (i = 0; i < num; i++) { q = block(REG, NIL, NIL, INT, 0, 0); regno(q) = R0 + argofs++; p = block(REG, NIL, NIL, INT, 0, 0); regno(p) = SP; p = block(PLUS, p, bcon(4*off++), INT, 0, 0); p = block(UMUL, p, NIL, INT, 0, 0); p = buildtree(ASSIGN, p, q); ecomp(p); } *argofsp = argofs; }
/* * 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); }
NODE * amd64_builtin_va_end(NODE *f, NODE *a, TWORD t) { tfree(f); tfree(a); return bcon(0); /* nothing */ }
/* * 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; }
NODE * mips_builtin_va_end(NODE *f, NODE *a, TWORD t) { tfree(f); tfree(a); return bcon(0); }
/* * 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; }
/* 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; }
/* * Allocate off bits on the stack. p is a tree that when evaluated * is the multiply count for off, t is a NAME node where to write * the allocated address. */ void spalloc(NODE *t, NODE *p, OFFSZ off) { NODE *sp; if ((off % SZINT) == 0) p = buildtree(MUL, p, bcon(off/SZINT)); else if ((off % SZSHORT) == 0) { p = buildtree(MUL, p, bcon(off/SZSHORT)); p = buildtree(PLUS, p, bcon(1)); p = buildtree(RS, p, bcon(1)); } else if ((off % SZCHAR) == 0) { p = buildtree(MUL, p, bcon(off/SZCHAR)); p = buildtree(PLUS, p, bcon(3)); p = buildtree(RS, p, bcon(2)); } else cerror("roundsp"); /* save the address of sp */ sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue); sp->n_lval = 0; sp->n_rval = STKREG; t->n_type = sp->n_type; ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */ /* add the size to sp */ sp = block(REG, NIL, NIL, p->n_type, 0, 0); sp->n_lval = 0; sp->n_rval = STKREG; ecomp(buildtree(PLUSEQ, sp, p)); }
static NODE * mkstkref(int off, TWORD typ) { NODE *p; p = block(REG, NIL, NIL, PTR|typ, 0, MKAP(LONG)); regno(p) = FPREG; return buildtree(PLUS, p, bcon(off/SZCHAR)); }
/* * 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"); }
static NODE * builtin_bswap32(const struct bitable *bt, NODE *a) { NODE *f, *t1, *t2, *t3, *t4; t1 = buildtree(LS, buildtree(AND, ccopy(a), bcon(255)), bcon(24)); t2 = buildtree(LS, buildtree(AND, ccopy(a), bcon(255 << 8)), bcon(8)); t3 = buildtree(AND, buildtree(RS, ccopy(a), bcon(8)), bcon(255 << 8)); t4 = buildtree(AND, buildtree(RS, a, bcon(24)), bcon(255)); f = buildtree(OR, buildtree(OR, t1, t2), buildtree(OR, t3, t4)); return f; }
/* 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; }
/* * Called with a function call with arguments as argument. * This is done early in buildtree() and only done once. * Returns p. */ NODE * funcode(NODE *p) { NODE *l, *r; TWORD t; int i; nsse = ngpr = nrsp = 0; /* Check if hidden arg needed */ /* If so, add it in pass2 */ if ((l = p->n_left)->n_type == INCREF(FTN)+STRTY || l->n_type == INCREF(FTN)+UNIONTY) { int ssz = tsize(BTYPE(l->n_type), l->n_df, l->n_ap); if (ssz > 2*SZLONG) ngpr++; } /* Convert just regs to assign insn's */ p->n_right = argput(p->n_right); /* Must sort arglist so that STASG ends up first */ /* This avoids registers being clobbered */ while (argsort(p->n_right)) ; /* Check if there are varargs */ if (nsse || l->n_df == NULL || l->n_df->dfun == NULL) { ; /* Need RAX */ } else { union arglist *al = l->n_df->dfun; for (; al->type != TELLIPSIS; al++) { if ((t = al->type) == TNULL) return p; /* No need */ if (ISSOU(BTYPE(t))) al++; for (i = 0; t > BTMASK; t = DECREF(t)) if (ISARY(t) || ISFTN(t)) i++; if (i) al++; } } /* Always emit number of SSE regs used */ l = movtoreg(bcon(nsse), RAX); if (p->n_right->n_op != CM) { p->n_right = block(CM, l, p->n_right, INT, 0, 0); } else { for (r = p->n_right; r->n_left->n_op == CM; r = r->n_left) ; r->n_left = block(CM, l, r->n_left, INT, 0, 0); } return p; }
/* * Sanitycheck "new" keyword. */ NODE * cxx_new(NODE *p) { NODE *q = p; NODE *t1 = bcon(1); int nw = NM_NEW; while (p->n_op == LB) { nw = NM_NWA; t1 = buildtree(MUL, t1, eve(p->n_right)); p->n_right = bcon(0); p = p->n_left; } if (p->n_op != TYPE) uerror("new used illegally"); t1 = buildtree(MUL, t1, xbcon(tsize(p->n_type, p->n_df, p->n_ap)/SZCHAR, NULL, INTPTR)); tfree(q); return callftn(decoratename(NULL, nw), t1, NULL); }
/* called from moveargs() */ static NODE * movearg_64bit(NODE *p, int *regp) { int reg = *regp; NODE *q, *r; #if ALLONGLONG == 64 /* alignment */ ++reg; reg &= ~1; *regp = reg; #endif if (reg > R3) { q = pusharg(p, regp); } else if (reg == R3) { /* half in and half out of the registers */ r = tcopy(p); if (!features(FEATURE_BIGENDIAN)) { q = block(SCONV, p, NIL, INT, 0, 0); q = movearg_32bit(q, regp); /* little-endian */ r = buildtree(RS, r, bcon(32)); r = block(SCONV, r, NIL, INT, 0, 0); r = pusharg(r, regp); /* little-endian */ } else { q = buildtree(RS, p, bcon(32)); q = block(SCONV, q, NIL, INT, 0, 0); q = movearg_32bit(q, regp); /* big-endian */ r = block(SCONV, r, NIL, INT, 0, 0); r = pusharg(r, regp); /* big-endian */ } q = straighten(block(CM, q, r, p->n_type, p->n_df, p->n_ap)); } else { q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_ap); regno(q) = R0R1 + (reg - R0); q = buildtree(ASSIGN, q, p); *regp = reg + 2; } return q; }