summaryrefslogtreecommitdiff
path: root/opt
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2012-06-17 00:38:42 -0400
committerOri Bernstein <ori@eigenstate.org>2012-06-17 00:38:42 -0400
commit6f83d942aeb7c284341be7b1e514d994cc17b715 (patch)
tree9c45d69173f0851072cb1bc158471343c27dbc57 /opt
parent6ca71755bfa098a5849753f3aa7512f0b10257aa (diff)
downloadmc-6f83d942aeb7c284341be7b1e514d994cc17b715.tar.gz
Add missing file.
Diffstat (limited to 'opt')
-rw-r--r--opt/fold.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/opt/fold.c b/opt/fold.c
new file mode 100644
index 0000000..bc5ffde
--- /dev/null
+++ b/opt/fold.c
@@ -0,0 +1,124 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+#include "opt.h"
+
+int islit(Node *n, vlong *v)
+{
+ Node *l;
+
+ if (exprop(n) != Olit)
+ return 0;
+ l = n->expr.args[0];
+ if (l->lit.littype != Lint)
+ return 0;
+ *v = l->lit.intval;
+ return 1;
+}
+
+int isval(Node *n, vlong val)
+{
+ vlong v;
+
+ if (!islit(n, &v))
+ return 0;
+ return v == val;
+}
+
+Node *val(int line, vlong val)
+{
+ Node *n;
+
+ n = mkint(line, val);
+ n = mkexpr(line, Olit, n, NULL);
+ return n;
+}
+
+Node *fold(Node *n)
+{
+ Node **args, *r;
+ vlong a, b;
+ size_t i;
+
+ assert(n->type == Nexpr);
+
+ r = NULL;
+ args = n->expr.args;
+ if (exprop(n) != Ovar && exprop(n) != Ocjmp &&
+ exprop(n) != Ojmp && exprop(n) != Olit)
+ for (i = 0; i < n->expr.nargs; i++)
+ args[i] = fold(args[i]);
+ switch (exprop(n)) {
+ case Ovar:
+ /* FIXME: chase small consts */
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ break;
+ case Oneg:
+ if (islit(args[0], &a))
+ r = val(n->line, -a);
+ break;
+ default:
+ break;
+ }
+
+ if (r)
+ return r;
+ else
+ return n;
+}