shithub: scc

Download patch

ref: c25c5f047c289b9e5d0d07e73d80244ceb97786e
parent: 76bddee887ffd0d602cbbf5fc8e95869249943c5
author: Roberto E. Vargas Caballero <[email protected]>
date: Mon Sep 26 07:41:01 EDT 2016

[cc2-qbe] Implement switch statements

This is a first implementation of switches, which uses a if-else-if
chain. At this point we cannot implement any other form of switch
because we need support for indirect jump in qbe.

--- a/cc2/arch/qbe/cgen.c
+++ b/cc2/arch/qbe/cgen.c
@@ -414,6 +414,47 @@
 	return NULL;
 }
 
+static void
+swtch_if(Node *idx)
+{
+	Node aux1, aux2, *np;
+	Symbol *deflabel = NULL;
+
+	for (;;) {
+		np = delstmt();
+		setlabel(np->label);
+
+		switch (np->op) {
+		case OESWITCH:
+			if (deflabel) {
+				aux1.op = OJMP;
+				aux1.label = NULL;
+				aux1.u.sym = deflabel;
+				cgen(&aux1);
+			}
+			return;
+		case OCASE:
+			aux1 = *np;
+			aux1.op = OBRANCH;
+			aux1.label = NULL;
+			aux1.left = &aux2;
+
+			aux2.op = OEQ;
+			aux2.type = idx->type;
+			aux2.left = np->left;
+			aux2.right = idx;
+
+			cgen(&aux1);
+			break;
+		case ODEFAULT:
+			deflabel = np->u.sym;
+			break;
+		default:
+			abort();
+		}
+	}
+}
+
 static Node *
 rhs(Node *np, Node *ret)
 {
@@ -550,11 +591,6 @@
 		return lhs(l, ret);
 	case OFIELD:
 		return field(np, ret, 0);
-	case OCASE:
-	case ODEFAULT:
-	case OESWITCH:
-	case OBSWITCH:
-		/* TODO: implement these operators */
 	default:
 		abort();
 	}
@@ -585,6 +621,10 @@
 	case ORET:
 		p = (np->left) ? rhs(np->left, &ret) : NULL;
 		code(ASRET, NULL, p, NULL);
+		break;
+	case OBSWITCH:
+		p = rhs(np->left, &ret);
+		swtch_if(p);
 		break;
 	default:
 		rhs(np, &ret);