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); }
static Tree addtree(int op, Tree l, Tree r) { Type ty = inttype; if (isarith(l->type) && isarith(r->type)) { ty = binary(l->type, r->type); l = cast(l, ty); r = cast(r, ty); } else if (isptr(l->type) && isint(r->type)) return addtree(ADD, r, l); else if ( isptr(r->type) && isint(l->type) && !isfunc(r->type->type)) { long n; ty = unqual(r->type); n = unqual(ty->type)->size; if (n == 0) error("unknown size for type `%t'\n", ty->type); l = cast(l, promote(l->type)); if (n > 1) l = multree(MUL, cnsttree(signedptr, n), l); if (isunsigned(l->type)) l = cast(l, unsignedptr); else l = cast(l, signedptr); if (YYcheck && !isaddrop(r->op)) /* omit */ return nullcall(ty, YYcheck, r, l); /* omit */ return simplify(ADD, ty, l, r); } else typeerror(op, l, r); return simplify(op, ty, l, r); }
int iscallb(Tree e) { return e->op == RIGHT && e->kids[0] && e->kids[1] && e->kids[0]->op == CALL+B && e->kids[1]->op == INDIR+B && isaddrop(e->kids[1]->kids[0]->op) && e->kids[1]->kids[0]->u.sym->temporary; }
static void swstmt(int loop, int lab, int lev) { Tree e; struct swtch sw; Code head, tail; t = gettok(); expect('('); definept(NULL); e = expr(')'); if (!isint(e->type)) { error("illegal type `%t' in switch expression\n", e->type); e = retype(e, inttype); } e = cast(e, promote(e->type)); if (generic(e->op) == INDIR && isaddrop(e->kids[0]->op) && e->kids[0]->u.sym->type == e->type && !isvolatile(e->kids[0]->u.sym->type)) { sw.sym = e->kids[0]->u.sym; walk(NULL, 0, 0); } else { sw.sym = genident(REGISTER, e->type, level); addlocal(sw.sym); walk(asgn(sw.sym, e), 0, 0); } head = code(Switch); sw.lab = lab; sw.deflab = NULL; sw.ncases = 0; sw.size = SWSIZE; sw.values = newarray(SWSIZE, sizeof *sw.values, FUNC); sw.labels = newarray(SWSIZE, sizeof *sw.labels, FUNC); refinc /= 10.0; statement(loop, &sw, lev); if (sw.deflab == NULL) { sw.deflab = findlabel(lab); definelab(lab); if (sw.ncases == 0) warning("switch statement with no cases\n"); } if (findlabel(lab + 1)->ref) definelab(lab + 1); tail = codelist; codelist = head->prev; codelist->next = head->prev = NULL; if (sw.ncases > 0) swgen(&sw); branch(lab); head->next->prev = codelist; codelist->next = head->next; codelist = tail; }
Tree unary(void) { Tree p; switch (t) { case '*': t = gettok(); p = unary(); p = pointer(p); if (isptr(p->type) && (isfunc(p->type->type) || isarray(p->type->type))) p = retype(p, p->type->type); else { if (YYnull) p = nullcheck(p); p = rvalue(p); } break; case '&': t = gettok(); p = unary(); if (isarray(p->type) || isfunc(p->type)) p = retype(p, ptr(p->type)); else p = lvalue(p); if (isaddrop(p->op) && p->u.sym->sclass == REGISTER) error("invalid operand of unary &; `%s' is declared register\n", p->u.sym->name); else if (isaddrop(p->op)) p->u.sym->addressed = 1; break; case '+': t = gettok(); p = unary(); p = pointer(p); if (isarith(p->type)) p = cast(p, promote(p->type)); else typeerror(ADD, p, NULL); break; case '-': t = gettok(); p = unary(); p = pointer(p); if (isarith(p->type)) { Type ty = promote(p->type); p = cast(p, ty); if (isunsigned(ty)) { warning("unsigned operand of unary -\n"); p = simplify(ADD, ty, simplify(BCOM, ty, p, NULL), cnsttree(ty, 1UL)); } else p = simplify(NEG, ty, p, NULL); } else typeerror(SUB, p, NULL); break; case '~': t = gettok(); p = unary(); p = pointer(p); if (isint(p->type)) { Type ty = promote(p->type); p = simplify(BCOM, ty, cast(p, ty), NULL); } else typeerror(BCOM, p, NULL); break; case '!': t = gettok(); p = unary(); p = pointer(p); if (isscalar(p->type)) p = simplify(NOT, inttype, cond(p), NULL); else typeerror(NOT, p, NULL); break; case INCR: t = gettok(); p = unary(); p = incr(INCR, pointer(p), consttree(1, inttype)); break; case DECR: t = gettok(); p = unary(); p = incr(DECR, pointer(p), consttree(1, inttype)); break; case TYPECODE: case SIZEOF: { int op = t; Type ty; p = NULL; t = gettok(); if (t == '(') { t = gettok(); if (istypename(t, tsym)) { ty = typename(); expect(')'); } else { p = postfix(expr(')')); ty = p->type; } } else {