shithub: scc

Download patch

ref: a4e43c119fe7f2c9e6f2c80b0092ac379fa8e4c7
parent: 2c2a9652ce246e092bcb3e3801d7ab434724fd45
author: Roberto E. Vargas Caballero <[email protected]>
date: Mon May 9 07:32:51 EDT 2016

[cc2-qbe] Ensure correctness of basic blocks

We have to take care of how basic blocks are built in QBE,
so we have to ensure that all the basic blocks of the program
are finalized with a jump of any type. We also need a label
in the next statement of a branch, because in branches in QBE
we have to use one label for true and another one for false.

--- a/cc2/arch/qbe/optm.c
+++ b/cc2/arch/qbe/optm.c
@@ -7,12 +7,32 @@
 Node *
 optm(Node *np)
 {
+	int op = np->op;
 	Node *p, *dst, *next = np->next;
 	Symbol *sym, *osym;
 
-	switch (np->op) {
+	if (!next) {
+		/*
+		 * In QBE we need at the end of a basic block
+		 * a jump, so we have to ensure that the last
+		 * statement of the function is a ret, a jmp
+		 * or a branch. In the same way, QBE does
+		 * not accept labels at the end of a function
+		 * (ONOP is used for labels) so we have to add
+		 * a ret there, and in the case of branches
+		 * we need a label for the next statement
+		 */
+		if (op == ONOP || op == OBRANCH || (op != ORET && op != OJMP)) {
+			p = newnode();
+			p->op = ORET;
+			addstmt(p, KEEPCUR);
+		}
+		next = np->next;
+	}
+
+	switch (op) {
 	case ONOP:
-		if (next && next->op == ONOP) {
+		if (next->op == ONOP) {
 			sym = np->u.sym;
 			osym = next->u.sym;
 			osym->id = sym->id;
@@ -21,8 +41,13 @@
 			return NULL;
 		}
 		break;
-	case OJMP:
 	case OBRANCH:
+		if (!next->label) {
+			sym = getsym(TMPSYM);
+			sym->kind = SLABEL;
+			next->label = sym;
+		}
+	case OJMP:
 		for (;;) {
 			dst = np->u.sym->u.stmt;
 			if (dst->op != OJMP)