aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2019-04-15 22:21:27 -0700
committerMichael Forney <mforney@mforney.org>2019-04-15 23:08:33 -0700
commit5eb638ef6c5e2b1abb927ad395aa6f15fcb3e92a (patch)
tree678c639a8c43593c7b8f4f577b9fce2adf071cca
parent4f56de1d1ae28ef3222577c8d38479a1ad1d2a99 (diff)
expr: Handle compound assignment of bit-fields
-rw-r--r--expr.c12
-rw-r--r--tests/bitfield-compound-assign.c7
-rw-r--r--tests/bitfield-compound-assign.qbe21
3 files changed, 39 insertions, 1 deletions
diff --git a/expr.c b/expr.c
index f937947..28585c9 100644
--- a/expr.c
+++ b/expr.c
@@ -867,7 +867,7 @@ mkassignexpr(struct expr *l, struct expr *r)
struct expr *
assignexpr(struct scope *s)
{
- struct expr *e, *l, *r, *tmp;
+ struct expr *e, *l, *r, *tmp, *bit;
enum tokenkind op;
l = condexpr(s);
@@ -895,11 +895,21 @@ assignexpr(struct scope *s)
if (!op)
return mkassignexpr(l, r);
/* rewrite `E1 OP= E2` as `T = &E1, *T = *T OP E2`, where T is a temporary slot */
+ if (l->kind == EXPRBITFIELD) {
+ bit = l;
+ l = l->bitfield.base;
+ } else {
+ bit = NULL;
+ }
tmp = mkexpr(EXPRTEMP, mkpointertype(l->type, l->qual));
tmp->lvalue = true;
tmp->temp = NULL;
e = mkassignexpr(tmp, mkunaryexpr(TBAND, l));
l = mkunaryexpr(TMUL, tmp);
+ if (bit) {
+ bit->bitfield.base = l;
+ l = bit;
+ }
r = mkbinaryexpr(&tok.loc, op, l, r);
e->next = mkassignexpr(l, r);
l = mkexpr(EXPRCOMMA, l->type);
diff --git a/tests/bitfield-compound-assign.c b/tests/bitfield-compound-assign.c
new file mode 100644
index 0000000..5ca42e4
--- /dev/null
+++ b/tests/bitfield-compound-assign.c
@@ -0,0 +1,7 @@
+struct {
+ int : 4, x : 9, : 3;
+} s;
+
+void f(void) {
+ s.x += 3;
+}
diff --git a/tests/bitfield-compound-assign.qbe b/tests/bitfield-compound-assign.qbe
new file mode 100644
index 0000000..829f5f6
--- /dev/null
+++ b/tests/bitfield-compound-assign.qbe
@@ -0,0 +1,21 @@
+export
+function $f() {
+@start.1
+@body.2
+ %.1 =l copy $s
+ %.2 =l mul 0, 1
+ %.3 =l add %.1, %.2
+ %.4 =l copy %.3
+ %.5 =w loadsw %.4
+ %.6 =w shl %.5, 19
+ %.7 =w sar %.6, 23
+ %.8 =w add %.7, 3
+ %.9 =w loaduw %.4
+ %.10 =w and %.9, 18446744073709543439
+ %.11 =w shl %.8, 4
+ %.12 =w and %.11, 8176
+ %.13 =w or %.10, %.12
+ storew %.13, %.4
+ ret
+}
+export data $s = align 4 { z 4 }