shithub: scc

Download patch

ref: effb6ade9692c5ca019344b501d2c178b5bbaefd
parent: 508b00b42102538e576dad13db861e699dec9092
parent: 3b24f6d8f63683c0cf5e19b9af7f93a2e9f28215
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Mon May 9 12:56:27 EDT 2016

Merge branch 'master' into quinq

--- a/cc2/Makefile
+++ b/cc2/Makefile
@@ -2,8 +2,9 @@
 
 include ../config.mk
 
-OBJS = main.o parser.o optm.o peep.o symbol.o node.o code.o\
-       arch/$(ARCH)/code.o arch/$(ARCH)/cgen.o arch/$(ARCH)/types.o
+OBJS = main.o parser.o peep.o symbol.o node.o code.o\
+       arch/$(ARCH)/code.o arch/$(ARCH)/cgen.o \
+       arch/$(ARCH)/types.o arch/$(ARCH)/optm.o
 
 all: cc2
 
--- /dev/null
+++ b/cc2/arch/amd64-sysv/optm.c
@@ -1,0 +1,9 @@
+
+#include "arch.h"
+#include "../../cc2.h"
+
+Node *
+optm(Node *np)
+{
+	return np;
+}
--- /dev/null
+++ b/cc2/arch/i386-sysv/optm.c
@@ -1,0 +1,9 @@
+
+#include "arch.h"
+#include "../../cc2.h"
+
+Node *
+optm(Node *np)
+{
+	return np;
+}
--- a/cc2/arch/qbe/arch.h
+++ b/cc2/arch/qbe/arch.h
@@ -131,5 +131,6 @@
 	ASTRUNCD,
 
 	ASJMP,
+	ASBRANCH,
 	ASRET,
 };
--- a/cc2/arch/qbe/cgen.c
+++ b/cc2/arch/qbe/cgen.c
@@ -5,6 +5,12 @@
 #include "arch.h"
 #include "../../cc2.h"
 
+enum lflags {
+	FORCE = 1 << 0,
+	LOADL = 1 << 1,
+	LOADR = 1 << 2
+};
+
 enum sflags {
 	ISTMP  = 1,
 	ISCONS = 2
@@ -104,47 +110,58 @@
 	return np;
 }
 
+/*
+ * load() load the address passed in a child of np in a temporary
+ * if it is not already in a temporay. It can be forced to load
+ * using the FORCE flag
+ */
 static Node *
