/* subtree - construct tree for l - r */ static Tree subtree(int op, Tree l, Tree r) { long n; 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) && !isfunc(l->type->type) && isint(r->type)) { ty = unqual(l->type); n = unqual(ty->type)->size; if (n == 0) error("unknown size for type `%t'\n", ty->type); r = cast(r, promote(r->type)); if (n > 1) r = multree(MUL, cnsttree(signedptr, n), r); if (isunsigned(r->type)) r = cast(r, unsignedptr); else r = cast(r, signedptr); return simplify(SUB+P, ty, l, r); } else if (compatible(l->type, r->type)) { ty = unqual(l->type); n = unqual(ty->type)->size; if (n == 0) error("unknown size for type `%t'\n", ty->type); l = simplify(SUB+U, unsignedptr, cast(l, unsignedptr), cast(r, unsignedptr)); return simplify(DIV+I, longtype, cast(l, longtype), cnsttree(longtype, n)); } else typeerror(op, l, r); return simplify(op, 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); }
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); }
BOOLEAN fittedConst(TYPE *tp, EXPRESSION *exp) { int n; if (!isint(tp) || !isintconst(exp)) return FALSE; n = getSize(basetype(tp)->type); switch (n) { case 8: if (isunsigned(tp)) { if (exp->v.i < 0 || exp->v.i > 255) return FALSE; } else { if (exp->v.i < - 128 || exp->v.i > 127) return FALSE; } break; case 16: if (isunsigned(tp)) { if (exp->v.i < 0 || exp->v.i > 65535) return FALSE; } else { if (exp->v.i < - 32768 || exp->v.i > 32767) return FALSE; } break; default: return TRUE; } }
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 {
void swcode(Swtch swp, int b[], int lb, int ub) { int hilab, lolab, l, u, k = (lb + ub)/2; long *v = swp->values; if (k > lb && k < ub) { lolab = genlabel(1); hilab = genlabel(1); } else if (k > lb) { lolab = genlabel(1); hilab = swp->deflab->u.l.label; } else if (k < ub) { lolab = swp->deflab->u.l.label; hilab = genlabel(1); } else lolab = hilab = swp->deflab->u.l.label; l = b[k]; u = b[k+1] - 1; if (u - l + 1 <= 3) { int i; for (i = l; i <= u; i++) cmp(EQ, swp->sym, v[i], swp->labels[i]->u.l.label); if (k > lb && k < ub) cmp(GT, swp->sym, v[u], hilab); else if (k > lb) cmp(GT, swp->sym, v[u], hilab); else if (k < ub) cmp(LT, swp->sym, v[l], lolab); else assert(lolab == hilab), branch(lolab); walk(NULL, 0, 0); } else { Tree e; Type ty = signedint(swp->sym->type); Symbol table = genident(STATIC, array(voidptype, u - l + 1, 0), GLOBAL); (*IR->defsymbol)(table); if (!isunsigned(swp->sym->type) || v[l] != 0) cmp(LT, swp->sym, v[l], lolab); cmp(GT, swp->sym, v[u], hilab); e = (*optree['-'])(SUB, cast(idtree(swp->sym), ty), cnsttree(ty, v[l])); if (e->type->size < unsignedptr->size) e = cast(e, unsignedlong); walk(tree(JUMP, voidtype, rvalue((*optree['+'])(ADD, pointer(idtree(table)), e)), NULL), 0, 0); code(Switch); codelist->u.swtch.table = table; codelist->u.swtch.sym = swp->sym; codelist->u.swtch.deflab = swp->deflab; codelist->u.swtch.size = u - l + 1; codelist->u.swtch.values = &v[l]; codelist->u.swtch.labels = &swp->labels[l]; if (v[u] - v[l] + 1 >= 10000) warning("switch generates a huge table\n"); } if (k > lb) { assert(lolab != swp->deflab->u.l.label); definelab(lolab); swcode(swp, b, lb, k - 1); } if (k < ub) { assert(hilab != swp->deflab->u.l.label); definelab(hilab); swcode(swp, b, k + 1, ub); } }