[DTrace-devel] [PATCH] Fix typecast
Kris Van Hees
kris.van.hees at oracle.com
Mon Aug 1 19:15:21 UTC 2022
DTrace internally keeps integers basically in a 64-bit format. Shorter,
signed integers are already sign-extended.
The current logic makes an error when an integer is extended and the
signedness changes. It truncates the source and then extends. E.g.,
consider a 1-byte source and 2-byte destination:
signed?
src dst input expected currently
N Y 0xff 0x00ff -1
Y N 0xff 0xffff 0xff
Note:
*) In the first case, no casting is even necessary. If the integer
is being extended and it is unsigned, then higher-order bits can simply
be left alone.
*) In the second case, the signed input is supposed to be sign-extended
before truncating to the new size. We currently truncate first, at the
smaller size.
Fix. Add tests.
Notice that:
*) Casting constants like "var = (type) constant" is handled
in the parser.
*) Casting variables like "var1 = (type) var2" is handled
in the code generator.
This patch is a modified version of an earlier patch by Eugene Loh.
Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
Reviewed-by: Kris Van Hees <kris.van.hees at oracle.com>
---
libdtrace/dt_cg.c | 34 ++++----
libdtrace/dt_parser.c | 14 ++--
test/unittest/arithmetic/tst.cast-exp.d | 101 ++++++++++++++++++++++++
test/unittest/arithmetic/tst.cast-exp.r | 43 ++++++++++
4 files changed, 167 insertions(+), 25 deletions(-)
create mode 100644 test/unittest/arithmetic/tst.cast-exp.d
create mode 100644 test/unittest/arithmetic/tst.cast-exp.r
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 3e53c4bc..b40c9e48 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -2515,30 +2515,19 @@ dt_cg_typecast(const dt_node_t *src, const dt_node_t *dst,
{
size_t srcsize;
size_t dstsize;
- int n;
/* If the destination type is '@' (any type) we need not cast. */
if (dst->dn_ctfp == NULL && dst->dn_type == CTF_ERR)
return;
- srcsize = dt_node_type_size(src);
- dstsize = dt_node_type_size(dst);
-
- if (dstsize < srcsize)
- n = sizeof(uint64_t) * NBBY - dstsize * NBBY;
- else
- n = sizeof(uint64_t) * NBBY - srcsize * NBBY;
-
if (!dt_node_is_scalar(dst))
return;
- if (n != 0 && (dstsize < srcsize ||
- (src->dn_flags & DT_NF_SIGNED) ^ (dst->dn_flags & DT_NF_SIGNED))) {
- emit(dlp, BPF_MOV_REG(dst->dn_reg, src->dn_reg));
- emit(dlp, BPF_ALU64_IMM(BPF_LSH, dst->dn_reg, n));
- emit(dlp, BPF_ALU64_IMM((dst->dn_flags & DT_NF_SIGNED) ? BPF_ARSH : BPF_RSH, dst->dn_reg, n));
- } else if (dt_node_is_arith(dst) && dt_node_is_pointer(src) &&
- (src->dn_flags & DT_NF_ALLOCA)) {
+ srcsize = dt_node_type_size(src);
+ dstsize = dt_node_type_size(dst);
+
+ if (dt_node_is_arith(dst) && dt_node_is_pointer(src) &&
+ (src->dn_flags & DT_NF_ALLOCA)) {
int mst;
if ((mst = dt_regset_alloc(drp)) == -1)
@@ -2550,6 +2539,19 @@ dt_cg_typecast(const dt_node_t *src, const dt_node_t *dst,
emit(dlp, BPF_LOAD(BPF_DW, dst->dn_reg, mst, DMST_SCALARIZER));
dt_regset_free(drp, mst);
+ } else {
+ int srcsigned = src->dn_flags & DT_NF_SIGNED;
+ int dstsigned = dst->dn_flags & DT_NF_SIGNED;
+
+ if (dst->dn_reg != src->dn_reg)
+ emit(dlp, BPF_MOV_REG(dst->dn_reg, src->dn_reg));
+
+ if ((!srcsigned && dstsigned) && srcsize == dstsize) {
+ int n = (sizeof(uint64_t) - dstsize) * NBBY;
+
+ emit(dlp, BPF_ALU64_IMM(BPF_LSH, dst->dn_reg, n));
+ emit(dlp, BPF_ALU64_IMM(BPF_ARSH, dst->dn_reg, n));
+ }
}
}
diff --git a/libdtrace/dt_parser.c b/libdtrace/dt_parser.c
index 8cd4ec10..1625e887 100644
--- a/libdtrace/dt_parser.c
+++ b/libdtrace/dt_parser.c
@@ -2123,18 +2123,14 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
dt_node_is_integer(lp)) {
size_t srcsize = dt_node_type_size(rp);
size_t dstsize = dt_node_type_size(lp);
+ int srcsigned = rp->dn_flags & DT_NF_SIGNED;
+ int dstsigned = lp->dn_flags & DT_NF_SIGNED;
- if ((dstsize < srcsize) || ((lp->dn_flags & DT_NF_SIGNED) ^
- (rp->dn_flags & DT_NF_SIGNED))) {
- int n = dstsize < srcsize ?
- (sizeof(uint64_t) * NBBY - dstsize * NBBY) :
- (sizeof(uint64_t) * NBBY - srcsize * NBBY);
+ if ((!srcsigned && dstsigned) && srcsize == dstsize) {
+ int n = (sizeof(uint64_t) - dstsize) * NBBY;
rp->dn_value <<= n;
- if (lp->dn_flags & DT_NF_SIGNED)
- rp->dn_value = (intmax_t)rp->dn_value >> n;
- else
- rp->dn_value = rp->dn_value >> n;
+ rp->dn_value = (intmax_t)rp->dn_value >> n;
}
dt_node_type_propagate(lp, rp);
diff --git a/test/unittest/arithmetic/tst.cast-exp.d b/test/unittest/arithmetic/tst.cast-exp.d
new file mode 100644
index 00000000..6939586b
--- /dev/null
+++ b/test/unittest/arithmetic/tst.cast-exp.d
@@ -0,0 +1,101 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: Integers are typecast correctly. (explicit)
+ * Compare results to a similar C program,
+ * albeit with the format string
+ * "%hhd %hd %d %lld %hhu %hu %u %llu\n".
+ *
+ * SECTION: Types, Operators, and Expressions/Arithmetic Operators
+ */
+/* @@runtest-opts: -qC */
+
+signed char c;
+short s;
+int i;
+long long l;
+unsigned char C;
+unsigned short S;
+unsigned int I;
+unsigned long long L;
+
+#define TEST(x) \
+ c = (char)(x); \
+ s = (short)(x); \
+ i = (int)(x); \
+ l = (long long)(x); \
+ C = (unsigned char)(x); \
+ S = (unsigned short)(x); \
+ I = (unsigned int)(x); \
+ L = (unsigned long long)(x); \
+ printf("%d %d %d %d %d %d %d %d\n", c, s, i, l, C, S, I, L)
+
+BEGIN
+{
+ /* from scalar */
+ TEST(-2);
+ TEST(0xfffffffffffffffe);
+ TEST(0xfffffffe);
+ TEST(0xfffe);
+ TEST(0xfe);
+ TEST(2);
+ TEST(0x55);
+ TEST(0x5555);
+ TEST(0x55555555);
+ TEST(0x5555555555555555);
+
+ /* from char */
+ c = -2; TEST(c);
+ c = 0xfe; TEST(c);
+ c = 2; TEST(c);
+ c = 0x55; TEST(c);
+
+ /* from short */
+ s = -2; TEST(s);
+ s = 0xfffe; TEST(s);
+ s = 2; TEST(s);
+ s = 0x5555; TEST(s);
+
+ /* from int */
+ i = -2; TEST(i);
+ i = 0xfffffffe; TEST(i);
+ i = 2; TEST(i);
+ i = 0x55555555; TEST(i);
+
+ /* from long long */
+ l = -2; TEST(l);
+ l = 0xfffffffffffffffe; TEST(l);
+ l = 2; TEST(l);
+ l = 0x5555555555555555; TEST(l);
+
+ /* from unsigned char */
+ C = -2; TEST(C);
+ C = 0xfe; TEST(C);
+ C = 2; TEST(C);
+ C = 0x55; TEST(C);
+
+ /* from unsigned short */
+ S = -2; TEST(S);
+ S = 0xfffe; TEST(S);
+ S = 2; TEST(S);
+ S = 0x5555; TEST(S);
+
+ /* from unsigned int */
+ I = -2; TEST(I);
+ I = 0xfffffffe; TEST(I);
+ I = 2; TEST(I);
+ I = 0x55555555; TEST(I);
+
+ /* from unsigned long long */
+ L = -2; TEST(L);
+ L = 0xfffffffffffffffe; TEST(L);
+ L = 2; TEST(L);
+ L = 0x5555555555555555; TEST(L);
+
+ exit (0);
+}
diff --git a/test/unittest/arithmetic/tst.cast-exp.r b/test/unittest/arithmetic/tst.cast-exp.r
new file mode 100644
index 00000000..0ae3e3f1
--- /dev/null
+++ b/test/unittest/arithmetic/tst.cast-exp.r
@@ -0,0 +1,43 @@
+-2 -2 -2 -2 254 65534 4294967294 18446744073709551614
+-2 -2 -2 -2 254 65534 4294967294 18446744073709551614
+-2 -2 -2 4294967294 254 65534 4294967294 4294967294
+-2 -2 65534 65534 254 65534 65534 65534
+-2 254 254 254 254 254 254 254
+2 2 2 2 2 2 2 2
+85 85 85 85 85 85 85 85
+85 21845 21845 21845 85 21845 21845 21845
+85 21845 1431655765 1431655765 85 21845 1431655765 1431655765
+85 21845 1431655765 6148914691236517205 85 21845 1431655765 6148914691236517205
+-2 -2 -2 -2 254 65534 4294967294 18446744073709551614
+-2 -2 -2 -2 254 65534 4294967294 18446744073709551614
+2 2 2 2 2 2 2 2
+85 85 85 85 85 85 85 85
+-2 -2 -2 -2 254 65534 4294967294 18446744073709551614
+-2 -2 -2 -2 254 65534 4294967294 18446744073709551614
+2 2 2 2 2 2 2 2
+85 21845 21845 21845 85 21845 21845 21845
+-2 -2 -2 -2 254 65534 4294967294 18446744073709551614
+-2 -2 -2 -2 254 65534 4294967294 18446744073709551614
+2 2 2 2 2 2 2 2
+85 21845 1431655765 1431655765 85 21845 1431655765 1431655765
+-2 -2 -2 -2 254 65534 4294967294 18446744073709551614
+-2 -2 -2 -2 254 65534 4294967294 18446744073709551614
+2 2 2 2 2 2 2 2
+85 21845 1431655765 6148914691236517205 85 21845 1431655765 6148914691236517205
+-2 254 254 254 254 254 254 254
+-2 254 254 254 254 254 254 254
+2 2 2 2 2 2 2 2
+85 85 85 85 85 85 85 85
+-2 -2 65534 65534 254 65534 65534 65534
+-2 -2 65534 65534 254 65534 65534 65534
+2 2 2 2 2 2 2 2
+85 21845 21845 21845 85 21845 21845 21845
+-2 -2 -2 4294967294 254 65534 4294967294 4294967294
+-2 -2 -2 4294967294 254 65534 4294967294 4294967294
+2 2 2 2 2 2 2 2
+85 21845 1431655765 1431655765 85 21845 1431655765 1431655765
+-2 -2 -2 -2 254 65534 4294967294 18446744073709551614
+-2 -2 -2 -2 254 65534 4294967294 18446744073709551614
+2 2 2 2 2 2 2 2
+85 21845 1431655765 6148914691236517205 85 21845 1431655765 6148914691236517205
+
--
2.34.1
More information about the DTrace-devel
mailing list