Example #1
0
Node *fold(Node *n, int foldvar)
{
    Node **args, *r;
    Type *t;
    vlong a, b;
    size_t i;

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

    r = NULL;
    args = n->expr.args;
    for (i = 0; i < n->expr.nargs; i++)
        args[i] = fold(args[i], foldvar);
    switch (exprop(n)) {
        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 (isval(args[0], 0))
                r = args[1];
            if (isval(args[1], 0))
                r = args[0];
            if (islit(args[0], &a) && islit(args[1], &b))
                r = val(n->line, a + b, exprtype(n));
            break;
        case Osub:
            /* x - 0 = 0 */
            if (isval(args[1], 0))
                r = args[0];
            if (islit(args[0], &a) && islit(args[1], &b))
                r = val(n->line, a - b, exprtype(n));
            break;
        case Omul:
            /* 1 * x = x */
            if (isval(args[0], 1))
                r = args[1];
            if (isval(args[1], 1))
                r = args[0];
            /* 0 * x = 0 */
            if (isval(args[0], 0))
                r = args[0];
            if (isval(args[1], 0))
                r = args[1];
            if (islit(args[0], &a) && islit(args[1], &b))
                r = val(n->line, a * b, exprtype(n));
            break;
        case Odiv:
            /* x/1 = x */
            if (isval(args[1], 1))
                r = args[0];
            /* 0/x = 0 */
            if (isval(args[1], 0))
                r = args[1];
            if (islit(args[0], &a) && islit(args[1], &b))
                r = val(n->line, a / b, exprtype(n));
            break;
        case Omod:
            /* x%1 = x */
            if (isval(args[1], 0))
                r = args[0];
            if (islit(args[0], &a) && islit(args[1], &b))
                r = val(n->line, a % b, exprtype(n));
            break;
        case Oneg:
            if (islit(args[0], &a))
                r = val(n->line, -a, exprtype(n));
            break;
        case Obsl:
            if (islit(args[0], &a) && islit(args[1], &b))
                r = val(n->line, a << b, exprtype(n));
            break;
        case Obsr:
            if (islit(args[0], &a) && islit(args[1], &b))
                r = val(n->line, a >> b, exprtype(n));
            break;
        case Obor:
            if (islit(args[0], &a) && islit(args[1], &b))
                r = val(n->line, a | b, exprtype(n));
            break;
        case Oband:
            if (islit(args[0], &a) && islit(args[1], &b))
                r = val(n->line, a & b, exprtype(n));
            break;
        case Obxor:
            if (islit(args[0], &a) && islit(args[1], &b))
                r = val(n->line, 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;
            break;
        case Ocast:
            r = foldcast(n);
            break;
        default:
            break;
    }

    if (r)
        return r;
    else
        return n;
}
Example #2
0
File: fold.c Project: 8l/mc
Node *fold(Node *n, int foldvar)
{
	Node **args, *r;
	Type *t;
	vlong a, b;
	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 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, 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, 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;
	default:
		break;
	}

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

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