changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: mpc: constant expression folding

changeset 5068: fa3700dc38f9
parent 5067: 863e33d86749
child 5069: 467142072a11
author: cinap_lenrek@felloff.net
date: Mon, 01 Feb 2016 19:27:57 +0100
files: sys/src/cmd/mpc.y
description: mpc: constant expression folding
     1.1--- a/sys/src/cmd/mpc.y
     1.2+++ b/sys/src/cmd/mpc.y
     1.3@@ -28,6 +28,7 @@ struct Node
     1.4 	Node*	l;
     1.5 	Node*	r;
     1.6 	Sym*	s;
     1.7+	mpint*	m;
     1.8 	int	n;
     1.9 };
    1.10 
    1.11@@ -238,11 +239,11 @@ expr:
    1.12 	{
    1.13 		$$ = new('e', $1, $2);
    1.14 	}
    1.15-|	expr LSH num
    1.16+|	expr LSH expr
    1.17 	{
    1.18 		$$ = new(LSH, $1, $3);
    1.19 	}
    1.20-|	expr RSH num
    1.21+|	expr RSH expr
    1.22 	{
    1.23 		$$ = new(RSH, $1, $3);
    1.24 	}
    1.25@@ -390,6 +391,7 @@ new(int c, Node *l, Node *r)
    1.26 	n->l = l;
    1.27 	n->r = r;
    1.28 	n->s = nil;
    1.29+	n->m = nil;
    1.30 	n->n = lineno;
    1.31 	return n;
    1.32 }
    1.33@@ -561,7 +563,7 @@ complex(Node *n)
    1.34 {
    1.35 	if(n->c == NAME)
    1.36 		return 0;
    1.37-	if(n->c == NUM && strlen(n->s->n) == 1 && atoi(n->s->n) < 3)
    1.38+	if(n->c == NUM && n->m->sign > 0 && mpcmp(n->m, mptwo) <= 0)
    1.39 		return 0;
    1.40 	return 1;
    1.41 }
    1.42@@ -570,37 +572,131 @@ void
    1.43 bcom(Node *n, Node *t);
    1.44 
    1.45 Node*
    1.46-ecom(Node *f, Node *t)
    1.47+ccom(Node *f)
    1.48 {
    1.49-	Node *l, *r, *t2;
    1.50-	mpint *m;
    1.51+	Node *l, *r;
    1.52 
    1.53 	if(f == nil)
    1.54 		return nil;
    1.55 
    1.56+	if(f->m != nil)
    1.57+		return f;
    1.58+	f->m = (void*)~0;
    1.59+
    1.60+	switch(f->c){
    1.61+	case NUM:
    1.62+		f->m = strtomp(f->s->n, nil, 0, nil);
    1.63+		if(f->m == nil)
    1.64+			diag(f, "bad constant");
    1.65+		goto out;
    1.66+
    1.67+	case LSH:
    1.68+	case RSH:
    1.69+		break;
    1.70+
    1.71+	case '+':
    1.72+	case '-':
    1.73+	case '*':
    1.74+	case '/':
    1.75+	case '%':
    1.76+	case '^':
    1.77+		if(modulo == nil || modulo->c == NUM)
    1.78+			break;
    1.79+
    1.80+		/* wet floor */
    1.81+	default:
    1.82+		return f;
    1.83+	}
    1.84+
    1.85+	f->l = l = ccom(f->l);
    1.86+	f->r = r = ccom(f->r);
    1.87+	if(l == nil || r == nil || l->c != NUM || r->c != NUM)
    1.88+		return f;
    1.89+
    1.90+	f->m = mpnew(0);
    1.91+	switch(f->c){
    1.92+	case LSH:
    1.93+	case RSH:
    1.94+		if(mpsignif(r->m) > 32)
    1.95+			diag(f, "bad shift");
    1.96+		if(f->c == LSH)
    1.97+			mpleft(l->m, mptoi(r->m), f->m);
    1.98+		else
    1.99+			mpright(l->m, mptoi(r->m), f->m);
   1.100+		goto out;
   1.101+
   1.102+	case '+':
   1.103+		mpadd(l->m, r->m, f->m);
   1.104+		break;
   1.105+	case '-':
   1.106+		mpsub(l->m, r->m, f->m);
   1.107+		break;
   1.108+	case '*':
   1.109+		mpmul(l->m, r->m, f->m);
   1.110+		break;
   1.111+	case '/':
   1.112+		if(modulo != nil){
   1.113+			mpinvert(r->m, modulo->m, f->m);
   1.114+			mpmul(f->m, l->m, f->m);
   1.115+		} else {
   1.116+			mpdiv(l->m, r->m, f->m, nil);
   1.117+		}
   1.118+		break;
   1.119+	case '%':
   1.120+		mpmod(l->m, r->m, f->m);
   1.121+		break;
   1.122+	case '^':
   1.123+		mpexp(l->m, r->m, modulo != nil ? modulo->m : nil, f->m);
   1.124+		goto out;
   1.125+	}
   1.126+	if(modulo != nil)
   1.127+		mpmod(f->m, modulo->m, f->m);
   1.128+
   1.129+out:
   1.130+	f->l = nil;
   1.131+	f->r = nil;
   1.132+	f->s = nil;
   1.133+	f->c = NUM;
   1.134+	return f;
   1.135+}
   1.136+
   1.137+Node*
   1.138+ecom(Node *f, Node *t)
   1.139+{
   1.140+	Node *l, *r, *t2;
   1.141+
   1.142+	if(f == nil)
   1.143+		return nil;
   1.144+
   1.145+	f = ccom(f);
   1.146 	if(f->c == NUM){
   1.147-		m = strtomp(f->s->n, nil, 0, nil);
   1.148-		if(m == nil)
   1.149-			diag(f, "bad constant");
   1.150-		if(mpcmp(m, mpzero) == 0){
   1.151+		if(f->m->sign < 0){
   1.152+			f->m->sign = 1;
   1.153+			t = ecom(f, t);
   1.154+			f->m->sign = -1;
   1.155+			if(isconst(t))
   1.156+				t = ecom(t, alloctmp());
   1.157+			cprint("%N->sign = -1;\n", t);
   1.158+			return t;
   1.159+		}
   1.160+		if(mpcmp(f->m, mpzero) == 0){
   1.161 			f->c = NAME;
   1.162 			f->s = sym("mpzero");
   1.163 			f->s->f = FSET;
   1.164 			return ecom(f, t);
   1.165 		}
   1.166-		if(mpcmp(m, mpone) == 0){
   1.167+		if(mpcmp(f->m, mpone) == 0){
   1.168 			f->c = NAME;
   1.169 			f->s = sym("mpone");
   1.170 			f->s->f = FSET;
   1.171 			return ecom(f, t);
   1.172 		}
   1.173-		if(mpcmp(m, mptwo) == 0){
   1.174+		if(mpcmp(f->m, mptwo) == 0){
   1.175 			f->c = NAME;
   1.176 			f->s = sym("mptwo");
   1.177 			f->s->f = FSET;
   1.178 			return ecom(f, t);
   1.179 		}
   1.180-		mpfree(m);
   1.181 	}
   1.182 
   1.183 	if(f->c == ','){
   1.184@@ -645,24 +741,23 @@ ecom(Node *f, Node *t)
   1.185 
   1.186 	switch(f->c){
   1.187 	case NUM:
   1.188-		m = strtomp(f->s->n, nil, 0, nil);
   1.189-		if(m == nil)
   1.190-			diag(f, "bad constant");
   1.191-		if(mpsignif(m) <= 32)
   1.192-			cprint("uitomp(%udUL, %N);\n", mptoui(m), t);
   1.193-		else if(mpsignif(m) <= 64)
   1.194-			cprint("uvtomp(%lludULL, %N);\n", mptouv(m), t);
   1.195+		if(mpsignif(f->m) <= 32)
   1.196+			cprint("uitomp(%udUL, %N);\n", mptoui(f->m), t);
   1.197+		else if(mpsignif(f->m) <= 64)
   1.198+			cprint("uvtomp(%lludULL, %N);\n", mptouv(f->m), t);
   1.199 		else
   1.200-			cprint("strtomp(\"%.16B\", nil, 16, %N);\n", m, t);
   1.201-		mpfree(m);
   1.202+			cprint("strtomp(\"%.16B\", nil, 16, %N);\n", f->m, t);
   1.203 		goto out;
   1.204 	case LSH:
   1.205+	case RSH:
   1.206+		r = ccom(f->r);
   1.207+		if(r == nil || r->c != NUM || mpsignif(r->m) > 32)
   1.208+			diag(f, "bad shift");
   1.209 		l = f->l->c == NAME ? f->l : ecom(f->l, t);
   1.210-		cprint("mpleft(%N, %N, %N);\n", l, f->r, t);
   1.211-		goto out;
   1.212-	case RSH:
   1.213-		l = f->l->c == NAME ? f->l : ecom(f->l, t);
   1.214-		cprint("mpright(%N, %N, %N);\n", l, f->r, t);
   1.215+		if(f->c == LSH)
   1.216+			cprint("mpleft(%N, %d, %N);\n", l, mptoi(r->m), t);
   1.217+		else
   1.218+			cprint("mpright(%N, %d, %N);\n", l, mptoi(r->m), t);
   1.219 		goto out;
   1.220 	case '*':
   1.221 	case '/':
   1.222@@ -670,8 +765,10 @@ ecom(Node *f, Node *t)
   1.223 		r = ecom(f->r, nil);
   1.224 		break;
   1.225 	default:
   1.226-		l = ecom(f->l, complex(f->l) && !symref(f->r, t->s) ? t : nil);
   1.227-		r = ecom(f->r, complex(f->r) && l->s != t->s ? t : nil);
   1.228+		l = ccom(f->l);
   1.229+		r = ccom(f->r);
   1.230+		l = ecom(l, complex(l) && !symref(r, t->s) ? t : nil);
   1.231+		r = ecom(r, complex(r) && l->s != t->s ? t : nil);
   1.232 		break;
   1.233 	}
   1.234 
   1.235@@ -975,8 +1072,11 @@ Nfmt(Fmt *f)
   1.236 		return fmtprint(f, "%N, %N", n->l, n->r);
   1.237 
   1.238 	switch(n->c){
   1.239+	case NUM:
   1.240+		if(n->m != nil)
   1.241+			return fmtprint(f, "%B", n->m);
   1.242+		/* wet floor */
   1.243 	case NAME:
   1.244-	case NUM:
   1.245 		return fmtprint(f, "%s", n->s->n);
   1.246 	case EQ:
   1.247 		return fmtprint(f, "==");