vbit-test

The program tests the effect of an undefined input bit to an IROp on the
definedness of the result of that operation. It also checks that only those
bits in the result are undefined that we expect to be undefined. That way
we can detect false positives (there are bits in the result that are
undefined but shouldn't) and false negatives (there are defined bits in
the result that should be undefined).

By design, the tester will always be in-synch with the list of IROps
in libvex_ir.h. Addition / removel of IROps will cause a compile or
runtime error of the tester and thusly will not go unnoticed.


How it works
------------
The underlying idea is to
(1) use VALGRIND_SET_VBITS to set the V-bits of the operands of an IROp
(2) execute that IROp
(3) use VALGRIND_GET_VBITS to obtain the V-bits of the result
(4) compare the result against our expectation
Do that for all IROps and for all input bits of their operands.
For all this to work, the tester must run under the auspices of memcheck.

The key step here is #2. To "execute an IROp" we need to inject some
IR into the the superblock. This is accomplished by adding a new "special
instruction" that is supported by all frontends. During the decoding step
that instruction will be recognised and a suitable piece of IR will be
inserted (function vex_inject_ir does just that). What is "suitable" depends
on the IROp at hand and its operands. We need to know the addresses of
those operands, their types and, trivially, which IROp we want to execute.
This information is collected in the IR Injection Control Block (IRICB).
To get the IRICB to VEX we use the new client request 
VG_USERREQ__VEX_INIT_FOR_IRI.


Invocation
----------
Use   vbit-test --help   to obtain list of supported command line flags.


Source code overview
--------------------
main.c
Contains the main loop that iterates over all IROps in libvex_ir.h.
Depending on the number of operands one of the functions test_unary,
test_binary, etc. will be invoked to run all tests for that opreator.

irops.c
List of IROps. For each operator it defines how undefined input bits
influence the output (result) and whether the operator is supported on a
given architecture.

util.c
Miscellaneous convenience functions. It also includes sizeof_irtype and
typeof_primop which were imported from VEX/priv/ir_defs.c.

unary.c
The function test_unary_op is the work horse. It iterates over all input
bits of the single operand. For each such bit, the corresponding V-bit will
be set to undefined, the IROps is executed and the resulting V-bits will
be compared against the expected result.
The function check_result_for_unary will check the V-bits for correctness.

binary.c, ternary.c, qernary.c
Like unary.c...

valgrind.c
The main function there is valgrind_execute_test. It will 
(1) set the V-bits of the operands using the VALGRIND_SET_VBITS mechanism,
(2) inject IR into the current IRSB to exacute a single IROp, and
(3) obtain the V-bits of the result using the VALGRIND_GET_VBITS mechanism.
The addresses of the operands and the result, as well as they V-bit vectors
are stored in the test_data_t structure.

<valgrind>/VEX/priv/ir_inject.c
The file provides the function vex_inject_ir which will inject a piece of
IR into the current IRSB based on the information provided in the IRICB.
That code snippet will perform a single IR operation

<valgrind>/include/valgrind.h
Defines the macro VALGRIND_VEX_INJECT_IR for all architectures.
Also defines a new client request VG_USERREQ__VEX_INIT_FOR_IRI.


Adding a new IROp
-----------------
The following steps are needed
(1) Add the operator to irops.c
(2) If the operator propagates undefinedness from input to output in a new
    way:
    (a) Add a new enumerator to undef_t and document it there.
    (b) Add a new case in function check_result_for_XYZ depending on the
        arity of the operator. The code snippet there is supposed to check
        that the result matches what we expect.


Status
------
vbit-test has been tested on x86-64, ppc64, s390x, and mips32.
There is support for other architectures in valgrind.h and guest_ARCH_toIR.c
but it has not been tested. 
