aboutsummaryrefslogtreecommitdiff
path: root/qbe.c
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2021-07-05 22:26:52 -0700
committerMichael Forney <mforney@mforney.org>2021-07-05 22:26:57 -0700
commit7bf0c0fb11af04d50cf7c374a44aa6101cca9c9d (patch)
tree4a54ad7462e00b49e2e7b981daedcd94f408ed5a /qbe.c
parent003f6a14b05bb16fa6f950dc193a8cbd62e0836d (diff)
qbe: Fix bitfield sign extension with types shorter than int
Diffstat (limited to 'qbe.c')
-rw-r--r--qbe.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/qbe.c b/qbe.c
index 44742c0..d108479 100644
--- a/qbe.c
+++ b/qbe.c
@@ -280,13 +280,17 @@ funcalloc(struct func *f, struct decl *d)
static struct value *
funcbits(struct func *f, struct type *t, struct value *v, struct bitfield b)
{
- int class;
+ int class, bits;
class = t->size <= 4 ? 'w' : 'l';
- if (b.after)
- v = funcinst(f, ISHL, class, v, mkintconst(b.after));
- if (b.before + b.after)
- v = funcinst(f, t->basic.issigned ? ISAR : ISHR, class, v, mkintconst(b.before + b.after));
+ bits = b.after;
+ if (bits) {
+ bits += (t->size + 3 & ~3) - t->size << 3;
+ v = funcinst(f, ISHL, class, v, mkintconst(bits));
+ }
+ bits += b.before;
+ if (bits)
+ v = funcinst(f, t->basic.issigned ? ISAR : ISHR, class, v, mkintconst(bits));
return v;
}