Beispiel #1
0
static Node *uconid(Simp *s, Node *n)
{
    Ucon *uc;

    if (exprop(n) != Oucon)
        return load(addr(s, n, mktype(n->line, Tyuint)));

    uc = finducon(n);
    return word(uc->line, uc->id);
}
Beispiel #2
0
static Dtree *addunion(Dtree *t, Node *pat, Node *val, Node ***cap, size_t *ncap)
{
    Node *elt, *tag, *id;
    int32_t t1, t2;
    Dtree *sub;
    Ucon *uc;
    size_t i;

    if (t->any)
        return t->any;
    uc = finducon(tybase(exprtype(pat)), pat->expr.args[0]);
    t2 = uc->id;
    /* if we have the value already... */
    sub = NULL;
    for (i = 0; i < t->nval; i++) {
        tag = t->val[i]->expr.args[0];
        t1 = tag->lit.intval;
        if (t1 == t2) {
            if (pat->expr.nargs > 1) {
                elt = uvalue(val, exprtype(pat->expr.args[1])); 
                return addpat(t->sub[i], pat->expr.args[1], elt, cap, ncap);
            } else {
                return t->sub[i];
            }
        }
    }

    /* otherwise create a new match */
    sub = mkdtree();
    sub->patexpr = pat;
    tag = mkexpr(pat->loc, Outag, val, NULL);
    tag->expr.type = mktype(pat->loc, Tyint32);

    id = mkintlit(pat->loc, uc->id);
    id->expr.type = mktype(pat->loc, Tyint32);

    lappend(&t->val, &t->nval, id);
    lappend(&t->sub, &t->nsub, sub);
    lappend(&t->load, &t->nload, tag);
    if (pat->expr.nargs == 2) {
        elt = uvalue(val, exprtype(pat->expr.args[1])); 
        sub = addpat(sub, pat->expr.args[1], elt, cap, ncap);
    }
    return sub;
}
Beispiel #3
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;
    }
}
Beispiel #4
0
Datei: fold.c Projekt: oridb/mc
Node *
fold(Node *n, int foldvar)
{
	Node **args, *r;
	Type *t;
	vlong a, b;
	Ucon *uc;
	size_t i;

	if (!n)
		return NULL;
	if (n->type != Nexpr)
		return n;

	r = NULL;
	args = n->expr.args;
	if (n->expr.idx)
		n->expr.idx = fold(n->expr.idx, foldvar);
	for (i = 0; i < n->expr.nargs; i++)
		args[i] = fold(args[i], foldvar);
	switch (exprop(n)) {
	case Outag:
		if (exprop(args[0]) != Oucon)
			break;
		uc = finducon(tybase(exprtype(args[0])), args[0]->expr.args[0]);
		r = val(n->loc, uc->id, exprtype(n));
		break;
	case Oudata:
		if (exprop(args[0]) != Oucon || args[0]->expr.nargs != 2)
			break;
		r = args[0]->expr.args[1];
		break;
	case Ovar:
		if (foldvar && issmallconst(decls[n->expr.did]))
			r = fold(decls[n->expr.did]->decl.init, foldvar);
		break;
	case Oadd:
		/* x + 0 = 0 */
		if (isintval(args[0], 0))
			r = args[1];
		if (isintval(args[1], 0))
			r = args[0];
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a + b, exprtype(n));
		break;
	case Osub:
		/* x - 0 = 0 */
		if (isintval(args[1], 0))
			r = args[0];
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, (uint64_t)a - b, exprtype(n));
		break;
	case Omul:
		/* 1 * x = x */
		if (isintval(args[0], 1))
			r = args[1];
		if (isintval(args[1], 1))
			r = args[0];
		/* 0 * x = 0 */
		if (isintval(args[0], 0))
			r = args[0];
		if (isintval(args[1], 0))
			r = args[1];
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a * b, exprtype(n));
		break;
	case Odiv:
		/* x/0 = error */
		if (isintval(args[1], 0))
			fatal(args[1], "division by zero");
		/* x/1 = x */
		if (isintval(args[1], 1))
			r = args[0];
		/* 0/x = 0 */
		if (isintval(args[1], 0))
			r = args[1];
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a / b, exprtype(n));
		break;
	case Omod:
		/* x%0 = error */
		if (isintval(args[1], 0))
			fatal(args[1], "division by zero");
		/* x%1 = 0 */
		if (isintval(args[1], 1))
			r = val(n->loc, 0, exprtype(n));
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a % b, exprtype(n));
		break;
	case Oneg:
		if (getintlit(args[0], &a))
			r = val(n->loc, -a, exprtype(n));
		break;
	case Obsl:
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, (uint64_t)a << b, exprtype(n));
		break;
	case Obsr:
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a >> b, exprtype(n));
		break;
	case Obor:
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a | b, exprtype(n));
		break;
	case Oband:
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a & b, exprtype(n));
		break;
	case Obxor:
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a ^ b, exprtype(n));
		break;
	case Omemb:
		t = tybase(exprtype(args[0]));
		/* we only fold lengths right now */
		if (t->type == Tyarray && !strcmp(namestr(args[1]), "len")) {
			r = t->asize;
			r->expr.type = exprtype(n);
		}
		break;
	case Oarr:
                if (n->expr.nargs > 0)
                    qsort(n->expr.args, n->expr.nargs, sizeof(Node*), idxcmp);
		break;
	case Ocast:
		r = foldcast(n);
		break;
	case Osize:
		if (sizefn)
			r = val(n->loc, sizefn(n->expr.args[0]), exprtype(n));
		break;
	default:
		break;
	}

	if (r && n->expr.idx)
		r->expr.idx = n->expr.idx;

	if (r)
		return r;
	else
		return n;
}