scc

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

commit 9ee4cece6aca3287438981fe8c6c10b274cc0bc2
parent 2b1cab704ca1f2538a50a801a0af9ec3d09f8c38
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 *