Skip to content

Commit

Permalink
cg: support casts of pointers to integers
Browse files Browse the repository at this point in the history
When we cast a pointer to an integer, we want to scalarize it,
i.e. ensure that it is no longer a map_value, so that the user can
compare it freely to other integers.

Add a new DMST_SCALARIZER field to the machine state that anyone
can stuff map_values into and pull them right back out of to
scalarize them.

Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
Reviewed-by: Kris Van Hees <kris.van.hees@oracle.com>
  • Loading branch information
nickalcock committed Apr 19, 2022
1 parent 82bf9e8 commit 843ce03
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 1 deletion.
20 changes: 19 additions & 1 deletion libdtrace/dt_cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -2468,6 +2468,8 @@ dt_cg_store(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp, dt_node_t *dst)
* a scalar type is being narrowed or changing signed-ness. We first shift the
* desired bits high (losing excess bits if narrowing) and then shift them down
* using logical shift (unsigned result) or arithmetic shift (signed result).
*
* We also need to scalarize pointers if we are casting them to an integral type.
*/
static void
dt_cg_typecast(const dt_node_t *src, const dt_node_t *dst,
Expand All @@ -2489,11 +2491,27 @@ dt_cg_typecast(const dt_node_t *src, const dt_node_t *dst,
else
n = sizeof(uint64_t) * NBBY - srcsize * NBBY;

if (dt_node_is_scalar(dst) && n != 0 && (dstsize < srcsize ||
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)) {
int mst;

if ((mst = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);

emit(dlp, BPF_LOAD(BPF_DW, mst, BPF_REG_FP, DT_STK_DCTX));
emit(dlp, BPF_LOAD(BPF_DW, mst, mst, DCTX_MST));
emit(dlp, BPF_STORE(BPF_DW, mst, DMST_SCALARIZER, src->dn_reg));
emit(dlp, BPF_LOAD(BPF_DW, dst->dn_reg, mst, DMST_SCALARIZER));

dt_regset_free(drp, mst);
}
}

Expand Down
2 changes: 2 additions & 0 deletions libdtrace/dt_dctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ typedef struct dt_mstate {
uint32_t tag; /* Tag (for future use) */
uint32_t scratch_top; /* Current top of scratch space */
int32_t syscall_errno; /* syscall errno */
uint64_t scalarizer; /* used to scalarize pointers */
uint64_t fault; /* DTrace fault flags */
uint64_t tstamp; /* cached timestamp value */
dt_pt_regs regs; /* CPU registers */
Expand All @@ -36,6 +37,7 @@ typedef struct dt_mstate {
#define DMST_TAG offsetof(dt_mstate_t, tag)
#define DMST_SCRATCH_TOP offsetof(dt_mstate_t, scratch_top)
#define DMST_ERRNO offsetof(dt_mstate_t, syscall_errno)
#define DMST_SCALARIZER offsetof(dt_mstate_t, scalarizer)
#define DMST_FAULT offsetof(dt_mstate_t, fault)
#define DMST_TSTAMP offsetof(dt_mstate_t, tstamp)
#define DMST_REGS offsetof(dt_mstate_t, regs)
Expand Down

0 comments on commit 843ce03

Please sign in to comment.