diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-08-13 06:15:36 +0200 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-08-17 05:18:37 +0200 |
commit | b987e1d1319678d87049f415acd2ce16ba5e5263 (patch) | |
tree | 4b52b4247ceb1cf5dd781e1932d7d19c6b1561fe | |
parent | 49f7e13a7ac9a582d11e9c1ad01e71740f486601 (diff) | |
download | sparse-b987e1d1319678d87049f415acd2ce16ba5e5263.tar.gz |
fix evaluate_ptr_add() when sizeof(offset) != sizeof(pointer)
For a binary op, both sides need to be converted to the resulting
type of the usual conversion. For a compound-assignment (which
is equivalent to a binary op followed by an assignment), the LHS
can't be so converted since its type needs to be preserved for
the assignment, so only the RHS is converted at evaluation and
the type of the RHS is used at linearization to convert the LHS.
However, in the case of pointer arithmetics, a number of shortcuts
are taken and as a result additions with mixed sizes can be produced
producing invalid IR.
So, fix this by converting the RHS to the same size as pointers,
as done for 'normal' binops.
Note: On 32-bit kernel, this patch also removes a few warnings
about non size-preserving casts. It's fine as these warnings
were designed for when an address would be stored in an
integer, not for storing an offset like it's the case here.
Reported-by: Valentin Schneider <valentin.schneider@arm.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r-- | evaluate.c | 4 | ||||
-rw-r--r-- | validation/linear/pointer-arith32.c | 94 | ||||
-rw-r--r-- | validation/linear/pointer-arith64.c | 79 |
3 files changed, 175 insertions, 2 deletions
@@ -619,7 +619,7 @@ static struct symbol *evaluate_ptr_add(struct expression *expr, struct symbol *i ctype = &ptr_ctype; expr->ctype = ctype; - if (multiply == 1 && itype->bit_size >= bits_in_pointer) + if (multiply == 1 && itype->bit_size == bits_in_pointer) return ctype; if (index->type == EXPR_VALUE) { @@ -639,7 +639,7 @@ static struct symbol *evaluate_ptr_add(struct expression *expr, struct symbol *i return ctype; } - if (itype->bit_size < bits_in_pointer) + if (itype->bit_size != bits_in_pointer) index = cast_to(index, ssize_t_ctype); if (multiply > 1) { diff --git a/validation/linear/pointer-arith32.c b/validation/linear/pointer-arith32.c new file mode 100644 index 00000000..531fd232 --- /dev/null +++ b/validation/linear/pointer-arith32.c @@ -0,0 +1,94 @@ +char *cps(char *data, short pos) +{ + data += pos; + return data; +} + +int *ipss(int *data, short pos) +{ + data += pos; + return data; +} +int *ipus(int *data, unsigned short pos) +{ + data += pos; + return data; +} + +char *cpq(char *data, long long pos) +{ + data += pos; + return data; +} + +int *ipq_ref(int *data, long long pos) +{ + data = data + pos; + return data; +} + +int *ipq(int *data, long long pos) +{ + data += pos; + return data; +} + +/* + * check-name: pointer-arith32 + * check-command: test-linearize -Wno-decl --arch=generic -m32 $file + * + * check-output-start +cps: +.L0: + <entry-point> + sext.32 %r2 <- (16) %arg2 + add.32 %r5 <- %arg1, %r2 + ret.32 %r5 + + +ipss: +.L2: + <entry-point> + sext.32 %r10 <- (16) %arg2 + mul.32 %r11 <- %r10, $4 + add.32 %r14 <- %arg1, %r11 + ret.32 %r14 + + +ipus: +.L4: + <entry-point> + zext.32 %r19 <- (16) %arg2 + mul.32 %r20 <- %r19, $4 + add.32 %r23 <- %arg1, %r20 + ret.32 %r23 + + +cpq: +.L6: + <entry-point> + trunc.32 %r28 <- (64) %arg2 + add.32 %r31 <- %arg1, %r28 + ret.32 %r31 + + +ipq_ref: +.L8: + <entry-point> + trunc.32 %r37 <- (64) %arg2 + mul.32 %r38 <- %r37, $4 + add.32 %r39 <- %arg1, %r38 + ret.32 %r39 + + +ipq: +.L10: + <entry-point> + trunc.32 %r43 <- (64) %arg2 + mul.32 %r44 <- %r43, $4 + add.32 %r47 <- %arg1, %r44 + ret.32 %r47 + + + * check-output-end + */ diff --git a/validation/linear/pointer-arith64.c b/validation/linear/pointer-arith64.c new file mode 100644 index 00000000..dad10331 --- /dev/null +++ b/validation/linear/pointer-arith64.c @@ -0,0 +1,79 @@ +char *cps(char *data, short pos) +{ + data += pos; + return data; +} + +int *ipss(int *data, short pos) +{ + data += pos; + return data; +} +int *ipus(int *data, unsigned short pos) +{ + data += pos; + return data; +} + +int *ipsi(int *data, int pos) +{ + data += pos; + return data; +} +int *ipui(int *data, unsigned int pos) +{ + data += pos; + return data; +} + +/* + * check-name: pointer-arith64 + * check-command: test-linearize -Wno-decl --arch=generic -m64 $file + * + * check-output-start +cps: +.L0: + <entry-point> + sext.64 %r2 <- (16) %arg2 + add.64 %r5 <- %arg1, %r2 + ret.64 %r5 + + +ipss: +.L2: + <entry-point> + sext.64 %r10 <- (16) %arg2 + mul.64 %r11 <- %r10, $4 + add.64 %r14 <- %arg1, %r11 + ret.64 %r14 + + +ipus: +.L4: + <entry-point> + zext.64 %r19 <- (16) %arg2 + mul.64 %r20 <- %r19, $4 + add.64 %r23 <- %arg1, %r20 + ret.64 %r23 + + +ipsi: +.L6: + <entry-point> + sext.64 %r28 <- (32) %arg2 + mul.64 %r29 <- %r28, $4 + add.64 %r32 <- %arg1, %r29 + ret.64 %r32 + + +ipui: +.L8: + <entry-point> + zext.64 %r37 <- (32) %arg2 + mul.64 %r38 <- %r37, $4 + add.64 %r41 <- %arg1, %r38 + ret.64 %r41 + + + * check-output-end + */ |