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 *