diff options
-rw-r--r-- | qbe.c | 14 | ||||
-rw-r--r-- | test/bitfield-short.c | 7 | ||||
-rw-r--r-- | test/bitfield-short.qbe | 14 |
3 files changed, 30 insertions, 5 deletions
@@ -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; } diff --git a/test/bitfield-short.c b/test/bitfield-short.c new file mode 100644 index 0000000..b0be6fd --- /dev/null +++ b/test/bitfield-short.c @@ -0,0 +1,7 @@ +struct { + short x : 7; +} s = {.x = -64}; + +int main(void) { + return s.x > 0; +} diff --git a/test/bitfield-short.qbe b/test/bitfield-short.qbe new file mode 100644 index 0000000..e8bc086 --- /dev/null +++ b/test/bitfield-short.qbe @@ -0,0 +1,14 @@ +export data $s = align 2 { b 64, z 1 } +export +function w $main() { +@start.1 +@body.2 + %.1 =l mul 0, 1 + %.2 =l add $s, %.1 + %.3 =w loadsh %.2 + %.4 =w shl %.3, 25 + %.5 =w sar %.4, 25 + %.6 =w extsh %.5 + %.7 =w csgtw %.6, 0 + ret %.7 +} |