commit 12586fdbde8bc3b7715a93dadf32a051699c04c8
parent 61e2e3177d38dc8a7b798a370408d58901e3d550
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 7 Jun 2016 09:32:16 +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.
Diffstat:
1 file changed, 40 insertions(+), 3 deletions(-)
diff --git 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);