shithub: scc

Download patch

ref: 04eaf8bf9813e47819a823534b8b53e481088f77
parent: 585dc6d025dabe3e95271084e27e6c833c8c3dbf
author: Roberto E. Vargas Caballero <[email protected]>
date: Wed Jul 22 10:30:27 EDT 2015

Simplify multiplicative expressions

--- a/cc1/code.c
+++ b/cc1/code.c
@@ -124,15 +124,20 @@
 	[OSWITCH] = emitswitch
 };
 
-static Node *simple_sub(Node *), *simple_add(Node *);
+static Node *simple_add(Type *, Node *, Node *),
+            *simple_sub(Type *, Node *, Node *),
+            *simple_mul(Type *, Node *, Node *),
+            *simple_div(Type *, Node *, Node *),
+            *simple_mod(Type *, Node *, Node *);
 
-static Node *(*opsimp[])(Node *) = {
+static Node *(*opsimp[])(Type *, Node *, Node *) = {
 	[OADD] = simple_add,
-	[OSUB] = simple_sub
-
+	[OSUB] = simple_sub,
+	[OMUL] = simple_mul,
+	[ODIV] = simple_div,
+	[OMOD] = simple_mod
 };
 
-
 void
 freetree(Node *np)
 {
@@ -388,10 +393,8 @@
 }
 
 static Node *
-simple_add(Node *np)
+simple_mod(Type *tp, Node *lp, Node *rp)
 {
-	Node *lp = np->left, *rp = np->right;
-	Type *tp = np->type;
 	Symbol *sym, *ls = lp->sym, *rs = rp->sym;
 
 	switch (tp->op) {
@@ -398,22 +401,94 @@
 	case INT:
 		sym = newsym(NS_IDEN);
 		sym->type = tp;
+		if (tp->sign) {
+			if (rs->u.i == 0)
+				goto division_by_0;
+			sym->u.i = ls->u.i % rs->u.i;
+		} else {
+			if (rs->u.u == 0)
+				goto division_by_0;
+			sym->u.u = ls->u.u % rs->u.u;
+		}
+		return constnode(sym);
+	default:
+		return NULL;
+	}
+
+division_by_0:
+	warn("division by 0");
+	return NULL;
+}
+
+static Node *
+simple_div(Type *tp, Node *lp, Node *rp)
+{
+	Symbol *sym, *ls = lp->sym, *rs = rp->sym;
+
+	switch (tp->op) {
+	case INT:
+		sym = newsym(NS_IDEN);
+		sym->type = tp;
+		if (tp->sign) {
+			if (rs->u.i == 0)
+				goto division_by_0;
+			sym->u.i = ls->u.i / rs->u.i;
+		} else {
+			if (rs->u.u == 0)
+				goto division_by_0;
+			sym->u.u = ls->u.u / rs->u.u;
+		}
+		return constnode(sym);
+	default:
+		return NULL;
+	}
+
+division_by_0:
+	warn("division by 0");
+	return NULL;
+}
+
+static Node *
+simple_mul(Type *tp, Node *lp, Node *rp)
+{
+	Symbol *sym, *ls = lp->sym, *rs = rp->sym;
+
+	switch (tp->op) {
+	case INT:
+		sym = newsym(NS_IDEN);
+		sym->type = tp;
 		if (tp->sign)
+			sym->u.i = ls->u.i * rs->u.i;
+		else
+			sym->u.u = ls->u.u * rs->u.u;
+		return constnode(sym);
+	default:
+		return NULL;
+	}
+}
+
+static Node *
+simple_add(Type *tp, Node *lp, Node *rp)
+{
+	Symbol *sym, *ls = lp->sym, *rs = rp->sym;
+
+	switch (tp->op) {
+	case INT:
+		sym = newsym(NS_IDEN);
+		sym->type = tp;
+		if (tp->sign)
 			sym->u.i = ls->u.i + rs->u.i;
 		else
 			sym->u.u = ls->u.u + rs->u.u;
-		freetree(np);
 		return constnode(sym);
 	default:
-		return np;
+		return NULL;
 	}
 }
 
 static Node *
-simple_sub(Node *np)
+simple_sub(Type *tp, Node *lp, Node *rp)
 {
-	Node *lp = np->left, *rp = np->right;
-	Type *tp = np->type;
 	Symbol *sym, *ls = lp->sym, *rs = rp->sym;
 
 	switch (tp->op) {
@@ -424,10 +499,9 @@
 			sym->u.i = ls->u.i - rs->u.i;
 		else
 			sym->u.u = ls->u.u - rs->u.u;
-		freetree(np);
 		return constnode(sym);
 	default:
-		return np;
+		return NULL;
 	}
 }
 
@@ -434,7 +508,14 @@
 Node *
 simplify(Node *np)
 {
-	if (!np->left->constant || !np->right->constant)
+	Node *new, *lp = np->left, *rp = np->right;
+
+	if (!lp->constant || !rp->constant)
 		return np;
-	return (*opsimp[np->op])(np);
+	new = (*opsimp[np->op])(np->type, lp, rp);
+	if (new) {
+		freetree(np);
+		np = new;
+	}
+	return np;
 }
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -667,6 +667,7 @@
 		}
 		next();
 		np = (*fun)(op, np, cast());
+		np = simplify(np);
 	}
 }