void retcode(Tree p) { Type ty; if (p == NULL) { if (events.returns) apply(events.returns, cfunc, NULL); return; } p = pointer(p); ty = assign(freturn(cfunc->type), p); if (ty == NULL) { error("illegal return type; found `%t' expected `%t'\n", p->type, freturn(cfunc->type)); return; } p = cast(p, ty); if (retv) { if (iscallb(p)) p = tree(RIGHT, p->type, tree(CALL+B, p->type, p->kids[0]->kids[0], idtree(retv)), rvalue(idtree(retv))); else { Type ty = retv->type->type; assert(isstruct(ty)); if (ty->u.sym->u.s.cfields) { ty->u.sym->u.s.cfields = 0; p = asgntree(ASGN, rvalue(idtree(retv)), p); ty->u.sym->u.s.cfields = 1; } else p = asgntree(ASGN, rvalue(idtree(retv)), p); } walk(p, 0, 0); if (events.returns) apply(events.returns, cfunc, rvalue(idtree(retv))); return; } if (events.returns) { Symbol t1 = genident(AUTO, p->type, level); addlocal(t1); walk(asgn(t1, p), 0, 0); apply(events.returns, cfunc, idtree(t1)); p = idtree(t1); } if (!isfloat(p->type)) p = cast(p, promote(p->type)); if (isptr(p->type)) { Symbol q = localaddr(p); if (q && (q->computed || q->generated)) warning("pointer to a %s is an illegal return value\n", q->scope == PARAM ? "parameter" : "local"); else if (q) warning("pointer to %s `%s' is an illegal return value\n", q->scope == PARAM ? "parameter" : "local", q->name); } walk(tree(mkop(RET,p->type), p->type, p, NULL), 0, 0); }
Tree asgntree(int op, Tree l, Tree r) { Type aty, ty; r = pointer(r); ty = assign(l->type, r); if (ty) r = cast(r, ty); else { typeerror(ASGN, l, r); if (r->type == voidtype) r = retype(r, inttype); ty = r->type; } if (l->op != FIELD) l = lvalue(l); aty = l->type; if (isptr(aty)) aty = unqual(aty)->type; if (isconst(aty) || (isstruct(aty) && unqual(aty)->u.sym->u.s.cfields)) { if (isaddrop(l->op) && !l->u.sym->computed && !l->u.sym->generated) error("assignment to const identifier `%s'\n", l->u.sym->name); else error("assignment to const location\n"); } if (l->op == FIELD) { long n = 8 * l->u.field->type->size - fieldsize(l->u.field); if (n > 0 && isunsigned(l->u.field->type)) r = bittree(BAND, r, cnsttree(r->type, (unsigned long)fieldmask(l->u.field))); else if (n > 0) { if (r->op == CNST + I) { n = r->u.v.i; if (n & (1 << (fieldsize(l->u.field) - 1))) n |= ~0UL << fieldsize(l->u.field); r = cnsttree(r->type, n); } else r = shtree(RSH, shtree(LSH, r, cnsttree(inttype, n)), cnsttree(inttype, n)); } } if (isstruct(ty) && isaddrop(l->op) && iscallb(r)) return tree(RIGHT, ty, tree(CALL + B, ty, r->kids[0]->kids[0], l), idtree(l->u.sym)); return tree(mkop(op, ty), ty, l, r); }
Tree call(Tree f, Type fty, Coordinate src) { int n = 0; Tree args = NULL, r = NULL, e; Type *proto, rty = unqual(freturn(fty)); Symbol t3 = NULL; if (fty->u.f.oldstyle) proto = NULL; else proto = fty->u.f.proto; if (hascall(f)) r = f; if (isstruct(rty)) { t3 = temporary(AUTO, unqual(rty)); if (rty->size == 0) error("illegal use of incomplete type `%t'\n", rty); } if (t != ')') for (;;) { Tree q = pointer(expr1(0)); if (proto && *proto && *proto != voidtype) { Type aty; q = value(q); aty = assign(*proto, q); if (aty) q = cast(q, aty); else error("type error in argument %d to %s; found `%t' expected `%t'\n", n + 1, funcname(f), q->type, *proto); if ((isint(q->type) || isenum(q->type)) && q->type->size != inttype->size) q = cast(q, promote(q->type)); ++proto; } else { if (!fty->u.f.oldstyle && *proto == NULL) error("too many arguments to %s\n", funcname(f)); q = value(q); if (isarray(q->type) || q->type->size == 0) error("type error in argument %d to %s; `%t' is illegal\n", n + 1, funcname(f), q->type); else q = cast(q, promote(q->type)); } if (!IR->wants_argb && isstruct(q->type)) if (iscallb(q)) q = addrof(q); else { Symbol t1 = temporary(AUTO, unqual(q->type)); q = asgn(t1, q); q = tree(RIGHT, ptr(t1->type), root(q), lvalue(idtree(t1))); } if (q->type->size == 0) q->type = inttype; if (hascall(q)) r = r ? tree(RIGHT, voidtype, r, q) : q; args = tree(mkop(ARG, q->type), q->type, q, args); n++; if (Aflag >= 2 && n == 32) warning("more than 31 arguments in a call to %s\n", funcname(f)); if (t != ',') break; t = gettok(); } expect(')'); if (proto && *proto && *proto != voidtype) error("insufficient number of arguments to %s\n", funcname(f)); if (r) args = tree(RIGHT, voidtype, r, args); e = calltree(f, rty, args, t3); if (events.calls) apply(events.calls, &src, &e); return e; }