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 cnsttree(Type ty, ...) { Tree p = tree(mkop(CNST,ty), ty, NULL, NULL); va_list ap; va_start(ap, ty); switch (ty->op) { case INT: p->u.v.i = va_arg(ap, long); break; case UNSIGNED:p->u.v.u = va_arg(ap, unsigned long)&ones(8*ty->size); break; case FLOAT: p->u.v.d = va_arg(ap, long double); break; case POINTER: p->u.v.p = va_arg(ap, void *); break; default: assert(0); } va_end(ap); return p; }
Tree eqtree(int op, Tree l, Tree r) { Type xty = unqual(l->type), yty = unqual(r->type); if (isptr(xty) && isnullptr(r) || isptr(xty) && !isfunc(xty->type) && isvoidptr(yty) || (isptr(xty) && isptr(yty) && eqtype(unqual(xty->type), unqual(yty->type), 1))) { Type ty = unsignedptr; l = cast(l, ty); r = cast(r, ty); return simplify(mkop(op,ty), inttype, l, r); } if (isptr(yty) && isnullptr(l) || isptr(yty) && !isfunc(yty->type) && isvoidptr(xty)) return eqtree(op, r, l); return cmptree(op, l, r); }
static Tree cmptree(int op, Tree l, Tree r) { Type ty; if (isarith(l->type) && isarith(r->type)) { ty = binary(l->type, r->type); l = cast(l, ty); r = cast(r, ty); } else if (compatible(l->type, r->type)) { ty = unsignedptr; l = cast(l, ty); r = cast(r, ty); } else { ty = unsignedtype; typeerror(op, l, r); } return simplify(mkop(op,ty), inttype, l, r); }
Tree vcall(Symbol func, Type ty, ...) { va_list ap; Tree args = NULL, e, f = pointer(idtree(func)), r = NULL; assert(isfunc(func->type)); if (ty == NULL) ty = freturn(func->type); va_start(ap, ty); while ((e = va_arg(ap, Tree)) != NULL) { if (hascall(e)) r = r == NULL ? e : tree(RIGHT, voidtype, r, e); args = tree(mkop(ARG, e->type), e->type, e, args); } va_end(ap); if (r != NULL) args = tree(RIGHT, voidtype, r, args); return calltree(f, ty, args, NULL); }
static void asmstmt(int lab, Swtch swp, int lev) { //wjr jan 31 43 lines char *asmi, *ireg, *oreg, *symn; Tree p; t = gettok(); expect('('); definept(NULL); if (t != SCON) { error("expecting string constant\n"); return; } asmi = strdup(tsym->u.c.v.p); /*t = gettok(); expect(':'); if (t != SCON) { error("expecting string constant\n"); return; } ireg = strdup(tsym->u.c.v.p); t = gettok(); expect(':'); if (t != SCON) { error("expecting string constant\n"); return; } oreg = strdup(tsym->u.c.v.p);*/ t = gettok(); expect(')'); expect(';'); symn = (char *) malloc(strlen(asmi) /*+ strlen(ireg) + strlen(oreg)*/ +4); sprintf(symn, "%s", asmi);// was sprintf(symn, "%s:%s:%s", asmi, ireg, oreg); free(asmi); /* free(ireg); free(oreg);*/ p = tree(mkop(IASM, voidtype), voidtype, NULL, NULL); p->u.v.p = symn; listnodes(p, 0, 0); }
Tree calltree(Tree f, Type ty, Tree args, Symbol t3) { Tree p; if (args) f = tree(RIGHT, f->type, args, f); if (isstruct(ty)) assert(t3), p = tree(RIGHT, ty, tree(CALL+B, ty, f, addrof(idtree(t3))), idtree(t3)); else { Type rty = ty; if (isenum(ty)) rty = unqual(ty)->type; if (!isfloat(rty)) rty = promote(rty); p = tree(mkop(CALL, rty), rty, f, NULL); if (isptr(ty) || p->type->size > ty->size) p = cast(p, ty); } return p; }
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; }
/* tracevalue - append format and argument to print the value of e */ static void tracevalue(Tree e, int lev) { Type ty = unqual(e->type); switch (ty->op) { case INT: if (ty == chartype || ty == signedchar) appendstr("'\\x%02x'"); else if (ty == longtype) appendstr("0x%ld"); else appendstr("0x%d"); break; case UNSIGNED: if (ty == chartype || ty == unsignedchar) appendstr("'\\x%02x'"); else if (ty == unsignedlong) appendstr("0x%lx"); else appendstr("0x%x"); break; case FLOAT: if (ty == longdouble) appendstr("%Lg"); else appendstr("%g"); break; case POINTER: if (unqual(ty->type) == chartype || unqual(ty->type) == signedchar || unqual(ty->type) == unsignedchar) { static Symbol null; if (null == NULL) null = mkstr("(null)"); tracevalue(cast(e, unsignedtype), lev + 1); appendstr(" \"%.30s\""); e = condtree(e, e, pointer(idtree(null->u.c.loc))); } else { appendstr("("); appendstr(typestring(ty, "")); appendstr(")0x%x"); } break; case STRUCT: { Field q; appendstr("("); appendstr(typestring(ty, "")); appendstr("){"); for (q = ty->u.sym->u.s.flist; q; q = q->link) { appendstr(q->name); appendstr("="); tracevalue(field(addrof(e), q->name), lev + 1); if (q->link) appendstr(","); } appendstr("}"); return; } case UNION: appendstr("("); appendstr(typestring(ty, "")); appendstr("){...}"); return; case ARRAY: if (lev && ty->type->size > 0) { int i; e = pointer(e); appendstr("{"); for (i = 0; i < ty->size/ty->type->size; i++) { Tree p = (*optree['+'])(ADD, e, consttree(i, inttype)); if (isptr(p->type) && isarray(p->type->type)) p = retype(p, p->type->type); else p = rvalue(p); if (i) appendstr(","); tracevalue(p, lev + 1); } appendstr("}"); } else appendstr(typestring(ty, "")); return; default: assert(0); } e = cast(e, promote(ty)); args = tree(mkop(ARG,e->type), e->type, e, args); }