/* simplifies * a || b * to * if a || b * t = true * else * t = false * ;; */ static Node *simplazy(Simp *s, Node *n) { Node *r, *t, *u; Node *ltrue, *lfalse, *ldone; /* set up temps and labels */ r = temp(s, n); ltrue = genlbl(); lfalse = genlbl(); ldone = genlbl(); /* simp the conditional */ simpcond(s, n, ltrue, lfalse); /* if true */ append(s, ltrue); u = mkexpr(n->line, Olit, mkbool(n->line, 1), NULL); u->expr.type = mktype(n->line, Tybool); t = set(r, u); append(s, t); jmp(s, ldone); /* if false */ append(s, lfalse); u = mkexpr(n->line, Olit, mkbool(n->line, 0), NULL); u->expr.type = mktype(n->line, Tybool); t = set(r, u); append(s, t); jmp(s, ldone); /* finish */ append(s, ldone); return r; }
LOCAL void putct1(bigptr q, bigptr lp, bigptr cp, int *ip) { NODE *p; int i; struct bigblock *lp1, *cp1; if(q->tag==TEXPR && q->b_expr.opcode==OPCONCAT) { putct1(q->b_expr.leftp, lp, cp, ip); putct1(q->b_expr.rightp, lp, cp , ip); frexpr(q->vleng); ckfree(q); } else { i = (*ip)++; lp1 = cpexpr(lp); lp1->b_addr.memoffset = mkexpr(OPPLUS, lp1->b_addr.memoffset, MKICON(i*FSZLENG)); cp1 = cpexpr(cp); cp1->b_addr.memoffset = mkexpr(OPPLUS, cp1->b_addr.memoffset, MKICON(i*FSZADDR)); p = putassign( lp1, cpexpr(q->vleng) ); sendp2(p); p = putassign( cp1, addrof(putch1(q)) ); sendp2(p); } }
static Node * comparecomplex(Flattenctx *s, Node *n, Op op) { Type *ty; Node *l, *r, *e; /* special case: unions with nullary constructors can be compared easily. */ ty = tybase(exprtype(n->expr.args[0])); if (ty->type == Tyunion && isenum(ty)) { l = mkexpr(n->loc, Outag, rval(s, n->expr.args[0]), NULL); r = mkexpr(n->loc, Outag, rval(s, n->expr.args[1]), NULL); l->expr.type = mktype(n->loc, Tyuint32); r->expr.type = mktype(n->loc, Tyuint32); if (op == Oeq) e = mkexpr(n->loc, Oueq, l, r, NULL); else if (op == One) e = mkexpr(n->loc, Oune, l, r, NULL); else fatal(n, "unsupported operator %s for enum union", opstr[op]); e->expr.type = mktype(n->loc, Tybool); return e; } fatal(n, "cannot compare values of type %s for equality\n", tystr(exprtype(n->expr.args[0]))); return NULL; }
static struct expr * parse_inner() { if (token("prune")) { struct expr *e = mkexpr(EXPR_PRUNE); return e; } else if (token("print")) { struct expr *e = mkexpr(EXPR_PRINT); return e; } else if (token("!")) { struct expr *e = parse_cmp(); struct expr *not = mkexpr(EXPR_NOT); not->a.expr = e; return not; } else if (token("(")) { struct expr *e = parse_or(); if (token(")")) return e; parse_error("missing ) at '%.15s'", pos); return 0; } else { parse_error("unknown expression at '%.15s'", pos); return 0; } }
Node * mksliceexpr(Srcloc loc, Node *sl, Node *base, Node *off) { if (!base) base = mkintlit(loc, 0); if (!off) off = mkexpr(loc, Omemb, sl, mkname(loc, "len"), NULL); return mkexpr(loc, Oslice, sl, base, off, NULL); }
/* Arithmetic IF */ void prarif(bigptr p, int neg, int zer, int pos) { bigptr x1 = fmktemp(p->vtype, NULL); putexpr(mkexpr(OPASSIGN, cpexpr(x1), p)); putif(mkexpr(OPGE, cpexpr(x1), MKICON(0)), neg); putif(mkexpr(OPLE, x1, MKICON(0)), pos); putgoto(zer); }
static Node *ptrsized(Simp *s, Node *v) { if (size(v) == Ptrsz) return v; else if (size(v) < Ptrsz) v = mkexpr(v->line, Ozwiden, v, NULL); else if (size(v) > Ptrsz) v = mkexpr(v->line, Otrunc, v, NULL); v->expr.type = tyintptr; return v; }
static Node *genmatch(Srcloc loc, Dtree *dt) { Node *lastcmp, *cmp, *eq, *pat; size_t i; dtdumpnode(dt, stdout, 0, 0); lastcmp = NULL; cmp = NULL; pat = NULL; if (dt->nsub == 0) return dt->act; for (i = 0; i < dt->nsub; i++) { eq = mkexpr(loc, Oeq, dt->load[i], dt->val[i], NULL); cmp = mkifstmt(loc, eq, genmatch(loc, dt->sub[i]), NULL); if (!pat) pat = cmp; if (lastcmp) lastcmp->ifstmt.iffalse = cmp; else lastcmp = cmp; lastcmp = cmp; } if (dt->any) lastcmp->ifstmt.iffalse = genmatch(loc, dt->any); return pat; }
static void cjmp(Simp *s, Node *cond, Node *iftrue, Node *iffalse) { Node *jmp; jmp = mkexpr(cond->line, Ocjmp, cond, iftrue, iffalse, NULL); append(s, jmp); }
static struct expr * parse_timecmp() { enum prop prop; enum op op; if (token("atime")) prop = PROP_ATIME; else if (token("ctime")) prop = PROP_CTIME; else if (token("mtime")) prop = PROP_MTIME; else if (token("date")) prop = PROP_DATE; else return parse_cmp(); op = parse_op(); if (!op) parse_error("invalid comparison at '%.15s'", pos); int64_t n; if (parse_num(&n) || parse_dur(&n)) { struct expr *e = mkexpr(op); e->a.prop = prop; e->b.num = n; return e; } return 0; }
static Node *assign(Simp *s, Node *lhs, Node *rhs) { Node *t, *u, *v, *r; if (exprop(lhs) == Otup) { r = destructure(s, lhs, rhs); } else { t = lval(s, lhs); u = rval(s, rhs, t); /* if we stored the result into t, rval() should return that, * so we know our work is done. */ if (u == t) { r = t; } else if (stacknode(lhs)) { t = addr(s, t, exprtype(lhs)); u = addr(s, u, exprtype(lhs)); v = disp(lhs->line, size(lhs)); r = mkexpr(lhs->line, Oblit, t, u, v, NULL); } else { r = set(t, u); } } return r; }
/* Takes a tuple and binds the i'th element of it to the * i'th name on the rhs of the assignment. */ static Node *destructure(Simp *s, Node *lhs, Node *rhs) { Node *plv, *prv, *lv, *sz, *stor, **args; size_t off, i; args = lhs->expr.args; rhs = rval(s, rhs, NULL); off = 0; for (i = 0; i < lhs->expr.nargs; i++) { lv = lval(s, args[i]); off = tyalign(off, size(lv)); prv = add(addr(s, rhs, exprtype(args[i])), disp(rhs->line, off)); if (stacknode(args[i])) { sz = disp(lhs->line, size(lv)); plv = addr(s, lv, exprtype(lv)); stor = mkexpr(lhs->line, Oblit, plv, prv, sz, NULL); } else { stor = set(lv, load(prv)); } append(s, stor); off += size(lv); } return NULL; }
static Node *structmemb(Node *n, Node *name, Type *ty) { Node *elt; elt = mkexpr(n->loc, Omemb, n, name, NULL); elt->expr.type = ty; return elt; }
static Node *mul(Node *a, Node *b) { Node *n; n = mkexpr(a->line, Omul, a, b, NULL); n->expr.type = a->expr.type; return n; }
static Node *uvalue(Node *n, Type *ty) { Node *elt; elt = mkexpr(n->loc, Oudata, n, NULL); elt->expr.type = ty; return elt; }
static Node *sub(Node *a, Node *b) { Node *n; n = mkexpr(a->line, Osub, a, b, NULL); n->expr.type = a->expr.type; return n; }
Node * mkboollit(Srcloc loc, int val) { Node *e; e = mkexpr(loc, Olit, mkbool(loc, val), NULL); e->expr.type = mktype(loc, Tybool); return e; }
static IRAtom* assignNew ( IRSB* sb, IRExpr* e ) { IRTemp t; IRType ty = typeOfIRExpr(sb->tyenv, e); t = newIRTemp(sb->tyenv, ty); assign(sb, t, e); return mkexpr(t); }
static Node *add(Node *a, Node *b) { Node *n; assert(size(a) == size(b)); n = mkexpr(a->line, Oadd, a, b, NULL); n->expr.type = a->expr.type; return n; }
static Node *deref(Node *a) { Node *n; assert(a->expr.type->type == Typtr); n = mkexpr(a->line, Oderef, a, NULL); n->expr.type = base(a->expr.type); return n; }
static Node *val(int line, vlong val, Type *t) { Node *n; n = mkint(line, val); n = mkexpr(line, Olit, n, NULL); n->expr.type = t; return n; }
static void jmp(Flattenctx *s, Node *lbl) { Node *n; n = mkexpr(lbl->loc, Ojmp, lbl, NULL); n->expr.type = mktype(n->loc, Tyvoid); append(s, n); }
static void cjmp(Flattenctx *s, Node *cond, Node *iftrue, Node *iffalse) { Node *jmp; jmp = mkexpr(cond->loc, Ocjmp, cond, iftrue, iffalse, NULL); jmp->expr.type = mktype(cond->loc, Tyvoid); append(s, jmp); }
static Node * seqlen(Flattenctx *s, Node *n, Type *ty) { Node *r; if (!ty) ty = n->expr.type; if (exprtype(n)->type == Tyarray) { r = mkexpr(n->loc, Osllen, rval(s, n), NULL); r->expr.type = ty; } else if (exprtype(n)->type == Tyslice) { r = mkexpr(n->loc, Osllen, rval(s, n), NULL); r->expr.type = ty; } else { die("invalid seq type for len"); } return r; }
static Node * add(Node *a, Node *b) { Node *n; n = mkexpr(a->loc, Oadd, a, b, NULL); n->expr.type = a->expr.type; return n; }
static Node *val(Srcloc loc, vlong val, Type *t) { Node *l, *n; l = mkint(loc, val); n = mkexpr(loc, Olit, l, NULL); l->lit.type = t; n->expr.type = t; return n; }
static Node *set(Node *a, Node *b) { Node *n; assert(a != NULL && b != NULL); assert(exprop(a) == Ovar || exprop(a) == Oderef); n = mkexpr(a->line, Oset, a, b, NULL); n->expr.type = exprtype(a); return n; }
static Node *arrayelt(Node *n, size_t i) { Node *idx, *elt; idx = mkintlit(n->loc, i); idx->expr.type = mktype(n->loc, Tyuint64); elt = mkexpr(n->loc, Oidx, n, idx, NULL); elt->expr.type = tybase(exprtype(n))->sub[0]; return elt; }
static Node *intconvert(Simp *s, Node *from, Type *to, int issigned) { Node *r; size_t fromsz, tosz; fromsz = size(from); tosz = tysize(to); r = rval(s, from, NULL); if (fromsz > tosz) { r = mkexpr(from->line, Otrunc, r, NULL); } else if (tosz > fromsz) { if (issigned) r = mkexpr(from->line, Oswiden, r, NULL); else r = mkexpr(from->line, Ozwiden, r, NULL); } r->expr.type = to; return r; }
Inline(int fno, int type, struct Chain *args) #endif { register expptr q, t, t1; switch(fno) { case 8: /* real abs */ case 9: /* short int abs */ case 10: /* long int abs */ case 11: /* double precision abs */ if( addressable(q = (expptr) args->datap) ) { t = q; q = NULL; } else t = (expptr) mktmp(type,ENULL); t1 = mkexpr(type == TYREAL && forcedouble ? OPDABS : OPABS, cpexpr(t), ENULL); if(q) t1 = mkexpr(OPCOMMA, mkexpr(OPASSIGN, cpexpr(t),q), t1); frexpr(t); return(t1); case 26: /* dprod */ q = mkexpr(OPSTAR, mkconv(TYDREAL,(expptr)args->datap), (expptr)args->nextp->datap); return(q); case 27: /* len of character string */ q = (expptr) cpexpr(((tagptr)args->datap)->headblock.vleng); frexpr((expptr)args->datap); return(q); case 14: /* half-integer mod */ case 15: /* mod */ return mkexpr(OPMOD, (expptr) args->datap, (expptr) args->nextp->datap); } return(NULL); }