shithub: scc

Download patch

ref: a7de023df75d9812c925ec5655be09ef0c02646e
parent: 68d883b47e13b145757532c4f9fb77df515eb613
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Fri Nov 12 03:08:06 EST 2021

cc2/qbe: Fix post increment and decrement

These operators use their operand as lhs and rhs, and assign()
was evaluating twice the operand. It didn't have effects with
simple variables but it created problems with more complex
expressions with side effects. The operand must be evaluated
only once, like a lhs and load it when it has to be used like
an rhs.

--- a/src/cmd/cc/cc2/target/qbe/cgen.c
+++ b/src/cmd/cc/cc2/target/qbe/cgen.c
@@ -511,11 +511,12 @@
 static Node *
 assign(Node *np)
 {
-	Node *tmp, aux;
+	Node *ret, aux;
 	Node *l = np->left, *r = np->right;
 	int op;
 
 	switch (np->u.subop) {
+		break;
 	case OINC:
 		op = OADD;
 		goto post_oper;
@@ -522,36 +523,35 @@
 	case ODEC:
 		op = OSUB;
 	post_oper:
-		tmp = rhs(l);
+		l = lhs(l);
+		ret = load(&l->type, l);
 		aux.op = op;
-		aux.left = tmp;
+		aux.left = ret;
 		aux.right = r;
 		aux.type = np->type;
-		r = complex(&aux);
+		r = rhs(&aux);
 		break;
 	default:
 		/* assign abbreviation */
-		aux.type = np->type;
 		aux.op = np->u.subop;
-		aux.right = np->right;
-		aux.left = np->left;
-		r = rhs(complex(&aux));
+		aux.left = l;
+		aux.right = r;
+		aux.type = np->type;
+		r = complex(&aux);
 	case 0:
-		op = 0;
+		if (l->complex >= r->complex) {
+			l = lhs(l);
+			r = rhs(r);
+		} else {
+			r = rhs(r);
+			l = lhs(l);
+		}
+		ret = r;
 		break;
 	}
 
-	if (l->complex >= r->complex) {
-		l = lhs(l);
-		r = rhs(r);
-	} else {
-		r = rhs(r);
-		l = lhs(l);
-	}
-
 	code(assignop(&np->type), l, r, NULL);
-
-	return (op == 0) ? r : tmp;
+	return ret;
 }
 
 static Node *