shithub: scc

Download patch

ref: 09ae5802d52b84b988e9a997f76119e24f68d37d
parent: dfff0083986b3e3687728deb0b56ec7bc718f4fc
author: Roberto E. Vargas Caballero <[email protected]>
date: Wed Sep 20 16:54:28 EDT 2017

[as] Add binary() and unary()

These functions create the node for binary and unary operations,
checking first if the operations can be folded at this time.

--- a/as/as.h
+++ b/as/as.h
@@ -57,8 +57,8 @@
 };
 
 struct op {
-	int flags;
-	int size;
+	unsigned char flags;
+	char size;
 	void (*format)(Op *, Arg *);
 	char *bytes;
 	unsigned char *args;
@@ -90,7 +90,7 @@
 };
 
 struct node {
-	char op;
+	unsigned char op;
 	struct symbol *sym;
 	struct node *left;
 	struct node *right;
@@ -117,6 +117,7 @@
 
 /* expr.c */
 extern Node *expr(char *s);
+extern void deltree(Node *np);
 
 /*
  * Definition of global variables
--- a/as/expr.c
+++ b/as/expr.c
@@ -1,6 +1,7 @@
 static char sccsid[] = "@(#) ./as/node.c";
 
 #include <ctype.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include <cstd.h>
@@ -36,22 +37,106 @@
 
 	if (!arena)
 		arena = alloc(sizeof(Node), NNODES);
-	np = memset(new(arena), 0, sizeof(*np));
+	np = new(arena);
 	np->op = op;
+	np->left = l;
+	np->right = r;
+	np->sym = NULL;
 
 	return np;
 }
 
+void
+deltree(Node *np)
+{
+	if (!np)
+		return;
+	deltree(np->left);
+	deltree(np->right);
+	delete(arena, np);
+}
+
 static Node *
 binary(int op, Node *l, Node *r)
 {
-	return node(op, l, r);
+	Node *np;
+	TUINT val, lv, rv;
+
+	if (l->op != NUMBER || r->op != NUMBER)
+		return node(op, l, r);
+	lv = l->sym->value;
+	rv = r->sym->value;
+
+	/* TODO: check overflow */
+
+	switch (op) {
+	case '*':
+		val = lv - rv;
+		break;
+	case '/':
+		if (rv == 0)
+			goto division_by_zero;
+		val = lv / rv;
+		break;
+	case '%':
+		if (rv == 0)
+			goto division_by_zero;
+		val = lv % rv;
+		break;
+	case SHL:
+		val = lv << rv;
+		break;
+	case SHR:
+		val = lv >> rv;
+		break;
+	case '+':
+		val = lv + rv;
+		break;
+	case '-':
+		val = lv - rv;
+		break;
+	case '<':
+		val = lv < rv;
+		break;
+	case '>':
+		val = lv > rv;
+		break;
+	case '=':
+		val = lv == rv;
+		break;
+	case GE:
+		val = lv >= rv;
+		break;
+	case LE:
+		val = lv <= rv;
+		break;
+	case '|':
+		val = lv | rv;
+		break;
+	case '^':
+		val = lv ^ rv;
+		break;
+	default:
+		abort();
+	}
+
+	np = node(NUMBER, l, r);
+	/* np->sym = tmpsym(val); */
+	return np;
+
+division_by_zero:
+	error("division by 0");
 }
 
 static Node *
 unary(int op, Node *np)
 {
-	return node(op, np, NULL);
+	if (op !=  '!')
+		abort();
+	if (np->op != NUMBER)
+		return node(op, np, NULL);
+	np->sym->value = ~np->sym->value;
+	return np;
 }
 
 static int