shithub: scc

Download patch

ref: 3b24f6d8f63683c0cf5e19b9af7f93a2e9f28215
parent: d8b42decda0af1265ba2d6a79b1fdbe5fb75e8d2
author: Roberto E. Vargas Caballero <[email protected]>
date: Mon May 9 12:44:44 EDT 2016

[cc2-qbe] Improve load()

This function was a bit low level function, and it was generating
a lot of code in every call. This new version has an interface
that is a bit ugly, but the result code is far better.

--- 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,48 +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)
 {
-	Node *new;
 	int op;
-	Type *tp = &np->type;
+	Type *tp;
+	Node *child;
 
-	new = tmpnode(newnode());
-	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());
+		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;
@@ -194,7 +210,7 @@
 			tmp = tmpnode(newnode());
 			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;
@@ -274,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:
@@ -285,7 +297,7 @@
 	case OELOOP:
 		return NULL;
 	case OCAST:
-		return cast(np, l);
+		return cast(np);
 	case OADDR:
 		np->flags |= ISTMP;
 		np->op = OTMP;
@@ -292,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:
@@ -328,9 +342,8 @@
 	case OOR:
 		abort();
 	case OBRANCH:
-		if (l && (l->flags & (ISTMP|ISCONS)) == 0)
-			l = np->left = load(l);
 		next = np->next;
+		l = load(np, LOADL);
 		if (next->label) {
 			sym = getsym(TMPSYM);
 			sym->kind = SLABEL;
@@ -351,9 +364,7 @@
 		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: