Skip to content

Commit

Permalink
Promote integers to 64 bits when loaded
Browse files Browse the repository at this point in the history
DTrace internally implements integers with 64-bit registers.  This
makes the manipulation of integers of different sizes simpler, by
avoiding a number of typecast operations.  But DTrace has also
loaded integers without promoting them appropriately.  E.g.,
((short)0xffff) has been treated as 0xffff rather than -1.

Promote signed integers to 64 bits when loading (if needed).

Add tests.  Specifically, typecasting should typically not be needed.
Therefore, operations such as x=y and x+y (of different types) should
work properly if integers are correctly represented in 64-bit registers.

Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Reviewed-by: Kris Van Hees <kris.van.hees@oracle.com>
  • Loading branch information
euloh authored and kvanhees committed Aug 4, 2022
1 parent 173361f commit 7e9ce1e
Show file tree
Hide file tree
Showing 5 changed files with 327 additions and 6 deletions.
25 changes: 19 additions & 6 deletions libdtrace/dt_cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -2129,6 +2129,22 @@ dt_cg_ldsize(dt_node_t *dnp, ctf_file_t *ctfp, ctf_id_t type, ssize_t *ret_size)
return ldstw[size];
}

/*
* Generate code to promote signed scalars (size < 64 bits) to native register
* size (64 bits).
*/
static void
dt_cg_promote(const dt_node_t *dnp, ssize_t size, dt_irlist_t *dlp,
dt_regset_t *drp)
{
if (dnp->dn_flags & DT_NF_SIGNED && size < sizeof(uint64_t)) {
int n = (sizeof(uint64_t) - size) * NBBY;

emit(dlp, BPF_ALU64_IMM(BPF_LSH, dnp->dn_reg, n));
emit(dlp, BPF_ALU64_IMM(BPF_ARSH, dnp->dn_reg, n));
}
}

static void
dt_cg_load_scalar(dt_node_t *dnp, uint_t op, ssize_t size, dt_irlist_t *dlp,
dt_regset_t *drp)
Expand All @@ -2145,12 +2161,7 @@ dt_cg_load_scalar(dt_node_t *dnp, uint_t op, ssize_t size, dt_irlist_t *dlp,
emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, BPF_REG_FP, DT_STK_SP));
emit(dlp, BPF_LOAD(op, dnp->dn_reg, dnp->dn_reg, 0));

if (dnp->dn_flags & DT_NF_SIGNED && size < sizeof(uint64_t)) {
int n = (sizeof(uint64_t) - size) * NBBY;

emit(dlp, BPF_ALU64_IMM(BPF_LSH, dnp->dn_reg, n));
emit(dlp, BPF_ALU64_IMM(BPF_ARSH, dnp->dn_reg, n));
}
dt_cg_promote(dnp, size, dlp, drp);
}

static void
Expand Down Expand Up @@ -2185,6 +2196,7 @@ dt_cg_load_var(dt_node_t *dst, dt_irlist_t *dlp, dt_regset_t *drp)
(size & (size - 1)) == 0);

emit(dlp, BPF_LOAD(ldstw[size], dst->dn_reg, dst->dn_reg, idp->di_offset));
dt_cg_promote(dst, size, dlp, drp);
}

return;
Expand Down Expand Up @@ -2225,6 +2237,7 @@ dt_cg_load_var(dt_node_t *dst, dt_irlist_t *dlp, dt_regset_t *drp)
emit(dlp, BPF_JUMP(lbl_done));
emitl(dlp, lbl_notnull,
BPF_LOAD(ldstw[size], dst->dn_reg, BPF_REG_0, 0));
dt_cg_promote(dst, size, dlp, drp);
dt_regset_free(drp, BPF_REG_0);

emitl(dlp, lbl_done,
Expand Down
116 changes: 116 additions & 0 deletions test/unittest/arithmetic/tst.cast-add.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* 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 promoted correctly for mixed-type adds.
* The .r results file can be generated by copying this file
* to a .c file and compiling the resulting C program.
*
* SECTION: Types, Operators, and Expressions/Arithmetic Operators
*/
/* @@runtest-opts: -qC -DUSE_AS_D_SCRIPT */

#ifndef USE_AS_D_SCRIPT
#include <stdio.h>
#endif

signed char c;
short s;
int i;
long long l;
unsigned char C;
unsigned short S;
unsigned int I;
unsigned long long L;

#ifdef USE_AS_D_SCRIPT
#define FMT " %d"
#define USE_FMT(f)
#else
char *fmt;
#define FMT fmt
#define USE_FMT(f) fmt = f;
#endif

#define TEST(x, y) \
x = -2; y = -3; printf(FMT, x + y); printf(FMT, y + x); \
x = -2; y = +3; printf(FMT, x + y); printf(FMT, y + x); \
x = +2; y = -3; printf(FMT, x + y); printf(FMT, y + x); \
x = +2; y = +3; printf(FMT, x + y); printf(FMT, y + x); printf("\n");

#ifdef USE_AS_D_SCRIPT
BEGIN
#else
int main(int c_unused, char *v_unused)
#endif
{
/* cast to signed char */
USE_FMT(" %hhd");
TEST(c, c)

/* cast to unsigned char */
USE_FMT(" %hhu");
TEST(C, c)
TEST(C, C)

/* cast to short */
USE_FMT(" %hd");
TEST(s, c)
TEST(s, C)
TEST(s, s)

/* cast to unsigned short */
USE_FMT(" %hu");
TEST(S, c)
TEST(S, C)
TEST(S, s)
TEST(S, S)

/* cast to int */
USE_FMT(" %d");
TEST(i, c)
TEST(i, C)
TEST(i, s)
TEST(i, S)
TEST(i, i)

/* cast to unsigned int */
USE_FMT(" %u");
TEST(I, c)
TEST(I, C)
TEST(I, s)
TEST(I, S)
TEST(I, i)
TEST(I, I)

/* cast to long long */
USE_FMT(" %lld");
TEST(l, c)
TEST(l, C)
TEST(l, s)
TEST(l, S)
TEST(l, i)
TEST(l, I)
TEST(l, l)

/* cast to unsigned long long */
USE_FMT(" %llu");
TEST(L, c)
TEST(L, C)
TEST(L, s)
TEST(L, S)
TEST(L, i)
TEST(L, I)
TEST(L, l)
TEST(L, L)

#ifdef USE_AS_D_SCRIPT
exit (0);
#else
return 0;
#endif
}
37 changes: 37 additions & 0 deletions test/unittest/arithmetic/tst.cast-add.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
-6 -6 6 6 -6 -6 6 6
251 251 1 1 255 255 5 5
250 250 6 6 250 250 6 6
-5 -5 1 1 -1 -1 5 5
251 251 1 1 255 255 5 5
-6 -6 6 6 -6 -6 6 6
65531 65531 1 1 65535 65535 5 5
251 251 1 1 255 255 5 5
65531 65531 1 1 65535 65535 5 5
65530 65530 6 6 65530 65530 6 6
-5 -5 1 1 -1 -1 5 5
251 251 1 1 255 255 5 5
-5 -5 1 1 -1 -1 5 5
65531 65531 1 1 65535 65535 5 5
-6 -6 6 6 -6 -6 6 6
4294967291 4294967291 1 1 4294967295 4294967295 5 5
251 251 1 1 255 255 5 5
4294967291 4294967291 1 1 4294967295 4294967295 5 5
65531 65531 1 1 65535 65535 5 5
4294967291 4294967291 1 1 4294967295 4294967295 5 5
4294967290 4294967290 6 6 4294967290 4294967290 6 6
-5 -5 1 1 -1 -1 5 5
251 251 1 1 255 255 5 5
-5 -5 1 1 -1 -1 5 5
65531 65531 1 1 65535 65535 5 5
-5 -5 1 1 -1 -1 5 5
4294967291 4294967291 1 1 4294967295 4294967295 5 5
-6 -6 6 6 -6 -6 6 6
18446744073709551611 18446744073709551611 1 1 18446744073709551615 18446744073709551615 5 5
251 251 1 1 255 255 5 5
18446744073709551611 18446744073709551611 1 1 18446744073709551615 18446744073709551615 5 5
65531 65531 1 1 65535 65535 5 5
18446744073709551611 18446744073709551611 1 1 18446744073709551615 18446744073709551615 5 5
4294967291 4294967291 1 1 4294967295 4294967295 5 5
18446744073709551611 18446744073709551611 1 1 18446744073709551615 18446744073709551615 5 5
18446744073709551610 18446744073709551610 6 6 18446744073709551610 18446744073709551610 6 6

112 changes: 112 additions & 0 deletions test/unittest/arithmetic/tst.cast-imp.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* 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. (implicit)
* The .r results file can be generated by copying this file
* to a .c file and compiling the resulting C program.
*
* SECTION: Types, Operators, and Expressions/Arithmetic Operators
*/
/* @@runtest-opts: -qC -DUSE_AS_D_SCRIPT */

#ifndef USE_AS_D_SCRIPT
#include <stdio.h>
#endif

signed char c, c0;
short s, s0;
int i, i0;
long long l, l0;
unsigned char C, C0;
unsigned short S, S0;
unsigned int I, I0;
unsigned long long L, L0;

#ifdef USE_AS_D_SCRIPT
#define FMT "%d %d %d %d %d %d %d %d\n"
#else
#define FMT "%hhd %hd %d %lld %hhu %hu %u %llu\n"
#endif

#define TEST(x) \
c = (x); s = (x); i = (x); l = (x); \
C = (x); S = (x); I = (x); L = (x); \
printf(FMT, c, s, i, l, C, S, I, L)

#ifdef USE_AS_D_SCRIPT
BEGIN
#else
int main(int c_unused, char **v_unused)
#endif
{
/* from scalar */
TEST(-2);
TEST(0xfffffffffffffffe);
TEST(0xfffffffe);
TEST(0xfffe);
TEST(0xfe);
TEST(2);
TEST(0x55);
TEST(0x5555);
TEST(0x55555555);
TEST(0x5555555555555555);

/* from signed char */
c0 = -2; TEST(c0);
c0 = 0xfe; TEST(c0);
c0 = 2; TEST(c0);
c0 = 0x55; TEST(c0);

/* from short */
s0 = -2; TEST(s0);
s0 = 0xfffe; TEST(s0);
s0 = 2; TEST(s0);
s0 = 0x5555; TEST(s0);

/* from int */
i0 = -2; TEST(i0);
i0 = 0xfffffffe; TEST(i0);
i0 = 2; TEST(i0);
i0 = 0x55555555; TEST(i0);

/* from long long */
l0 = -2; TEST(l0);
l0 = 0xfffffffffffffffe; TEST(l0);
l0 = 2; TEST(l0);
l0 = 0x5555555555555555; TEST(l0);

/* from unsigned char */
C0 = -2; TEST(C0);
C0 = 0xfe; TEST(C0);
C0 = 2; TEST(C0);
C0 = 0x55; TEST(C0);

/* from unsigned short */
S0 = -2; TEST(S0);
S0 = 0xfffe; TEST(S0);
S0 = 2; TEST(S0);
S0 = 0x5555; TEST(S0);

/* from unsigned int */
I0 = -2; TEST(I0);
I0 = 0xfffffffe; TEST(I0);
I0 = 2; TEST(I0);
I0 = 0x55555555; TEST(I0);

/* from unsigned long long */
L0 = -2; TEST(L0);
L0 = 0xfffffffffffffffe; TEST(L0);
L0 = 2; TEST(L0);
L0 = 0x5555555555555555; TEST(L0);

#ifdef USE_AS_D_SCRIPT
exit (0);
#else
return 0;
#endif
}
43 changes: 43 additions & 0 deletions test/unittest/arithmetic/tst.cast-imp.r
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 7e9ce1e

Please sign in to comment.