diff options
| author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-08-23 16:43:08 +0200 |
|---|---|---|
| committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-11-01 00:40:57 +0100 |
| commit | 226b62bc2ee4779447ce788d83aa0b409e384ec8 (patch) | |
| tree | ace913c378dd4085c34112c9e8602a7b39f75c27 /linearize.c | |
| parent | 594c7389969f79919f1170693c970fb25b8bfe4d (diff) | |
| download | sparse-dev-226b62bc2ee4779447ce788d83aa0b409e384ec8.tar.gz | |
eval_insn: give an explicit type to compare's operands
The return type of IR instructions is stored in the field
::type of struct instruction and this struct has no space
to hold the type of the operand(s). This is not a problem
for most instructions because there is an easy way to get
the operands' type. For example, for binops both types
must be the same so they are used interchangeably.
However, for compare instructions both types can be different
and there is no easy way to get the type of the operands.
Currently, this is ignored and creates some errors. It
also blocks simplifications that need this type information.
But compares instructions need only 2 operands, there is
thus one 'slot' left. So, use this slot for the operands' type.
This solves the current errors, allows new simplifications
and has very little impact on existing code. Of course,
this type information needs now to be tracked and adjusted
whenever the operands change or an instruction is changed
into a compare.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Diffstat (limited to 'linearize.c')
| -rw-r--r-- | linearize.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/linearize.c b/linearize.c index d9a3ac49..301a5d9e 100644 --- a/linearize.c +++ b/linearize.c @@ -1080,6 +1080,13 @@ static pseudo_t add_binary_op(struct entrypoint *ep, struct symbol *ctype, int o return target; } +static pseudo_t add_cmp_op(struct entrypoint *ep, struct symbol *ctype, int op, struct symbol *itype, pseudo_t left, pseudo_t right) +{ + pseudo_t target = add_binary_op(ep, ctype, op, left, right); + target->def->itype = itype; + return target; +} + static pseudo_t add_setval(struct entrypoint *ep, struct symbol *ctype, struct expression *val) { struct instruction *insn = alloc_typed_instruction(OP_SETVAL, ctype); @@ -1217,7 +1224,7 @@ static pseudo_t linearize_regular_preop(struct entrypoint *ep, struct expression return pre; case '!': { pseudo_t zero = value_pseudo(0); - return add_binary_op(ep, ctype, OP_SET_EQ, pre, zero); + return add_cmp_op(ep, ctype, OP_SET_EQ, expr->unop->ctype, pre, zero); } case '~': return add_unop(ep, ctype, OP_NOT, pre); @@ -1444,7 +1451,7 @@ static inline pseudo_t add_convert_to_bool(struct entrypoint *ep, pseudo_t src, zero = value_pseudo(0); op = OP_SET_NE; } - return add_binary_op(ep, &bool_ctype, op, src, zero); + return add_cmp_op(ep, &bool_ctype, op, type, src, zero); } static pseudo_t linearize_expression_to_bool(struct entrypoint *ep, struct expression *expr) @@ -1773,10 +1780,11 @@ static pseudo_t linearize_compare(struct entrypoint *ep, struct expression *expr [SPECIAL_UNSIGNED_LTE] = OP_SET_BE, [SPECIAL_UNSIGNED_GTE] = OP_SET_AE, }; - int op = opcode_float(cmpop[expr->op], expr->right->ctype); + struct symbol *itype = expr->right->ctype; + int op = opcode_float(cmpop[expr->op], itype); pseudo_t src1 = linearize_expression(ep, expr->left); pseudo_t src2 = linearize_expression(ep, expr->right); - pseudo_t dst = add_binary_op(ep, expr->ctype, op, src1, src2); + pseudo_t dst = add_cmp_op(ep, expr->ctype, op, itype, src1, src2); return dst; } |
