Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 170 additions & 13 deletions valgrind/fjalar/kvasir/dyncomp_translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,158 @@ UInt numConsts = 0;
// as one big switch statement for now in order to provide
// flexibility for future edits

/* Returns true if ty is a floating-point or vector type. */
static
Bool isFloatOrVectorType_DC ( IRType ty )
{
switch (ty) {
case Ity_F16: case Ity_F32: case Ity_F64: case Ity_F128:
case Ity_D32: case Ity_D64: case Ity_D128:
case Ity_V128: case Ity_V256:
return True;
default:
return False;
}
}

/* Handles an IROp that DynComp does not handle. By default, panics.
With --dyncomp-unhandled-ops=warn, prints a warning the first time
that each IROp is encountered and returns the tag of an approximation
of the operation.

The approximation guesses each operand's role from its type, as given
by typeOfPrimop:
* A first operand of type I32 is a rounding mode if the result or
another operand is a floating-point or vector value.
* A later operand of type I8 is a shift amount or lane index if the
first operand is not also of type I8.
Rounding modes, shift amounts, and lane indices do not interact with
anything. The other operands are "data operands".
* If the result has type I1 and there are 2 data operands, the
operation is a comparison: the data operands' tags are merged, and
the result has no tag.
* Otherwise, the data operands' tags are merged and the result gets
the merged tag. In units and comparisons modes, the operation is
instead treated as a non-interaction, because it might be (for
example) a multiplication.
With --dyncomp-interactions=none, the operation is a non-interaction.

atoms and vatoms hold the nargs operands and their tags. */
static
IRAtom* approximate_unhandled_op_DC ( IROp op, Int nargs,
IRAtom** atoms, IRAtom** vatoms,
const HChar* where )
{
static Bool warned[Iop_LAST - Iop_INVALID];
IRType t_dst, t_arg[4];
Bool isData[4];
IRAtom* data[4];
Int i, nDataTypes = 0, nData = 0;
Bool isRoundingMode = False, isComparison, isInteraction;
const HChar* description;

if (!dyncomp_warn_unhandled_ops) {
ppIROp(op);
VG_(printf)("\nUnhandled IROp: 0x%x\n", (UInt)op);
VG_(tool_panic)(where);
}

tl_assert(op > Iop_INVALID && op < Iop_LAST);
tl_assert(nargs >= 2 && nargs <= 4);

typeOfPrimop(op, &t_dst, &t_arg[0], &t_arg[1], &t_arg[2], &t_arg[3]);

if (t_arg[0] == Ity_I32) {
isRoundingMode = isFloatOrVectorType_DC(t_dst);
for (i = 1; i < nargs; i++) {
isRoundingMode |= isFloatOrVectorType_DC(t_arg[i]);
}
}
for (i = 0; i < nargs; i++) {
if (i == 0) {
isData[i] = !isRoundingMode;
} else {
isData[i] = !(t_arg[i] == Ity_I8 && t_arg[0] != Ity_I8);
}
if (isData[i]) {
nDataTypes++;
}
}

isComparison = (t_dst == Ity_I1 && nDataTypes == 2);
isInteraction = (!dyncomp_dataflow_only_mode
&& (isComparison
|| !(dyncomp_units_mode
|| dyncomp_dataflow_comparisons_mode)));

if (!warned[op - Iop_INVALID]) {
warned[op - Iop_INVALID] = True;
if (!isInteraction) {
description = "treating it as a non-interaction";
} else if (isComparison) {
description = "treating it as a comparison of its operands";
} else {
description = "merging the tags of its operands";
}
VG_(printf)("Warning: DynComp does not handle IROp ");
ppIROp(op);
VG_(printf)(" (0x%x) in %s; %s", (UInt)op, where, description);
if (nDataTypes < nargs) {
VG_(printf)(" (other than rounding modes, shift amounts, and"
" lane indices)");
}
VG_(printf)(". Its comparability may be imprecise.\n");
}

if (!isInteraction) {
return IRExpr_Const(IRConst_UWord(0));
}

// A constant has no tag, so it need not be merged.
for (i = 0; i < nargs; i++) {
if (isData[i] && atoms[i]->tag != Iex_Const) {
data[nData++] = vatoms[i];
}
}

if (isComparison) {
if (nData < 2) {
return IRExpr_Const(IRConst_UWord(0));
}
return mkIRExprCCall (Ity_Word,
2 /*Int regparms*/,
"MC_(helperc_MERGE_TAGS_RETURN_0)",
&MC_(helperc_MERGE_TAGS_RETURN_0),
mkIRExprVec_2( data[0], data[1] ));
}

switch (nData) {
case 0:
return IRExpr_Const(IRConst_UWord(0));
case 1:
return data[0];
case 2:
return mkIRExprCCall (Ity_Word,
2 /*Int regparms*/,
"MC_(helperc_MERGE_TAGS)",
&MC_(helperc_MERGE_TAGS),
mkIRExprVec_2( data[0], data[1] ));
case 3:
return mkIRExprCCall (Ity_Word,
3 /*Int regparms*/,
"MC_(helperc_MERGE_3_TAGS)",
&MC_(helperc_MERGE_3_TAGS),
mkIRExprVec_3( data[0], data[1], data[2] ));
default:
return mkIRExprCCall (Ity_Word,
3 /*Int regparms*/,
"MC_(helperc_MERGE_4_TAGS)",
&MC_(helperc_MERGE_4_TAGS),
mkIRExprVec_4( data[0], data[1], data[2],
data[3] ));
}
}