-load(Node *np)
+load(Node *np, int flags)
 {
 	int op;
-	Node *new = tmpnode(newnode(ONOP));
-	Type *tp = &np->type;
+	Type *tp;
+	Node *child;
 
-	new->left = np;
-	new->type = *tp;
+	child = (flags & LOADL) ? np->left : np->right;
+	tp = &child->type;
 
-	switch (tp->size) {
-	case 1:
-		op = ASLDB;
-		break;
-	case 2:
-		op = ASLDH;
-		break;
-	case 4:
-		op = (tp->flags & INTF) ? ASLDW : ASLDS;
-		break;
-	case 8:
-		op = (tp->flags & INTF) ? ASLDL : ASLDD;
-		break;
-	default:
-		abort();
+	if ((flags & FORCE) || !(child->flags & (ISTMP|ISCONS))) {
+		Node *new = tmpnode(newnode(OTMP));
+		new->type = *tp;
+		new->left = child;
+
+		switch (tp->size) {
+		case 1:
+			op = ASLDB;
+			break;
+		case 2:
+			op = ASLDH;
+			break;
+		case 4:
+			op = (tp->flags & INTF) ? ASLDW : ASLDS;
+			break;
+		case 8:
+			op = (tp->flags & INTF) ? ASLDL : ASLDD;
+			break;
+		default:
+			abort();
+		}
+		code(op, new, child, NULL);
+		child = new;
 	}
-	code(op, new, np, NULL);
 
-	return new;
+	return (flags & LOADL) ? (np->left = child) : (np->right = child);
 }
 
 static Node *
-cast(Node *nd, Node *ns)
+cast(Node *nd)
 {
 	Type *ts, *td;
-	Node *tmp;
+	Node *tmp, *ns;
 	int op, disint, sisint;
 	extern Type uint32type, int32type;
 
-	if ((ns->flags & (ISTMP|ISCONS)) == 0)
-		ns = nd->left = load(ns);
+	ns = load(nd, LOADL);
 	td = &nd->type;
 	ts = &ns->type;
 	disint = (td->flags & INTF) != 0;
@@ -193,7 +210,7 @@
 			tmp = tmpnode(newnode(ONOP));
 			tmp->type = (ts->flags&SIGNF) ? int32type : uint32type;
 			tmp->left = ns;
-			nd->left = ns = cast(tmp, ns);
+			nd->left = ns = cast(tmp);
 		case 4:
 			op = (td->size == 8) ? ASSWTOD : ASSWTOS;
 			break;
@@ -215,7 +232,7 @@
 Node *
 cgen(Node *np)
 {
-	Node *l, *r;
+	Node *l, *r, *ifyes, *ifno, *next;
 	Symbol *sym;
 	Type *tp;
 	int op, off;
@@ -224,13 +241,7 @@
 	if (!np)
 		return NULL;
 
-	if (np->label) {
-		setlabel(np->label);
-		if (np->next == NULL) {
-			addstmt(newnode(ORET));
-			prevstmt();
-		}
-	}
+	setlabel(np->label);
 	l = cgen(np->left);
 	r = cgen(np->right);
 	tp = &np->type;
@@ -279,11 +290,7 @@
 			abort();
 		}
 		op = tbl[np->op] + off;
-		if ((l->flags & (ISTMP|ISCONS)) == 0)
-			l = np->left = load(l);
-		if ((r->flags & (ISTMP|ISCONS)) == 0)
-			r = np->right = load(r);
-		code(op, tmpnode(np), l, r);
+		code(op, tmpnode(np), load(np, LOADL), load(np, LOADR));
 		return np;
 	case ONOP:
 	case OBLOOP:
@@ -290,7 +297,7 @@
 	case OELOOP:
 		return NULL;
 	case OCAST:
-		return cast(np, l);
+		return cast(np);
 	case OADDR:
 		np->flags |= ISTMP;
 		np->op = OTMP;
@@ -297,7 +304,9 @@
 		np->u.sym = l->u.sym;
 		return np;
 	case OPTR:
-		np->left = load(load(l));
+		load(np, LOADL);
+		/* FIXME: The type of the loaded value is not np->type */
+		load(np, LOADL|FORCE);
 		return tmpnode(np);
 	case OCPL:
 	case OPAR:
@@ -333,14 +342,29 @@
 	case OOR:
 		abort();
 	case OBRANCH:
-		abort();
+		next = np->next;
+		l = load(np, LOADL);
+		if (next->label) {
+			sym = getsym(TMPSYM);
+			sym->kind = SLABEL;
+			next->label = sym;
+		}
+		ifyes = label(np->u.sym);
+		ifno = label(next->label);
+		op = ASBRANCH;
+		np = np->left;
+		goto emit_jump;
 	case OJMP:
-		code(ASJMP, np, NULL, NULL);
+		ifyes = label(np->u.sym);
+		op = ASJMP;
+		np = ifno = NULL;
+	emit_jump:
+		code(op, np, ifyes, ifno);
+		deltree(ifyes);
+		deltree(ifno);
 		return NULL;
 	case ORET:
-		if (l && (l->flags & (ISTMP|ISCONS)) == 0)
-			l = np->left = load(l);
-		code(ASRET, l, NULL, NULL);
+		code(ASRET, load(np, LOADL), NULL, NULL);
 		return NULL;
 	case OCASE:
 	case ODEFAULT:
--- a/cc2/arch/qbe/code.c
+++ b/cc2/arch/qbe/code.c
@@ -9,7 +9,8 @@
 
 #define ADDR_LEN (IDENTSIZ+64)
 
-static void binary(void), unary(void), store(void), jmp(void), ret(void);
+static void binary(void), unary(void), store(void), jmp(void), ret(void),
+            branch(void);
 
 static struct opdata {
 	void (*fun)(void);
@@ -122,6 +123,7 @@
 	[ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'},
 	[ASSLTOS]= {.fun = unary, .txt = "truncd", .letter = 's'},
 
+	[ASBRANCH] = {.fun = branch},
 	[ASJMP]  = {.fun = jmp},
 	[ASRET]  = {.fun = ret},
 };
@@ -403,7 +405,18 @@
 static void
 jmp(void)
 {
-	printf("\t\tjmp\t%s\n", addr2txt(&pc->to));
+	printf("\t\tjmp\t%s\n", addr2txt(&pc->from1));
+}
+
+static void
+branch(void)
+{
+	char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
+
+	strcpy(to, addr2txt(&pc->to));
+	strcpy(from1, addr2txt(&pc->from1));
+	strcpy(from2, addr2txt(&pc->from2));
+	printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2);
 }
 
 void
--- /dev/null
+++ b/cc2/arch/qbe/optm.c
@@ -1,0 +1,67 @@
+
+#include <stddef.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+Node *
+optm(Node *np)
+{
+	int op = np->op;
+	Node *p, *dst, *next = np->next;
+	Symbol *sym, *osym;
+
+	if (!next) {
+		/*
+		 * In QBE we need at the end of a basic block
+		 * a jump, so we have to ensure that the last
+		 * statement of the function is a ret, a jmp
+		 * or a branch. In the same way, QBE does
+		 * not accept labels at the end of a function
+		 * (ONOP is used for labels) so we have to add
+		 * a ret there, and in the case of branches
+		 * we need a label for the next statement
+		 */
+		if (op == ONOP || op == OBRANCH || (op != ORET && op != OJMP))
+			addstmt(newnode(ORET), KEEPCUR);
+		next = np->next;
+	}
+
+	switch (op) {
+	case ONOP:
+		if (next->op == ONOP) {
+			sym = np->u.sym;
+			osym = next->u.sym;
+			osym->id = sym->id;
+			osym->numid = sym->id;
+			osym->u.stmt = sym->u.stmt;
+			return NULL;
+		}
+		break;
+	case OBRANCH:
+		if (!next->label) {
+			sym = getsym(TMPSYM);
+			sym->kind = SLABEL;
+			next->label = sym;
+		}
+	case OJMP:
+		for (;;) {
+			dst = np->u.sym->u.stmt;
+			if (dst->op != OJMP)
+				break;
+			np->u.sym = dst->u.sym;
+		}
+		for (p = np->next; p; p = p->next) {
+			if (p == dst)
+				return NULL;
+			if (p->op == ONOP ||
+			    p->op == OBLOOP ||
+			    p->op == OELOOP) {
+				continue;
+			}
+			break;
+		}
+		break;
+	}
+	return np;
+}
--- /dev/null
+++ b/cc2/arch/z80/optm.c
@@ -1,0 +1,9 @@
+
+#include "arch.h"
+#include "../../cc2.h"
+
+Node *
+optm(Node *np)
+{
+	return np;
+}
--- a/cc2/cc2.h
+++ b/cc2/cc2.h
@@ -202,16 +202,18 @@
 extern void code(int op, Node *to, Node *from1, Node *from2);
 extern void defvar(Symbol *), defpar(Symbol *), defglobal(Symbol *);
 extern void setlabel(Symbol *sym);
+extern Node *label(Symbol *sym);
 
 /* node.c */
+#define SETCUR  1
+#define KEEPCUR 0
 extern void apply(Node *(*fun)(Node *));
 extern void cleannodes(void);
 extern void delnode(Node *np);
 extern void deltree(Node *np);
 extern Node *newnode(int op);
-extern Node *addstmt(Node *np);
-extern Node *prevstmt(void), *nextstmt(void);
-
+extern Node *addstmt(Node *np, int flags);
+extern Node *nextstmt(void);
 
 /* symbol.c */
 #define TMPSYM  0
--- a/cc2/code.c
+++ b/cc2/code.c
@@ -38,7 +38,6 @@
 		addr->kind = OCONST;
 		addr->u.i = np->u.i;
 		break;
-	case OJMP:
 	case OLABEL:
 		addr->kind = SLABEL;
 		goto symbol;
@@ -50,9 +49,18 @@
 	symbol:
 		addr->u.sym = np->u.sym;
 		break;
-	default:
-		abort();
 	}
+}
+
+Node *
+label(Symbol *sym)
+{
+	Node *np;
+
+	np = newnode(OLABEL);
+	np->u.sym = sym;
+
+	return np;
 }
 
 void
