shithub: scc

Download patch

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);