ref: a9a44d981e099805a308e04d285c9d8f13bdb707
parent: 0a32c4a074ed8411162f5d26b24dcf3206ba3bd6
author: Roberto E. Vargas Caballero <[email protected]>
date: Tue Jun 7 05:32:16 EDT 2016
[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.
--- a/cc2/arch/qbe/cgen.c
+++ b/cc2/arch/qbe/cgen.c
@@ -315,6 +315,43 @@
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 @@
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 @@
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);