scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit a7de023df75d9812c925ec5655be09ef0c02646e
parent 68d883b47e13b145757532c4f9fb77df515eb613
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 12 Nov 2021 08:08:06 +0100

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.

Diffstat:
Msrc/cmd/cc/cc2/target/qbe/cgen.c | 38+++++++++++++++++++-------------------
1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/src/cmd/cc/cc2/target/qbe/cgen.c b/src/cmd/cc/cc2/target/qbe/cgen.c @@ -511,47 +511,47 @@ assignop(Type *tp) 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; 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 *