aboutsummaryrefslogtreecommitdiff
path: root/tccgen.c
diff options
context:
space:
mode:
authorgrischka <grischka>2014-09-23 12:30:08 +0200
committergrischka <grischka>2014-09-23 12:30:08 +0200
commit9d7fb3336049243a16ce20ba907946d1de9e1c0d (patch)
tree9c0b9009b9447f0749a070a2d14df814b83bb15e /tccgen.c
parent87d879aa7b3a75245e5e1a0fe15ba08105457df2 (diff)
downloadtinycc-9d7fb3336049243a16ce20ba907946d1de9e1c0d.tar.gz
tinycc-9d7fb3336049243a16ce20ba907946d1de9e1c0d.tar.bz2
tccgen: use lvalue as result from bitfield assignment
test case: #include <stdio.h> int main(int argc, char **argv) { struct _s { unsigned a:9, b:5, c:7; } _s, *s = &_s; int n = 250; s->a = s->b = s->c = n + 4; printf("--> %d / %d / %d\n", s->a, s->b, s->c); return 0; } before: --> 254 / 30 / 126 now: --> 30 / 30 / 126
Diffstat (limited to 'tccgen.c')
-rw-r--r--tccgen.c12
1 files changed, 5 insertions, 7 deletions
diff --git a/tccgen.c b/tccgen.c
index 5fd127f..d456a2a 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -2520,16 +2520,15 @@ ST_FUNC void vstore(void)
/* leave source on stack */
} else if (ft & VT_BITFIELD) {
/* bitfield store handling */
+
+ /* save lvalue as expression result (example: s.b = s.a = n;) */
+ vdup(), vtop[-1] = vtop[-2];
+
bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
/* remove bit field info to avoid loops */
vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
- /* duplicate source into other register */
- gv_dup();
- vswap();
- vrott(3);
-
if((ft & VT_BTYPE) == VT_BOOL) {
gen_cast(&vtop[-1].type);
vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
@@ -2561,8 +2560,7 @@ ST_FUNC void vstore(void)
gen_op('|');
/* store result */
vstore();
-
- /* pop off shifted source from "duplicate source..." above */
+ /* ... and discard */
vpop();
} else {