--- a/cc2/node.c
+++ b/cc2/node.c
@@ -49,16 +49,20 @@
 }
 
 Node *
-addstmt(Node *np)
+addstmt(Node *np, int flag)
 {
+	if (curstmt)
+		np->next = curstmt->next;
+	np->prev = curstmt;
+
 	if (!curfun->u.stmt)
 		curfun->u.stmt = np;
 	else
 		curstmt->next = np;
-	np->next = NULL;
-	np->prev = curstmt;
-	curstmt = np;
 
+	if (flag == SETCUR)
+		curstmt = np;
+
 	return np;
 }
 
@@ -84,12 +88,6 @@
 nextstmt(void)
 {
 	return curstmt = curstmt->next;
-}
-
-Node *
-prevstmt(void)
-{
-	return curstmt = curstmt->prev;
 }
 
 void
--- a/cc2/optm.c
+++ /dev/null
@@ -1,45 +1,0 @@
-
-#include <stddef.h>
-
-#include "arch.h"
-#include "cc2.h"
-
-Node *
-optm(Node *np)
-{
-	Node *p, *dst, *next = np->next;
-	Symbol *sym, *osym;
-
-	switch (np->op) {
-	case ONOP:
-		if (next && next->op == ONOP) {
-			sym = np->u.sym;
-			osym = next->u.sym;
-			osym->id = sym->id;
-			osym->numid = sym->id;
-			osym->u.stmt = sym->u.stmt;
-			return NULL;
-		}
-		break;
-	case OJMP:
-	case OBRANCH:
-		for (;;) {
-			dst = np->u.sym->u.stmt;
-			if (dst->op != OJMP)
-				break;
-			np->u.sym = dst->u.sym;
-		}
-		for (p = np->next; p; p = p->next) {
-			if (p == dst)
-				return NULL;
-			if (p->op == ONOP ||
-			    p->op == OBLOOP ||
-			    p->op == OELOOP) {
-				continue;
-			}
-			break;
-		}
-		break;
-	}
-	return np;
-}
--- a/cc2/parser.c
+++ b/cc2/parser.c
@@ -556,7 +556,7 @@
 	sym->kind = SLABEL;
 	sym->u.stmt = np;
 	np->label = sym;
-	addstmt(np);
+	addstmt(np, SETCUR);
 }
 
 static void
@@ -570,7 +570,7 @@
 		deltree(np);
 		return;
 	}
-	addstmt(np);
+	addstmt(np, SETCUR);
 }
 
 static void