Skip to content

Commit

Permalink
i#511 drreg: export instr_is_reg_spill_or_restore()
Browse files Browse the repository at this point in the history
Exports instr_is_reg_spill_or_restore() for use in drreg or elsewhere.
With ARM support and other factors there are many forms a spill or restore
might take and it's best for DR to provide this type of query.

Review-URL: https://codereview.appspot.com/261370044
  • Loading branch information
derekbruening committed Sep 25, 2015
1 parent 4b16998 commit 58e8582
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 16 deletions.
1 change: 1 addition & 0 deletions api/docs/release.dox
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ Further non-compatibility-affecting changes include:
- Added instr_is_sse() and instr_is_sse2().
- Added instr_is_3DNow(), instr_is_sse3(), and instr_is_ssse3().
- Added instr_is_sse41(), instr_is_sse42(), and instr_is_sse4A().
- Added instr_is_reg_spill_or_restore().

**************************************************
<hr>
Expand Down
10 changes: 5 additions & 5 deletions core/arch/arm/mangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ find_prior_scratch_reg_restore(dcontext_t *dcontext, instr_t *instr, reg_id_t *p
instr_is_label(prev) && instr_is_our_mangling(prev))
prev = instr_get_prev(prev);
if (prev != NULL &&
instr_is_reg_spill_or_restore(dcontext, prev, &tls, &spill, prior_reg)) {
instr_is_DR_reg_spill_or_restore(dcontext, prev, &tls, &spill, prior_reg)) {
if (tls && !spill &&
*prior_reg >= SCRATCH_REG0 && *prior_reg <= SCRATCH_REG3)
return prev;
Expand All @@ -461,8 +461,8 @@ insert_save_to_tls_if_necessary(dcontext_t *dcontext, instrlist_t *ilist,
STATS_INC(non_mbr_spills);
prev = find_prior_scratch_reg_restore(dcontext, where, &prior_reg);
if (INTERNAL_OPTION(opt_mangle) > 0 && prev != NULL && prior_reg == reg) {
ASSERT(instr_is_reg_spill_or_restore(dcontext, prev, &tls,
&spill, &prior_reg) &&
ASSERT(instr_is_DR_reg_spill_or_restore(dcontext, prev, &tls,
&spill, &prior_reg) &&
tls && !spill && prior_reg == reg);
/* remove the redundant restore-spill pair */
instrlist_remove(ilist, prev);
Expand Down Expand Up @@ -710,7 +710,7 @@ mangle_syscall_arch(dcontext_t *dcontext, instrlist_t *ilist, uint flags,
* For now we assume that the kernel honors the calling convention
* and won't clobber callee-saved regs.
*/
/* The instructions inserted here are checked in instr_is_reg_spill_or_restore
/* The instructions inserted here are checked in instr_is_DR_reg_spill_or_restore
* and translate_walk_restore, so any update here must be sync-ed there too.
*/
if (dr_reg_stolen != DR_REG_R10 && dr_reg_stolen != DR_REG_R11) {
Expand Down Expand Up @@ -809,7 +809,7 @@ mangle_add_predicated_fall_through(dcontext_t *dcontext, instrlist_t *ilist,
instr_t *prev = instr_get_next(mangle_start);
for (; prev != next_instr; prev = instr_get_next(prev)) {
if (instr_is_app(prev) ||
!instr_is_reg_spill_or_restore(dcontext, prev, NULL, NULL, NULL))
!instr_is_DR_reg_spill_or_restore(dcontext, prev, NULL, NULL, NULL))
instr_set_predicate(prev, pred);
}
}
Expand Down
21 changes: 19 additions & 2 deletions core/arch/instr.h
Original file line number Diff line number Diff line change
Expand Up @@ -2691,9 +2691,26 @@ bool instr_is_tls_xcx_spill(instr_t *instr);
/* Pass REG_NULL to not care about the reg */
bool
instr_is_tls_restore(instr_t *instr, reg_id_t reg, ushort offs);

DR_API
/**
* Returns whether \p instr is a register spill or restore, whether it was
* created by dr_save_reg(), dr_restore_reg(), dr_insert_read_raw_tls(),
* dr_insert_write_raw_tls(), routines that call the aforementioned routines
* (e.g., dr_save_arith_flags()), or DR's own internal spills and restores.
* Returns information about the spill/restore in the OUT parameters.
* The returned \p offs is the raw offset in bytes from the TLS segment base,
* the stolen register base, or the thread-private context area.
*/
bool
instr_is_reg_spill_or_restore(dcontext_t *dcontext, instr_t *instr,
bool *tls, bool *spill, reg_id_t *reg);
instr_is_reg_spill_or_restore(void *drcontext, instr_t *instr,
bool *tls OUT, bool *spill OUT, reg_id_t *reg OUT,
uint *offs OUT);

bool
instr_is_DR_reg_spill_or_restore(void *drcontext, instr_t *instr,
bool *tls OUT, bool *spill OUT, reg_id_t *reg OUT);

#ifdef ARM
bool instr_reads_thread_register(instr_t *instr);
bool instr_is_stolen_reg_move(instr_t *instr, bool *save, reg_id_t *reg);
Expand Down
38 changes: 32 additions & 6 deletions core/arch/instr_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -3240,20 +3240,24 @@ instr_check_mcontext_spill_restore(dcontext_t *dcontext, instr_t *instr,
#endif
}

bool
instr_is_reg_spill_or_restore(dcontext_t *dcontext, instr_t *instr,
bool *tls, bool *spill, reg_id_t *reg)
static bool
instr_is_reg_spill_or_restore_ex(void *drcontext, instr_t *instr, bool DR_only,
bool *tls, bool *spill, reg_id_t *reg, uint *offs_out)
{
dcontext_t *dcontext = (dcontext_t *) drcontext;
int check_disp = 0; /* init to satisfy some compilers */
reg_id_t myreg;
CLIENT_ASSERT(instr != NULL, "internal error: NULL argument");
CLIENT_ASSERT(instr != NULL, "invalid NULL argument");
if (reg == NULL)
reg = &myreg;
if (instr_check_tls_spill_restore(instr, spill, reg, &check_disp)) {
int offs = reg_spill_tls_offs(*reg);
if (offs != -1 && check_disp == os_tls_offset((ushort)offs)) {
if (!DR_only ||
(offs != -1 && check_disp == os_tls_offset((ushort)offs))) {
if (tls != NULL)
*tls = true;
if (offs_out != NULL)
*offs_out = check_disp;
return true;
}
#ifdef ARM
Expand All @@ -3271,6 +3275,8 @@ instr_is_reg_spill_or_restore(dcontext_t *dcontext, instr_t *instr,
});
if (tls != NULL)
*tls = true;
if (offs_out != NULL)
*offs_out = check_disp;
return true;
}
#endif
Expand All @@ -3279,15 +3285,35 @@ instr_is_reg_spill_or_restore(dcontext_t *dcontext, instr_t *instr,
instr_check_mcontext_spill_restore(dcontext, instr, spill,
reg, &check_disp)) {
int offs = opnd_get_reg_dcontext_offs(dr_reg_fixer[*reg]);
if (offs != -1 && check_disp == offs) {
if (!DR_only ||
(offs != -1 && check_disp == offs)) {
if (tls != NULL)
*tls = false;
if (offs_out != NULL)
*offs_out = check_disp;
return true;
}
}
return false;
}

DR_API
bool
instr_is_reg_spill_or_restore(void *drcontext, instr_t *instr,
bool *tls, bool *spill, reg_id_t *reg, uint *offs)
{
return instr_is_reg_spill_or_restore_ex(drcontext, instr, false,
tls, spill, reg, offs);
}

bool
instr_is_DR_reg_spill_or_restore(void *drcontext, instr_t *instr,
bool *tls, bool *spill, reg_id_t *reg)
{
return instr_is_reg_spill_or_restore_ex(drcontext, instr, true,
tls, spill, reg, NULL);
}

/* N.B. : client meta routines (dr_insert_* etc.) should never use anything other
* then TLS_XAX_SLOT unless the client has specified a slot to use as we let the
* client use the rest. */
Expand Down
6 changes: 3 additions & 3 deletions core/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ translate_walk_track(dcontext_t *tdcontext, instr_t *inst, translate_walk_t *wal
for (r = 0; r < REG_SPILL_NUM; r++)
walk->reg_spilled[r] = false;
}
if (instr_is_reg_spill_or_restore(tdcontext, inst, &spill_tls, &spill, &reg)) {
if (instr_is_DR_reg_spill_or_restore(tdcontext, inst, &spill_tls, &spill, &reg)) {
r = reg - REG_START_SPILL;
ASSERT(r < REG_SPILL_NUM);
IF_ARM({
Expand Down Expand Up @@ -1637,7 +1637,7 @@ stress_test_recreate_state(dcontext_t *dcontext, fragment_t *f, instrlist_t *ili
*/
ASSERT(success_so_far /* ok to fail */ ||
(!res &&
(instr_is_reg_spill_or_restore(dcontext, in, NULL, NULL, NULL) ||
(instr_is_DR_reg_spill_or_restore(dcontext, in, NULL, NULL, NULL) ||
(!instr_reads_memory(in) && !instr_writes_memory(in)))));

/* check that xsp and xcx are adjusted properly */
Expand All @@ -1651,7 +1651,7 @@ stress_test_recreate_state(dcontext_t *dcontext, fragment_t *f, instrlist_t *ili
instr_check_xsp_mangling(dcontext, in, &xsp_adjust);
if (xsp_adjust != 0)
LOG(THREAD, LOG_INTERP, 3, " xsp_adjust=%d\n", xsp_adjust);
if (instr_is_reg_spill_or_restore(dcontext, in, NULL, &spill, &reg) &&
if (instr_is_DR_reg_spill_or_restore(dcontext, in, NULL, &spill, &reg) &&
reg == REG_XCX)
spill_xcx_outstanding = spill;
}
Expand Down

0 comments on commit 58e8582

Please sign in to comment.