/* * 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; }
static NODE * builtin_cir(const struct bitable *bt, NODE *a) { char *n; if (a == NIL || a->n_op == CM) { uerror("wrong argument count to %s", bt->name); return bcon(0); } n = addname(bt->name[1] == 'r' ? "__real" : "__imag"); return cast(structref(a, DOT, n), bt->rt, 0); }
NODE * amd64_builtin_stdarg_start(const struct bitable *bt, NODE *a) { NODE *p, *r; /* use the values from the function header */ p = a->n_left; r = buildtree(ASSIGN, structref(ccopy(p), STREF, reg_save_area), mkstkref(-rsaoff, VOID)); r = buildtree(COMOP, r, buildtree(ASSIGN, structref(ccopy(p), STREF, overflow_arg_area), mkstkref(thisrsp, VOID))); r = buildtree(COMOP, r, buildtree(ASSIGN, structref(ccopy(p), STREF, gp_offset), bcon(thisgpr*(SZLONG/SZCHAR)))); r = buildtree(COMOP, r, buildtree(ASSIGN, structref(ccopy(p), STREF, fp_offset), bcon(thissse*(SZDOUBLE*2/SZCHAR)+48))); tfree(a); return r; }
/* * Check if we may have to do a cast to/from TI. */ NODE * gcc_eval_ticast(int op, NODE *p1, NODE *p2) { struct attr *a1, *a2; int t; a2 = NULL; /* XXX flow analysis */ if ((a1 = isti(p1)) == NULL && (a2 = isti(p2)) == NULL) return NIL; if (op == RETURN) p1 = p1tcopy(p1); if (a1 == NULL) { if (a2 == NULL) cerror("gcc_eval_ticast error"); switch (p1->n_type) { case LDOUBLE: p2 = doacall(floatuntixfsp, nametree(floatuntixfsp), p2); tfree(p1); break; case ULONG: case LONG: p2 = cast(structref(p2, DOT, loti), p1->n_type, 0); tfree(p1); break; case VOID: return NIL; default: uerror("gcc_eval_ticast: %d", p1->n_type); } return p2; } /* p2 can be anything, but we must cast it to p1 */ t = a1->iarg(1); if (p2->n_type == STRTY && (a2 = attr_find(p2->n_ap, GCC_ATYP_MODE)) && strcmp(a2->sarg(0), TISTR) == 0) { /* Already TI, just add extra mode bits */ a2 = attr_new(GCC_ATYP_MODE, 3); a2->sarg(0) = TISTR; a2->iarg(1) = t; p2->n_ap = attr_add(p2->n_ap, a2); } else { p2 = ticast(p2, t); } tfree(p1); return p2; }
/* * Ensure that a 128-bit assign succeeds. * If left is not TI, make right not TI, * else if left _is_ TI, make right TI, * else do nothing. */ static NODE * timodeassign(NODE *p1, NODE *p2) { struct attr *a1, *a2; a1 = isti(p1); a2 = isti(p2); if (a1 && a2 == NULL) { p2 = ticast(p2, a1->iarg(1)); } else if (a1 == NULL && a2) { if (ISFTY(p1->n_type)) cerror("cannot TI float convert"); p2 = structref(p2, DOT, loti); } return buildtree(ASSIGN, p1, p2); }
/* * Watch out for references to static members. */ NODE * cxxstructref(NODE *p, int f, char *n) { struct symtab *sp = strmemb(p->n_ap); if (sp == NULL) cerror("ref to unknown struct"); sp = sfind(n, sp); while (sp != NULL) { if (ISFTN(sp->stype) == 0) { if (sp->sclass == STATIC || sp->sclass == USTATIC) { tfree(p); return nametree(sp); } break; } sp = sfind(n, sp->snext); } return structref(p, f, n); }