commit 93ad4b36a9dec103d7851d117f4d6e1717a74d46
Author:     Roberto E. Vargas Caballero <[email protected]>
AuthorDate: Mon May 9 16:44:44 2016 +0200
Commit:     Roberto E. Vargas Caballero <[email protected]>
CommitDate: Mon May 9 16:44:44 2016 +0200

    [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.

diff --git a/cc2/arch/qbe/cgen.c b/cc2/arch/qbe/cgen.c
index b06ff1d..f0e2c2f 100644
--- 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 @@ tmpnode(Node *np)
        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 @@ cast(Node *nd, Node *ns)
                        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,25 +290,23 @@ cgen(Node *np)
                        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:
        case OELOOP:
                return NULL;
        case OCAST:
-               return cast(np, l);
+               return cast(np);
        case OADDR:
                np->flags |= ISTMP;
                np->op = OTMP;
                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 @@ cgen(Node *np)
        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 @@ cgen(Node *np)
                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:

Reply via email to