Example #1
0
File: flatten.c Project: oridb/mc
static void
flattencond(Flattenctx *s, Node *n, Node *ltrue, Node *lfalse)
{
	Node **args;
	Node *v, *lnext;

	args = n->expr.args;
	switch (exprop(n)) {
	case Oland:
		lnext = genlbl(n->loc);
		flattencond(s, args[0], lnext, lfalse);
		append(s, lnext);
		flattencond(s, args[1], ltrue, lfalse);
		break;
	case Olor:
		lnext = genlbl(n->loc);
		flattencond(s, args[0], ltrue, lnext);
		append(s, lnext);
		flattencond(s, args[1], ltrue, lfalse);
		break;
	case Olnot:
		flattencond(s, args[0], lfalse, ltrue);
		break;
	default:
		v = rval(s, n);
		cjmp(s, v, ltrue, lfalse);
		break;
	}
}
Example #2
0
File: flatten.c Project: oridb/mc
static Node*
flattentern(Flattenctx *s, Node *n)
{
	Node *l1, *l2, *l3;
	Node *res, *t;

	l1 = genlbl(n->loc);
	l2 = genlbl(n->loc);
	l3 = genlbl(n->loc);

	res = temp(s, n);
	flattencond(s, n->expr.args[0], l1, l2);

	append(s, l1);
	t = assign(s, res, rval(s, n->expr.args[1]));
	append(s, t);
	jmp(s, l3);

	append(s, l2);
	t = assign(s, res, rval(s, n->expr.args[2]));
	append(s, t);

	append(s, l3);

	return res;
}
Example #3
0
static void simpmatch(Simp *s, Node *n)
{
    Node *end, *cur, *next; /* labels */
    Node *val, *tmp;
    Node *m;
    size_t i;

    end = genlbl();
    val = temp(s, n->matchstmt.val);
    tmp = rval(s, n->matchstmt.val, val);
    if (val != tmp)
        append(s, assign(s, val, tmp));
    for (i = 0; i < n->matchstmt.nmatches; i++) {
        m = n->matchstmt.matches[i];

        /* check pattern */
        cur = genlbl();
        next = genlbl();
        umatch(s, m->match.pat, val, val->expr.type, cur, next);

        /* do the action if it matches */
        append(s, cur);
        simp(s, m->match.block);
        jmp(s, end);
        append(s, next);
    }
    append(s, end);
}
Example #4
0
static void simpcond(Simp *s, Node *n, Node *ltrue, Node *lfalse)
{
    Node **args;
    Node *v, *lnext;

    args = n->expr.args;
    switch (exprop(n)) {
        case Oland:
            lnext = genlbl();
            simpcond(s, args[0], lnext, lfalse);
            append(s, lnext);
            simpcond(s, args[1], ltrue, lfalse);
            break;
        case Olor:
            lnext = genlbl();
            simpcond(s, args[0], ltrue, lnext);
            append(s, lnext);
            simpcond(s, args[1], ltrue, lfalse);
            break;
        case Olnot:
            simpcond(s, args[0], lfalse, ltrue);
            break;
        default:
            v = rval(s, n, NULL);
            cjmp(s, v, ltrue, lfalse);
            break;
    }
}
Example #5
0
/* init; while cond; body;; 
 *    => init
 *       jmp :cond
 *       :body
 *           ...body...
 *           ...step...
 *       :cond
 *           ...cond...
 *            cjmp (cond) :body :end
 *       :end
 */
static void simploop(Simp *s, Node *n)
{
    Node *lbody;
    Node *lend;
    Node *lcond;
    Node *lstep;

    lbody = genlbl();
    lcond = genlbl();
    lstep = genlbl();
    lend = genlbl();

    lappend(&s->loopstep, &s->nloopstep, lstep);
    lappend(&s->loopexit, &s->nloopexit, lend);

    simp(s, n->loopstmt.init);  /* init */
    jmp(s, lcond);              /* goto test */
    simp(s, lbody);             /* body lbl */
    simp(s, n->loopstmt.body);  /* body */
    simp(s, lstep);             /* test lbl */
    simp(s, n->loopstmt.step);  /* step */
    simp(s, lcond);             /* test lbl */
    simpcond(s, n->loopstmt.cond, lbody, lend);    /* repeat? */
    simp(s, lend);              /* exit */

    s->nloopstep--;
    s->nloopexit--;
}
Example #6
0
/* if foo; bar; else baz;;
 *      => cjmp (foo) :bar :baz */
static void simpif(Simp *s, Node *n, Node *exit)
{
    Node *l1, *l2, *l3;
    Node *iftrue, *iffalse;

    l1 = genlbl();
    l2 = genlbl();
    if (exit)
        l3 = exit;
    else
        l3 = genlbl();

    iftrue = n->ifstmt.iftrue;
    iffalse = n->ifstmt.iffalse;

    simpcond(s, n->ifstmt.cond, l1, l2);
    simp(s, l1);
    simp(s, iftrue);
    jmp(s, l3);
    simp(s, l2);
    /* because lots of bunched up end labels are ugly,
     * coalesce them by handling 'elif'-like constructs
     * separately */
    if (iffalse && iffalse->type == Nifstmt) {
        simpif(s, iffalse, exit);
    } else {
        simp(s, iffalse);
        jmp(s, l3);
    }

    if (!exit)
        simp(s, l3);
}
Example #7
0
/* 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;
}
Example #8
0
/* pat; seq; 
 *      body;;
 *
 * =>
 *      .pseudo = seqinit
 *      jmp :cond
 *      :body
 *           ...body...
 *      :step
 *           ...step...
 *      :cond
 *           ...cond...
 *           cjmp (cond) :match :end
 *      :match
 *           ...match...
 *           cjmp (match) :body :step
 *      :end
 */
