commit 12586fdbde8bc3b7715a93dadf32a051699c04c8
Author:     Roberto E. Vargas Caballero <k...@shike2.com>
AuthorDate: Tue Jun 7 09:32:16 2016 +0200
Commit:     Roberto E. Vargas Caballero <k...@shike2.com>
CommitDate: Tue Jun 7 09:32:16 2016 +0200

    [cc2-qbe] Implement ternary operator
    
    The ternary operator is basically an if-else chain, where both
    branches assign to the same variable. This could be done with
    a phi instruction in qbe, but using the same temporary in both
    branches was more similar to the rest of the code.

diff --git a/cc2/arch/qbe/cgen.c b/cc2/arch/qbe/cgen.c
index d8b0821..acca4e8 100644
--- a/cc2/arch/qbe/cgen.c
+++ b/cc2/arch/qbe/cgen.c
@@ -315,6 +315,43 @@ assign(Node *to, Node *from)
        return from;
 }
 
+static Node *
+ternary(Node *np)
+{
+       Symbol *yes, *no, *phi;
+       Node *ifyes, *ifno, *phinode, *yesval, *colon;
+
+       tmpnode(np);
+       phi = newlabel();
+       yes = newlabel();
+       no = newlabel();
+
+       ifyes = label2node(yes);
+       ifno = label2node(no);
+       phinode = label2node(phi);
+
+       colon = np->right;
+       cgen(np->left);
+       load(np, LOADL);
+       code(ASBRANCH, np->left, ifyes, ifno);
+
+       setlabel(yes);
+       cgen(colon->left);
+       assign(np, load(colon, LOADL));
+       code(ASJMP, NULL, phinode, NULL);
+
+       setlabel(no);
+       cgen(colon->right);
+       assign(np, load(colon, LOADR));
+       setlabel(phi);
+
+       deltree(ifyes);
+       deltree(ifno);
+       deltree(phinode);
+
+       return np;
+}
+
 /* TODO: Fix "memory leaks" */
 Node *
 cgen(Node *np)
@@ -329,7 +366,7 @@ cgen(Node *np)
                return NULL;
 
        setlabel(np->label);
-        if (np->op != OCALL) {
+        if (np->op != OCALL && np->op != OASK) {
                np->left = cgen(np->left);
                np->right = cgen(np->right);
        }
@@ -411,11 +448,11 @@ cgen(Node *np)
        case OCALL:
                return call(np);
        case OFIELD:
-       case OASK:
-       case OCOLON:
        case OAND:
        case OOR:
                abort();
+       case OASK:
+               return ternary(np);
        case OBRANCH:
                next = np->next;
                load(np, LOADL);

Reply via email to