static
IRAtom* expr2tags_Qop_DC ( DCEnv* dce,
IROp op,
Expand Down Expand Up @@ -398,12 +550,13 @@ IRAtom* expr2tags_Qop_DC ( DCEnv* dce,
case Iop_Rotx64: // only used by mips

default:
ppIROp(op);
VG_(printf)("\nUnhandled IROp: 0x%x\n", (UInt)op);
VG_(tool_panic)("memcheck:expr2tags_Qop");
{
IRAtom* atoms[4] = { atom1, atom2, atom3, atom4 };
IRAtom* vatoms[4] = { vatom1, vatom2, vatom3, vatom4 };
return approximate_unhandled_op_DC( op, 4, atoms, vatoms,
"dyncomp:expr2tags_Qop_DC" );
}
}

VG_(tool_panic)("memcheck:expr2tags_Qop");
}

static
Expand Down Expand Up @@ -552,9 +705,12 @@ IRAtom* expr2tags_Triop_DC ( DCEnv* dce,
case Iop_2xMultU64Add128CarryOut: // only used by ppc

default:
ppIROp(op);
VG_(printf)("\nUnhandled IROp: 0x%x\n", (UInt)op);
VG_(tool_panic)("memcheck:expr2tags_Triop");
{
IRAtom* atoms[3] = { atom1, atom2, atom3 };
IRAtom* vatoms[3] = { vatom1, vatom2, vatom3 };
return approximate_unhandled_op_DC( op, 3, atoms, vatoms,
"dyncomp:expr2tags_Triop_DC" );
}
}

return IRExpr_Const(IRConst_UWord(0));
Expand Down Expand Up @@ -1566,12 +1722,13 @@ IRAtom* expr2tags_Binop_DC ( DCEnv* dce,
case Iop_RSqrtStep32Fx4: // only used by arm arm64
case Iop_RSqrtStep64Fx2: // only used by arm64

// Hopefully we will never get here if we've had had cases which
// handle every possible IR binary op. type (right?)
default:
ppIROp(op);
VG_(printf)("\nUnhandled IROp: 0x%x\n", (UInt)op);
VG_(tool_panic)("dyncomp:expr2tags_Binop_DC");
{
IRAtom* atoms[2] = { atom1, atom2 };
IRAtom* vatoms[2] = { vatom1, vatom2 };
return approximate_unhandled_op_DC( op, 2, atoms, vatoms,
"dyncomp:expr2tags_Binop_DC" );
}
}

// In this mode, NOTHING is an interaction:
Expand Down
11 changes: 11 additions & 0 deletions valgrind/fjalar/kvasir/kvasir_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ Bool dyncomp_units_mode = False; // Tries to be consistent with u
Bool dyncomp_dataflow_only_mode = False; // Nothing is an interaction
Bool dyncomp_dataflow_comparisons_mode = False; // Only comparisons are interactions

// If true, warn about (rather than panic on) a VEX IR operator (IROp) that
// DynComp does not handle.
Bool dyncomp_warn_unhandled_ops = False;


FILE* decls_fp = 0; // File pointer for .decls file (this will point
// to the same thing as dtrace_fp by default since
Expand Down Expand Up @@ -688,6 +692,9 @@ void fjalar_tool_print_usage()
" --dyncomp-interactions=units Only counts interactions that are consistent with units\n"
" --dyncomp-interactions=comparisons Only counts comparison operations as interactions\n"
" --dyncomp-interactions=none Tracks no interactions, just dataflow\n"
" --dyncomp-unhandled-ops=panic Stop at a VEX IR operator that DynComp does not handle (default)\n"
" --dyncomp-unhandled-ops=warn Warn once per unhandled VEX IR operator and approximate it\n"
" (comparability may be imprecise)\n"
"\n Debugging:\n"
" --kvasir-debug Print Kvasir-internal debug messages [--no-debug]\n"
" --dyncomp-debug Print DynComp debug messages (--dyncomp must also be on)\n"
Expand Down Expand Up @@ -732,6 +739,10 @@ Bool fjalar_tool_process_cmd_line_option(const HChar* arg)
else if VG_XACT_CLO(arg, "--dyncomp-interactions=all",
dyncomp_dataflow_only_mode, False) {
dyncomp_dataflow_comparisons_mode = dyncomp_units_mode = False; }
else if VG_XACT_CLO(arg, "--dyncomp-unhandled-ops=panic",
dyncomp_warn_unhandled_ops, False) {}
else if VG_XACT_CLO(arg, "--dyncomp-unhandled-ops=warn",
dyncomp_warn_unhandled_ops, True) {}
else if VG_YESNO_CLO(arg, "dyncomp-debug", dyncomp_print_debug_info) {}
else if VG_YESNO_CLO(arg, "dyncomp-trace", dyncomp_print_trace_all) {}
else if VG_YESNO_CLO(arg, "dyncomp-trace-merge", dyncomp_print_trace_info) {}
Expand Down
1 change: 1 addition & 0 deletions valgrind/fjalar/kvasir/kvasir_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ Bool dyncomp_delayed_trace;
Bool dyncomp_units_mode;
Bool dyncomp_dataflow_only_mode;
Bool dyncomp_dataflow_comparisons_mode;
Bool dyncomp_warn_unhandled_ops;

// Define MAX_DEBUG_INFO to turn on all sorts of
// debugging printouts. WARNING: you will get
Expand Down
Loading