static void simpiter(Simp *s, Node *n)
{
    Node *lbody, *lstep, *lcond, *lmatch, *lend;
    Node *idx, *len, *dcl, *seq, *val, *done;
    Node *zero;

    lbody = genlbl();
    lstep = genlbl();
    lcond = genlbl();
    lmatch = genlbl();
    lend = genlbl();

    lappend(&s->loopstep, &s->nloopstep, lstep);
    lappend(&s->loopexit, &s->nloopexit, lend);

    zero = mkintlit(n->line, 0);
    zero->expr.type = tyintptr;

    seq = rval(s, n->iterstmt.seq, NULL);
    idx = gentemp(s, n, tyintptr, &dcl);
    declarelocal(s, dcl);

    /* setup */
    append(s, assign(s, idx, zero));
    jmp(s, lcond);
    simp(s, lbody);
    /* body */
    simp(s, n->iterstmt.body);
    /* step */
    simp(s, lstep);
    simp(s, assign(s, idx, addk(idx, 1)));
    /* condition */
    simp(s, lcond);
    len = seqlen(s, seq, tyintptr);
    done = mkexpr(n->line, Olt, idx, len, NULL);
    cjmp(s, done, lmatch, lend);
    simp(s, lmatch);
    val = load(idxaddr(s, seq, idx));
    umatch(s, n->iterstmt.elt, val, val->expr.type, lbody, lstep);
    simp(s, lend);

    s->nloopstep--;
    s->nloopexit--;
}
Example #9
0
File: flatten.c Project: oridb/mc
/* flatten
 *      a || b
 * to
 *      if a || b
 *              t = true
 *      else
 *              t = false
 *      ;;
 */
static Node *
flattenlazy(Flattenctx *s, Node *n)
{
	Node *r, *t, *u;
	Node *ltrue, *lfalse, *ldone;

	/* set up temps and labels */
	r = temp(s, n);
	ltrue = genlbl(n->loc);
	lfalse = genlbl(n->loc);
	ldone = genlbl(n->loc);

	/* flatten the conditional */
	flattencond(s, n, ltrue, lfalse);


	/* if true */
	append(s, ltrue);
	u = mkexpr(n->loc, Olit, mkbool(n->loc, 1), NULL);
	u->expr.type = mktype(n->loc, Tybool);
	t = asn(r, u);
	append(s, t);
	jmp(s, ldone);

	/* if false */
	append(s, lfalse);
	u = mkexpr(n->loc, Olit, mkbool(n->loc, 0), NULL);
	u->expr.type = mktype(n->loc, Tybool);
	t = asn(r, u);
	append(s, t);
	jmp(s, ldone);

	/* finish */
	append(s, ldone);
	return r;
}
Example #10
0
static void umatch(Simp *s, Node *pat, Node *val, Type *t, Node *iftrue, Node *iffalse)
{
    Node *v, *x, *y;
    Node *deeper, *next;
    Node **patarg;
    Ucon *uc;
    size_t i;
    size_t off;

    assert(pat->type == Nexpr);
    t = tybase(t);
    if (exprop(pat) == Ovar && !decls[pat->expr.did]->decl.isconst) {
        v = assign(s, pat, val);
        append(s, v);
        jmp(s, iftrue);
        return;
    }
    switch (t->type) {
        /* Never supported */
        case Tyvoid: case Tybad: case Tyvalist: case Tyvar:
        case Typaram: case Tyunres: case Tyname: case Ntypes:
        /* Should never show up */
        case Tyslice:
            die("Unsupported type for compare");
            break;
        case Tybool: case Tychar: case Tybyte:
        case Tyint8: case Tyint16: case Tyint32: case Tyint:
        case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint:
        case Tyint64: case Tyuint64: case Tylong:  case Tyulong:
        case Tyfloat32: case Tyfloat64:
        case Typtr: case Tyfunc:
            v = mkexpr(pat->line, Oeq, pat, val, NULL);
            v->expr.type = mktype(pat->line, Tybool);
            cjmp(s, v, iftrue, iffalse);
            break;
        /* We got lucky. The structure of tuple, array, and struct literals
         * is the same, so long as we don't inspect the type, so we can
         * share the code*/
        case Tystruct: case Tytuple: case Tyarray: 
            patarg = pat->expr.args;
            off = 0;
            for (i = 0; i < pat->expr.nargs; i++) {
                off = tyalign(off, size(patarg[i]));
                next = genlbl();
                v = load(addk(addr(s, val, exprtype(patarg[i])), off));
                umatch(s, patarg[i], v, exprtype(patarg[i]), next, iffalse);
                append(s, next);
                off += size(patarg[i]);
            }
            jmp(s, iftrue);
            break;
        case Tyunion:
            uc = finducon(pat);
            if (!uc)
                uc = finducon(val);

            deeper = genlbl();

            x = uconid(s, pat);
            y = uconid(s, val);
            v = mkexpr(pat->line, Oeq, x, y, NULL);
            v->expr.type = tyintptr;
            cjmp(s, v, deeper, iffalse);
            append(s, deeper);
            if (uc->etype) {
                pat = patval(s, pat, uc->etype);
                val = patval(s, val, uc->etype);
                umatch(s, pat, val, uc->etype, iftrue, iffalse);
            }
            break;
    }
}