aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linearize.c
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-07-08 10:24:01 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-08-07 13:31:12 +0200
commit0908755d71eec16da5ab1f9ef1019bdcab4f1857 (patch)
tree11625be82f448c00a3311d4dfa972f92cf0b6812 /linearize.c
parent7347750afb894047b5145637cdebd1613c33d64a (diff)
downloadsparse-dev-0908755d71eec16da5ab1f9ef1019bdcab4f1857.tar.gz
fix instruction size & type in linearize_inc_dec()
If the ++ or -- operator is used on a bitfield, the addition or subtraction is done with the size of the bitfield. So code like: struct { int f:3; } s; ... s->f++; will generate intermediate code like: add.3 %r <- %a, $1 This is not incorrect from the IR point of view but CPUs have only register-sized instructions, like 'add.32'. So, these odd-sized instruction have one or two implicit masking/extend that should better make explicit. Fix this by casting to and from the base type when these operators are used on bitfields. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Diffstat (limited to 'linearize.c')
-rw-r--r--linearize.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/linearize.c b/linearize.c
index 9a6fd250..3cb44847 100644
--- a/linearize.c
+++ b/linearize.c
@@ -1119,7 +1119,11 @@ static pseudo_t linearize_inc_dec(struct entrypoint *ep, struct expression *expr
one = add_setfval(ep, expr->ctype, expr->op_value);
else
one = value_pseudo(expr->op_value);
- new = add_binary_op(ep, expr->ctype, op, old, one);
+ if (ad.btype != ad.type)
+ old = cast_pseudo(ep, old, ad.type, ad.btype);
+ new = add_binary_op(ep, ad.btype, op, old, one);
+ if (ad.btype != ad.type)
+ new = cast_pseudo(ep, new, ad.btype, ad.type);
linearize_store_gen(ep, new, &ad);
return postop ? old : new;
}