1
0
mirror of https://github.com/ioacademy-jikim/debugging synced 2026-08-31 09:49:38 +00:00

first commit

This commit is contained in:
jikim
2015-12-13 22:34:58 +09:00
commit 0b589c7986
9455 changed files with 4350134 additions and 0 deletions
@@ -0,0 +1,89 @@
vbit_test-binary.o: binary.c /usr/include/stdc-predef.h \
/usr/include/assert.h /usr/include/features.h \
/usr/include/i386-linux-gnu/sys/cdefs.h \
/usr/include/i386-linux-gnu/bits/wordsize.h \
/usr/include/i386-linux-gnu/gnu/stubs.h \
/usr/include/i386-linux-gnu/gnu/stubs-32.h /usr/include/string.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
/usr/include/i386-linux-gnu/bits/string.h \
/usr/include/i386-linux-gnu/bits/string2.h /usr/include/endian.h \
/usr/include/i386-linux-gnu/bits/endian.h \
/usr/include/i386-linux-gnu/bits/types.h \
/usr/include/i386-linux-gnu/bits/typesizes.h \
/usr/include/i386-linux-gnu/bits/string3.h vtest.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h /usr/include/stdint.h \
/usr/include/i386-linux-gnu/bits/wchar.h ../../../VEX/pub/libvex.h \
../../../VEX/pub/libvex_basictypes.h ../../../VEX/pub/libvex_ir.h \
vbits.h /usr/include/stdio.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
/usr/include/i386-linux-gnu/bits/stdio.h \
/usr/include/i386-linux-gnu/bits/stdio2.h
/usr/include/stdc-predef.h:
/usr/include/assert.h:
/usr/include/features.h:
/usr/include/i386-linux-gnu/sys/cdefs.h:
/usr/include/i386-linux-gnu/bits/wordsize.h:
/usr/include/i386-linux-gnu/gnu/stubs.h:
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
/usr/include/string.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
/usr/include/i386-linux-gnu/bits/string.h:
/usr/include/i386-linux-gnu/bits/string2.h:
/usr/include/endian.h:
/usr/include/i386-linux-gnu/bits/endian.h:
/usr/include/i386-linux-gnu/bits/types.h:
/usr/include/i386-linux-gnu/bits/typesizes.h:
/usr/include/i386-linux-gnu/bits/string3.h:
vtest.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
/usr/include/stdint.h:
/usr/include/i386-linux-gnu/bits/wchar.h:
../../../VEX/pub/libvex.h:
../../../VEX/pub/libvex_basictypes.h:
../../../VEX/pub/libvex_ir.h:
vbits.h:
/usr/include/stdio.h:
/usr/include/libio.h:
/usr/include/_G_config.h:
/usr/include/wchar.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
/usr/include/i386-linux-gnu/bits/stdio.h:
/usr/include/i386-linux-gnu/bits/stdio2.h:
@@ -0,0 +1,87 @@
vbit_test-irops.o: irops.c /usr/include/stdc-predef.h \
/usr/include/stdio.h /usr/include/features.h \
/usr/include/i386-linux-gnu/sys/cdefs.h \
/usr/include/i386-linux-gnu/bits/wordsize.h \
/usr/include/i386-linux-gnu/gnu/stubs.h \
/usr/include/i386-linux-gnu/gnu/stubs-32.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
/usr/include/i386-linux-gnu/bits/types.h \
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
/usr/include/i386-linux-gnu/bits/stdio.h \
/usr/include/i386-linux-gnu/bits/stdio2.h /usr/include/stdlib.h \
/usr/include/i386-linux-gnu/bits/stdlib-bsearch.h \
/usr/include/i386-linux-gnu/bits/stdlib-float.h \
/usr/include/i386-linux-gnu/bits/stdlib.h \
../../../include/pub_tool_basics.h ../../../VEX/pub/libvex_basictypes.h \
vtest.h /usr/lib/gcc/i686-linux-gnu/5/include/stdint.h \
/usr/include/stdint.h /usr/include/i386-linux-gnu/bits/wchar.h \
../../../VEX/pub/libvex.h ../../../VEX/pub/libvex_basictypes.h \
../../../VEX/pub/libvex_ir.h vbits.h
/usr/include/stdc-predef.h:
/usr/include/stdio.h:
/usr/include/features.h:
/usr/include/i386-linux-gnu/sys/cdefs.h:
/usr/include/i386-linux-gnu/bits/wordsize.h:
/usr/include/i386-linux-gnu/gnu/stubs.h:
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
/usr/include/i386-linux-gnu/bits/types.h:
/usr/include/i386-linux-gnu/bits/typesizes.h:
/usr/include/libio.h:
/usr/include/_G_config.h:
/usr/include/wchar.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
/usr/include/i386-linux-gnu/bits/stdio.h:
/usr/include/i386-linux-gnu/bits/stdio2.h:
/usr/include/stdlib.h:
/usr/include/i386-linux-gnu/bits/stdlib-bsearch.h:
/usr/include/i386-linux-gnu/bits/stdlib-float.h:
/usr/include/i386-linux-gnu/bits/stdlib.h:
../../../include/pub_tool_basics.h:
../../../VEX/pub/libvex_basictypes.h:
vtest.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
/usr/include/stdint.h:
/usr/include/i386-linux-gnu/bits/wchar.h:
../../../VEX/pub/libvex.h:
../../../VEX/pub/libvex_basictypes.h:
../../../VEX/pub/libvex_ir.h:
vbits.h:
@@ -0,0 +1,101 @@
vbit_test-main.o: main.c /usr/include/stdc-predef.h /usr/include/assert.h \
/usr/include/features.h /usr/include/i386-linux-gnu/sys/cdefs.h \
/usr/include/i386-linux-gnu/bits/wordsize.h \
/usr/include/i386-linux-gnu/gnu/stubs.h \
/usr/include/i386-linux-gnu/gnu/stubs-32.h /usr/include/stdio.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
/usr/include/i386-linux-gnu/bits/types.h \
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
/usr/include/i386-linux-gnu/bits/stdio.h \
/usr/include/i386-linux-gnu/bits/stdio2.h /usr/include/stdlib.h \
/usr/include/i386-linux-gnu/bits/stdlib-bsearch.h \
/usr/include/i386-linux-gnu/bits/stdlib-float.h \
/usr/include/i386-linux-gnu/bits/stdlib.h /usr/include/string.h \
/usr/include/i386-linux-gnu/bits/string.h \
/usr/include/i386-linux-gnu/bits/string2.h /usr/include/endian.h \
/usr/include/i386-linux-gnu/bits/endian.h \
/usr/include/i386-linux-gnu/bits/string3.h ../../../include/valgrind.h \
vtest.h /usr/lib/gcc/i686-linux-gnu/5/include/stdint.h \
/usr/include/stdint.h /usr/include/i386-linux-gnu/bits/wchar.h \
../../../VEX/pub/libvex.h ../../../VEX/pub/libvex_basictypes.h \
../../../VEX/pub/libvex_ir.h vbits.h
/usr/include/stdc-predef.h:
/usr/include/assert.h:
/usr/include/features.h:
/usr/include/i386-linux-gnu/sys/cdefs.h:
/usr/include/i386-linux-gnu/bits/wordsize.h:
/usr/include/i386-linux-gnu/gnu/stubs.h:
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
/usr/include/stdio.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
/usr/include/i386-linux-gnu/bits/types.h:
/usr/include/i386-linux-gnu/bits/typesizes.h:
/usr/include/libio.h:
/usr/include/_G_config.h:
/usr/include/wchar.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
/usr/include/i386-linux-gnu/bits/stdio.h:
/usr/include/i386-linux-gnu/bits/stdio2.h:
/usr/include/stdlib.h:
/usr/include/i386-linux-gnu/bits/stdlib-bsearch.h:
/usr/include/i386-linux-gnu/bits/stdlib-float.h:
/usr/include/i386-linux-gnu/bits/stdlib.h:
/usr/include/string.h:
/usr/include/i386-linux-gnu/bits/string.h:
/usr/include/i386-linux-gnu/bits/string2.h:
/usr/include/endian.h:
/usr/include/i386-linux-gnu/bits/endian.h:
/usr/include/i386-linux-gnu/bits/string3.h:
../../../include/valgrind.h:
vtest.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
/usr/include/stdint.h:
/usr/include/i386-linux-gnu/bits/wchar.h:
../../../VEX/pub/libvex.h:
../../../VEX/pub/libvex_basictypes.h:
../../../VEX/pub/libvex_ir.h:
vbits.h:
@@ -0,0 +1,73 @@
vbit_test-qernary.o: qernary.c /usr/include/stdc-predef.h \
/usr/include/assert.h /usr/include/features.h \
/usr/include/i386-linux-gnu/sys/cdefs.h \
/usr/include/i386-linux-gnu/bits/wordsize.h \
/usr/include/i386-linux-gnu/gnu/stubs.h \
/usr/include/i386-linux-gnu/gnu/stubs-32.h vtest.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h /usr/include/stdint.h \
/usr/include/i386-linux-gnu/bits/wchar.h ../../../VEX/pub/libvex.h \
../../../VEX/pub/libvex_basictypes.h ../../../VEX/pub/libvex_ir.h \
vbits.h /usr/include/stdio.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
/usr/include/i386-linux-gnu/bits/types.h \
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
/usr/include/i386-linux-gnu/bits/stdio.h \
/usr/include/i386-linux-gnu/bits/stdio2.h
/usr/include/stdc-predef.h:
/usr/include/assert.h:
/usr/include/features.h:
/usr/include/i386-linux-gnu/sys/cdefs.h:
/usr/include/i386-linux-gnu/bits/wordsize.h:
/usr/include/i386-linux-gnu/gnu/stubs.h:
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
vtest.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
/usr/include/stdint.h:
/usr/include/i386-linux-gnu/bits/wchar.h:
../../../VEX/pub/libvex.h:
../../../VEX/pub/libvex_basictypes.h:
../../../VEX/pub/libvex_ir.h:
vbits.h:
/usr/include/stdio.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
/usr/include/i386-linux-gnu/bits/types.h:
/usr/include/i386-linux-gnu/bits/typesizes.h:
/usr/include/libio.h:
/usr/include/_G_config.h:
/usr/include/wchar.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
/usr/include/i386-linux-gnu/bits/stdio.h:
/usr/include/i386-linux-gnu/bits/stdio2.h:
@@ -0,0 +1,73 @@
vbit_test-ternary.o: ternary.c /usr/include/stdc-predef.h \
/usr/include/assert.h /usr/include/features.h \
/usr/include/i386-linux-gnu/sys/cdefs.h \
/usr/include/i386-linux-gnu/bits/wordsize.h \
/usr/include/i386-linux-gnu/gnu/stubs.h \
/usr/include/i386-linux-gnu/gnu/stubs-32.h vtest.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h /usr/include/stdint.h \
/usr/include/i386-linux-gnu/bits/wchar.h ../../../VEX/pub/libvex.h \
../../../VEX/pub/libvex_basictypes.h ../../../VEX/pub/libvex_ir.h \
vbits.h /usr/include/stdio.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
/usr/include/i386-linux-gnu/bits/types.h \
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
/usr/include/i386-linux-gnu/bits/stdio.h \
/usr/include/i386-linux-gnu/bits/stdio2.h
/usr/include/stdc-predef.h:
/usr/include/assert.h:
/usr/include/features.h:
/usr/include/i386-linux-gnu/sys/cdefs.h:
/usr/include/i386-linux-gnu/bits/wordsize.h:
/usr/include/i386-linux-gnu/gnu/stubs.h:
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
vtest.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
/usr/include/stdint.h:
/usr/include/i386-linux-gnu/bits/wchar.h:
../../../VEX/pub/libvex.h:
../../../VEX/pub/libvex_basictypes.h:
../../../VEX/pub/libvex_ir.h:
vbits.h:
/usr/include/stdio.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
/usr/include/i386-linux-gnu/bits/types.h:
/usr/include/i386-linux-gnu/bits/typesizes.h:
/usr/include/libio.h:
/usr/include/_G_config.h:
/usr/include/wchar.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
/usr/include/i386-linux-gnu/bits/stdio.h:
/usr/include/i386-linux-gnu/bits/stdio2.h:
@@ -0,0 +1,73 @@
vbit_test-unary.o: unary.c /usr/include/stdc-predef.h \
/usr/include/assert.h /usr/include/features.h \
/usr/include/i386-linux-gnu/sys/cdefs.h \
/usr/include/i386-linux-gnu/bits/wordsize.h \
/usr/include/i386-linux-gnu/gnu/stubs.h \
/usr/include/i386-linux-gnu/gnu/stubs-32.h vtest.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h /usr/include/stdint.h \
/usr/include/i386-linux-gnu/bits/wchar.h ../../../VEX/pub/libvex.h \
../../../VEX/pub/libvex_basictypes.h ../../../VEX/pub/libvex_ir.h \
vbits.h /usr/include/stdio.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
/usr/include/i386-linux-gnu/bits/types.h \
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
/usr/include/i386-linux-gnu/bits/stdio.h \
/usr/include/i386-linux-gnu/bits/stdio2.h
/usr/include/stdc-predef.h:
/usr/include/assert.h:
/usr/include/features.h:
/usr/include/i386-linux-gnu/sys/cdefs.h:
/usr/include/i386-linux-gnu/bits/wordsize.h:
/usr/include/i386-linux-gnu/gnu/stubs.h:
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
vtest.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
/usr/include/stdint.h:
/usr/include/i386-linux-gnu/bits/wchar.h:
../../../VEX/pub/libvex.h:
../../../VEX/pub/libvex_basictypes.h:
../../../VEX/pub/libvex_ir.h:
vbits.h:
/usr/include/stdio.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
/usr/include/i386-linux-gnu/bits/types.h:
/usr/include/i386-linux-gnu/bits/typesizes.h:
/usr/include/libio.h:
/usr/include/_G_config.h:
/usr/include/wchar.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
/usr/include/i386-linux-gnu/bits/stdio.h:
/usr/include/i386-linux-gnu/bits/stdio2.h:
@@ -0,0 +1,90 @@
vbit_test-util.o: util.c /usr/include/stdc-predef.h /usr/include/stdio.h \
/usr/include/features.h /usr/include/i386-linux-gnu/sys/cdefs.h \
/usr/include/i386-linux-gnu/bits/wordsize.h \
/usr/include/i386-linux-gnu/gnu/stubs.h \
/usr/include/i386-linux-gnu/gnu/stubs-32.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
/usr/include/i386-linux-gnu/bits/types.h \
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
/usr/include/i386-linux-gnu/bits/stdio.h \
/usr/include/i386-linux-gnu/bits/stdio2.h /usr/include/stdlib.h \
/usr/include/i386-linux-gnu/bits/stdlib-bsearch.h \
/usr/include/i386-linux-gnu/bits/stdlib-float.h \
/usr/include/i386-linux-gnu/bits/stdlib.h /usr/include/assert.h \
/usr/include/endian.h /usr/include/i386-linux-gnu/bits/endian.h \
/usr/include/inttypes.h /usr/lib/gcc/i686-linux-gnu/5/include/stdint.h \
/usr/include/stdint.h /usr/include/i386-linux-gnu/bits/wchar.h vtest.h \
../../../VEX/pub/libvex.h ../../../VEX/pub/libvex_basictypes.h \
../../../VEX/pub/libvex_ir.h vbits.h
/usr/include/stdc-predef.h:
/usr/include/stdio.h:
/usr/include/features.h:
/usr/include/i386-linux-gnu/sys/cdefs.h:
/usr/include/i386-linux-gnu/bits/wordsize.h:
/usr/include/i386-linux-gnu/gnu/stubs.h:
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
/usr/include/i386-linux-gnu/bits/types.h:
/usr/include/i386-linux-gnu/bits/typesizes.h:
/usr/include/libio.h:
/usr/include/_G_config.h:
/usr/include/wchar.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
/usr/include/i386-linux-gnu/bits/stdio.h:
/usr/include/i386-linux-gnu/bits/stdio2.h:
/usr/include/stdlib.h:
/usr/include/i386-linux-gnu/bits/stdlib-bsearch.h:
/usr/include/i386-linux-gnu/bits/stdlib-float.h:
/usr/include/i386-linux-gnu/bits/stdlib.h:
/usr/include/assert.h:
/usr/include/endian.h:
/usr/include/i386-linux-gnu/bits/endian.h:
/usr/include/inttypes.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
/usr/include/stdint.h:
/usr/include/i386-linux-gnu/bits/wchar.h:
vtest.h:
../../../VEX/pub/libvex.h:
../../../VEX/pub/libvex_basictypes.h:
../../../VEX/pub/libvex_ir.h:
vbits.h:
@@ -0,0 +1,78 @@
vbit_test-valgrind.o: valgrind.c /usr/include/stdc-predef.h \
/usr/include/assert.h /usr/include/features.h \
/usr/include/i386-linux-gnu/sys/cdefs.h \
/usr/include/i386-linux-gnu/bits/wordsize.h \
/usr/include/i386-linux-gnu/gnu/stubs.h \
/usr/include/i386-linux-gnu/gnu/stubs-32.h ../../../memcheck/memcheck.h \
../../../include/valgrind.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h vtest.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h /usr/include/stdint.h \
/usr/include/i386-linux-gnu/bits/wchar.h ../../../VEX/pub/libvex.h \
../../../VEX/pub/libvex_basictypes.h ../../../VEX/pub/libvex_ir.h \
vbits.h /usr/include/stdio.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
/usr/include/i386-linux-gnu/bits/types.h \
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h \
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
/usr/include/i386-linux-gnu/bits/stdio.h \
/usr/include/i386-linux-gnu/bits/stdio2.h
/usr/include/stdc-predef.h:
/usr/include/assert.h:
/usr/include/features.h:
/usr/include/i386-linux-gnu/sys/cdefs.h:
/usr/include/i386-linux-gnu/bits/wordsize.h:
/usr/include/i386-linux-gnu/gnu/stubs.h:
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
../../../memcheck/memcheck.h:
../../../include/valgrind.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
vtest.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
/usr/include/stdint.h:
/usr/include/i386-linux-gnu/bits/wchar.h:
../../../VEX/pub/libvex.h:
../../../VEX/pub/libvex_basictypes.h:
../../../VEX/pub/libvex_ir.h:
vbits.h:
/usr/include/stdio.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
/usr/include/i386-linux-gnu/bits/types.h:
/usr/include/i386-linux-gnu/bits/typesizes.h:
/usr/include/libio.h:
/usr/include/_G_config.h:
/usr/include/wchar.h:
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
/usr/include/i386-linux-gnu/bits/stdio.h:
/usr/include/i386-linux-gnu/bits/stdio2.h:
@@ -0,0 +1,80 @@
vbit_test-vbits.o: vbits.c /usr/include/stdc-predef.h \
/usr/include/stdio.h /usr/include/features.h \
/usr/include/i386-linux-gnu/sys/cdefs.h \
/usr/include/i386-linux-gnu/bits/wordsize.h \
/usr/include/i386-linux-gnu/gnu/stubs.h \
/usr/include/i386-linux-gnu/gnu/stubs-32.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h \
/usr/include/i386-linux-gnu/bits/types.h \
/usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h \
/usr/include/i386-linux-gnu/bits/stdio_lim.h \
/usr/include/i386-linux-gnu/bits/sys_errlist.h \
/usr/include/i386-linux-gnu/bits/stdio.h \
/usr/include/i386-linux-gnu/bits/stdio2.h /usr/include/assert.h \
/usr/include/endian.h /usr/include/i386-linux-gnu/bits/endian.h \
/usr/include/inttypes.h /usr/lib/gcc/i686-linux-gnu/5/include/stdint.h \
/usr/include/stdint.h /usr/include/i386-linux-gnu/bits/wchar.h vbits.h \
vtest.h ../../../VEX/pub/libvex.h ../../../VEX/pub/libvex_basictypes.h \
../../../VEX/pub/libvex_ir.h
/usr/include/stdc-predef.h:
/usr/include/stdio.h:
/usr/include/features.h:
/usr/include/i386-linux-gnu/sys/cdefs.h:
/usr/include/i386-linux-gnu/bits/wordsize.h:
/usr/include/i386-linux-gnu/gnu/stubs.h:
/usr/include/i386-linux-gnu/gnu/stubs-32.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stddef.h:
/usr/include/i386-linux-gnu/bits/types.h:
/usr/include/i386-linux-gnu/bits/typesizes.h:
/usr/include/libio.h:
/usr/include/_G_config.h:
/usr/include/wchar.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdarg.h:
/usr/include/i386-linux-gnu/bits/stdio_lim.h:
/usr/include/i386-linux-gnu/bits/sys_errlist.h:
/usr/include/i386-linux-gnu/bits/stdio.h:
/usr/include/i386-linux-gnu/bits/stdio2.h:
/usr/include/assert.h:
/usr/include/endian.h:
/usr/include/i386-linux-gnu/bits/endian.h:
/usr/include/inttypes.h:
/usr/lib/gcc/i686-linux-gnu/5/include/stdint.h:
/usr/include/stdint.h:
/usr/include/i386-linux-gnu/bits/wchar.h:
vbits.h:
vtest.h:
../../../VEX/pub/libvex.h:
../../../VEX/pub/libvex_basictypes.h:
../../../VEX/pub/libvex_ir.h:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,43 @@
include $(top_srcdir)/Makefile.all.am
EXTRA_DIST = vbit-test.vgtest vbit-test.stderr.exp
dist_noinst_SCRIPTS = filter_stderr
#----------------------------------------------------------------------------
# Headers
#----------------------------------------------------------------------------
pkginclude_HEADERS =
noinst_HEADERS = vtest.h vbits.h
#----------------------------------------------------------------------------
# vbit_test
#----------------------------------------------------------------------------
noinst_PROGRAMS = vbit-test
if VGCONF_OS_IS_DARWIN
noinst_DSYMS = $(noinst_PROGRAMS)
endif
SOURCES = \
main.c \
unary.c \
binary.c \
ternary.c \
qernary.c \
util.c \
vbits.c \
irops.c \
valgrind.c
vbit_test_SOURCES = $(SOURCES)
vbit_test_CPPFLAGS = $(AM_CPPFLAGS_PRI) \
-I$(top_srcdir)/include \
-I$(top_srcdir)/memcheck \
-I$(top_srcdir)/VEX/pub
vbit_test_CFLAGS = $(AM_CFLAGS_PRI) -std=c99
vbit_test_DEPENDENCIES =
vbit_test_LDADD =
vbit_test_LDFLAGS = $(AM_CFLAGS_PRI) -std=c99 @LIB_UBSAN@
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,102 @@
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.
@@ -0,0 +1,9 @@
(1) For all operators: Add a test where both operands are completely
defined, i.e. all v-bits 0.
(2) Add support for IROps with vector operands.
(3) Test floating point operations with various rounding modes.
(4) Iop_CmpORD32U and friends are not supported (ppc only)
@@ -0,0 +1,469 @@
/* -*- mode: C; c-basic-offset: 3; -*- */
#include <assert.h>
#include <string.h> // memset
#include "vtest.h"
/* A convenience function to compute either v1 & ~v2 & val2 or
v1 & ~v2 & ~val2 depending on INVERT_VAL2. */
static vbits_t
and_combine(vbits_t v1, vbits_t v2, value_t val2, int invert_val2)
{
assert(v1.num_bits == v2.num_bits);
vbits_t new = { .num_bits = v2.num_bits };
if (invert_val2) {
switch (v2.num_bits) {
case 8: val2.u8 = ~val2.u8 & 0xff; break;
case 16: val2.u16 = ~val2.u16 & 0xffff; break;
case 32: val2.u32 = ~val2.u32; break;
case 64: val2.u64 = ~val2.u64; break;
default:
panic(__func__);
}
}
switch (v2.num_bits) {
case 8:
new.bits.u8 = (v1.bits.u8 & ~v2.bits.u8 & val2.u8) & 0xff;
break;
case 16:
new.bits.u16 = (v1.bits.u16 & ~v2.bits.u16 & val2.u16) & 0xffff;
break;
case 32:
new.bits.u32 = (v1.bits.u32 & ~v2.bits.u32 & val2.u32);
break;
case 64:
new.bits.u64 = (v1.bits.u64 & ~v2.bits.u64 & val2.u64);
break;
default:
panic(__func__);
}
return new;
}
/* Check the result of a binary operation. */
static void
check_result_for_binary(const irop_t *op, const test_data_t *data)
{
const opnd_t *result = &data->result;
const opnd_t *opnd1 = &data->opnds[0];
const opnd_t *opnd2 = &data->opnds[1];
vbits_t expected_vbits;
/* Only handle those undef-kinds that actually occur. */
switch (op->undef_kind) {
case UNDEF_NONE:
expected_vbits = defined_vbits(result->vbits.num_bits);
break;
case UNDEF_ALL:
expected_vbits = undefined_vbits(result->vbits.num_bits);
break;
case UNDEF_LEFT:
// LEFT with respect to the leftmost 1-bit in both operands
expected_vbits = left_vbits(or_vbits(opnd1->vbits, opnd2->vbits),
result->vbits.num_bits);
break;
case UNDEF_SAME:
assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
assert(opnd1->vbits.num_bits == result->vbits.num_bits);
// SAME with respect to the 1-bits in both operands
expected_vbits = or_vbits(opnd1->vbits, opnd2->vbits);
break;
case UNDEF_CONCAT:
assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
assert(result->vbits.num_bits == 2 * opnd1->vbits.num_bits);
expected_vbits = concat_vbits(opnd1->vbits, opnd2->vbits);
break;
case UNDEF_SHL:
/* If any bit in the 2nd operand is undefined, so are all bits
of the result. */
if (! completely_defined_vbits(opnd2->vbits)) {
expected_vbits = undefined_vbits(result->vbits.num_bits);
} else {
assert(opnd2->vbits.num_bits == 8);
unsigned shift_amount = opnd2->value.u8;
expected_vbits = shl_vbits(opnd1->vbits, shift_amount);
}
break;
case UNDEF_SHR:
/* If any bit in the 2nd operand is undefined, so are all bits
of the result. */
if (! completely_defined_vbits(opnd2->vbits)) {
expected_vbits = undefined_vbits(result->vbits.num_bits);
} else {
assert(opnd2->vbits.num_bits == 8);
unsigned shift_amount = opnd2->value.u8;
expected_vbits = shr_vbits(opnd1->vbits, shift_amount);
}
break;
case UNDEF_SAR:
/* If any bit in the 2nd operand is undefined, so are all bits
of the result. */
if (! completely_defined_vbits(opnd2->vbits)) {
expected_vbits = undefined_vbits(result->vbits.num_bits);
} else {
assert(opnd2->vbits.num_bits == 8);
unsigned shift_amount = opnd2->value.u8;
expected_vbits = sar_vbits(opnd1->vbits, shift_amount);
}
break;
case UNDEF_AND: {
/* Let v1, v2 be the V-bits of the 1st and 2nd operand, respectively
Let b1, b2 be the actual value of the 1st and 2nd operand, respect.
And output bit is undefined (i.e. its V-bit == 1), iff
(1) (v1 == 1) && (v2 == 1) OR
(2) (v1 == 1) && (v2 == 0 && b2 == 1) OR
(3) (v2 == 1) && (v1 == 0 && b1 == 1)
*/
vbits_t term1, term2, term3;
term1 = and_vbits(opnd1->vbits, opnd2->vbits);
term2 = and_combine(opnd1->vbits, opnd2->vbits, opnd2->value, 0);
term3 = and_combine(opnd2->vbits, opnd1->vbits, opnd1->value, 0);
expected_vbits = or_vbits(term1, or_vbits(term2, term3));
break;
}
case UNDEF_OR: {
/* Let v1, v2 be the V-bits of the 1st and 2nd operand, respectively
Let b1, b2 be the actual value of the 1st and 2nd operand, respect.
And output bit is undefined (i.e. its V-bit == 1), iff
(1) (v1 == 1) && (v2 == 1) OR
(2) (v1 == 1) && (v2 == 0 && b2 == 0) OR
(3) (v2 == 1) && (v1 == 0 && b1 == 0)
*/
vbits_t term1, term2, term3;
term1 = and_vbits(opnd1->vbits, opnd2->vbits);
term2 = and_combine(opnd1->vbits, opnd2->vbits, opnd2->value, 1);
term3 = and_combine(opnd2->vbits, opnd1->vbits, opnd1->value, 1);
expected_vbits = or_vbits(term1, or_vbits(term2, term3));
break;
}
case UNDEF_ORD:
/* Set expected_vbits for the Iop_CmpORD category of iops.
* If any of the input bits is undefined the least significant
* three bits in the result will be set, i.e. 0xe.
*/
expected_vbits = cmpord_vbits(opnd1->vbits.num_bits,
opnd2->vbits.num_bits);
break;
default:
panic(__func__);
}
if (! equal_vbits(result->vbits, expected_vbits))
complain(op, data, expected_vbits);
}
static int
test_shift(const irop_t *op, test_data_t *data)
{
unsigned num_input_bits, i;
opnd_t *opnds = data->opnds;
int tests_done = 0;
/* When testing the 1st operand's undefinedness propagation,
do so with all possible shift amnounts */
for (unsigned amount = 0; amount < bitsof_irtype(opnds[0].type); ++amount) {
opnds[1].value.u8 = amount;
// 1st (left) operand
num_input_bits = bitsof_irtype(opnds[0].type);
for (i = 0; i < num_input_bits; ++i) {
opnds[0].vbits = onehot_vbits(i, bitsof_irtype(opnds[0].type));
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
valgrind_execute_test(op, data);
check_result_for_binary(op, data);
tests_done++;
}
}
// 2nd (right) operand
/* If the operand is an immediate value, there are no v-bits to set. */
if (op->shift_amount_is_immediate) return tests_done;
num_input_bits = bitsof_irtype(opnds[1].type);
for (i = 0; i < num_input_bits; ++i) {
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
opnds[1].vbits = onehot_vbits(i, bitsof_irtype(opnds[1].type));
valgrind_execute_test(op, data);
check_result_for_binary(op, data);
tests_done++;
}
return tests_done;
}
static value_t
all_bits_zero_value(unsigned num_bits)
{
value_t val;
switch (num_bits) {
case 8: val.u8 = 0; break;
case 16: val.u16 = 0; break;
case 32: val.u32 = 0; break;
case 64: val.u64 = 0; break;
default:
panic(__func__);
}
return val;
}
static value_t
all_bits_one_value(unsigned num_bits)
{
value_t val;
switch (num_bits) {
case 8: val.u8 = 0xff; break;
case 16: val.u16 = 0xffff; break;
case 32: val.u32 = ~0u; break;
case 64: val.u64 = ~0ull; break;
default:
panic(__func__);
}
return val;
}
static int
test_and(const irop_t *op, test_data_t *data)
{
unsigned num_input_bits, bitpos;
opnd_t *opnds = data->opnds;
int tests_done = 0;
/* Undefinedness does not propagate if the other operand is 0.
Use an all-bits-zero operand and test the other operand in
the usual way (one bit undefined at a time). */
// 1st (left) operand variable, 2nd operand all-bits-zero
num_input_bits = bitsof_irtype(opnds[0].type);
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
opnds[0].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[0].type));
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
opnds[1].value = all_bits_zero_value(bitsof_irtype(opnds[1].type));
valgrind_execute_test(op, data);
check_result_for_binary(op, data);
tests_done++;
}
// 2nd (right) operand variable, 1st operand all-bits-zero
num_input_bits = bitsof_irtype(opnds[1].type);
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
opnds[1].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[1].type));
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
opnds[0].value = all_bits_zero_value(bitsof_irtype(opnds[0].type));
valgrind_execute_test(op, data);
check_result_for_binary(op, data);
tests_done++;
}
/* Undefinedness propagates if the other operand is 1.
Use an all-bits-one operand and test the other operand in
the usual way (one bit undefined at a time). */
// 1st (left) operand variable, 2nd operand all-bits-one
num_input_bits = bitsof_irtype(opnds[0].type);
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
opnds[0].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[0].type));
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
opnds[1].value = all_bits_one_value(bitsof_irtype(opnds[1].type));
valgrind_execute_test(op, data);
check_result_for_binary(op, data);
tests_done++;
}
// 2nd (right) operand variable, 1st operand all-bits-one
num_input_bits = bitsof_irtype(opnds[1].type);
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
opnds[1].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[1].type));
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
opnds[0].value = all_bits_one_value(bitsof_irtype(opnds[0].type));
valgrind_execute_test(op, data);
check_result_for_binary(op, data);
tests_done++;
}
return tests_done;
}
static int
test_or(const irop_t *op, test_data_t *data)
{
unsigned num_input_bits, bitpos;
opnd_t *opnds = data->opnds;
int tests_done = 0;
/* Undefinedness does not propagate if the other operand is 1.
Use an all-bits-one operand and test the other operand in
the usual way (one bit undefined at a time). */
// 1st (left) operand variable, 2nd operand all-bits-one
num_input_bits = bitsof_irtype(opnds[0].type);
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
opnds[1].value = all_bits_one_value(bitsof_irtype(opnds[1].type));
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
opnds[0].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[0].type));
valgrind_execute_test(op, data);
check_result_for_binary(op, data);
tests_done++;
}
// 2nd (right) operand variable, 1st operand all-bits-one
num_input_bits = bitsof_irtype(opnds[1].type);
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
opnds[0].value = all_bits_one_value(bitsof_irtype(opnds[0].type));
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
opnds[1].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[1].type));
valgrind_execute_test(op, data);
check_result_for_binary(op, data);
tests_done++;
}
/* Undefinedness propagates if the other operand is 0.
Use an all-bits-zero operand and test the other operand in
the usual way (one bit undefined at a time). */
// 1st (left) operand variable, 2nd operand all-bits-zero
num_input_bits = bitsof_irtype(opnds[0].type);
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
opnds[1].value = all_bits_zero_value(bitsof_irtype(opnds[1].type));
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
opnds[0].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[0].type));
valgrind_execute_test(op, data);
check_result_for_binary(op, data);
tests_done++;
}
// 2nd (right) operand variable, 1st operand all-bits-zero
num_input_bits = bitsof_irtype(opnds[1].type);
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
opnds[0].value = all_bits_zero_value(bitsof_irtype(opnds[0].type));
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
opnds[1].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[1].type));
valgrind_execute_test(op, data);
check_result_for_binary(op, data);
tests_done++;
}
return tests_done;
}
int
test_binary_op(const irop_t *op, test_data_t *data)
{
unsigned num_input_bits, i, bitpos;
opnd_t *opnds = data->opnds;
int tests_done = 0;
/* Handle special cases upfront */
switch (op->undef_kind) {
case UNDEF_SHL:
case UNDEF_SHR:
case UNDEF_SAR:
return test_shift(op, data);
case UNDEF_AND:
return test_and(op, data);
case UNDEF_OR:
return test_or(op, data);
default:
break;
}
/* For each operand, set a single bit to undefined and observe how
that propagates to the output. Do this for all bits in each
operand. */
for (i = 0; i < 2; ++i) {
/* If this is a shift op that requires an immediate shift amount,
do not iterate the v-bits of the 2nd operand */
if (i == 1 && op->shift_amount_is_immediate) break;
num_input_bits = bitsof_irtype(opnds[i].type);
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
/* Set the value of the 2nd operand to something != 0. So division
won't crash. */
memset(&opnds[1].value, 0xff, sizeof opnds[1].value);
/* For immediate shift amounts choose a value of '1'. That should
not cause a problem. */
if (op->shift_amount_is_immediate)
opnds[1].value.u8 = 1;
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
opnds[i].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[i].type));
valgrind_execute_test(op, data);
check_result_for_binary(op, data);
tests_done++;
}
}
return tests_done;
}
@@ -0,0 +1,3 @@
#! /bin/sh
../filter_stderr "$@"
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,158 @@
/* -*- mode: C; c-basic-offset: 3; -*- */
#include <assert.h> // assert
#include <stdio.h> // printf
#include <stdlib.h> // malloc
#include <string.h> // memset
#include "valgrind.h" // RUNNING_ON_VALGRIND
#include "vtest.h"
static test_data_t *
new_test_data(const irop_t *op)
{
test_data_t *data = malloc(sizeof *data);
memset(data, 0x0, sizeof *data); // initialise
/* Obtain the operand types and set them */
IRType t_dst, t1, t2, t3, t4;
typeof_primop(op->op, &t_dst, &t1, &t2, &t3, &t4);
assert(t_dst != Ity_INVALID);
assert(t1 != Ity_INVALID);
data->result.type = t_dst;
if (is_floating_point_op_with_rounding_mode(op->op)) {
data->opnds[0].type = t2;
data->opnds[1].type = t3;
data->opnds[2].type = t4;
data->opnds[3].type = Ity_INVALID;
} else {
data->opnds[0].type = t1;
data->opnds[1].type = t2;
data->opnds[2].type = t3;
data->opnds[3].type = t4;
}
/* Set the rounding mode if the operation requires one.
FIXME: We should iterate over all rounding modes. For that need
FIXME: to distinguish between binary and decimal floating point */
if (is_floating_point_op_with_rounding_mode(op->op)) {
// for now just pick one
data->rounding_mode = Irrm_NEAREST; // same as Irrm_DFP_NEAREST
} else {
data->rounding_mode = NO_ROUNDING_MODE;
}
return data;
}
int verbose = 0;
/* Certain IROps require special handling. */
static void
fixup_irops(void)
{
#ifdef __powerpc__
get_irop(Iop_ShlD64)->shift_amount_is_immediate = 1;
get_irop(Iop_ShrD64)->shift_amount_is_immediate = 1;
get_irop(Iop_ShlD128)->shift_amount_is_immediate = 1;
get_irop(Iop_ShrD128)->shift_amount_is_immediate = 1;
#endif
}
int
main(int argc, char *argv[])
{
assert(sizeof(long long) == 8);
int num_unary_tests = 0, num_binary_tests = 0;
int num_ternary_tests = 0, num_qernary_tests = 0;
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "-v") == 0) ++verbose;
else if (strcmp(argv[i], "--help") == 0) {
printf("\nvbit-test [ -v | --help ]\n");
printf("\n\t-v verbose mode; show number of 1, 2, 3 and 4 operand tests\n");
printf("\n\t-v -v verbose mode; shows IROps being tested\n");
printf("\n\t-v -v -v verbose mode, extreme edition\n\n");
return 0;
} else {
printf("%s ? Nothing happens.\n", argv[i]);
return 1;
}
}
if (! RUNNING_ON_VALGRIND) {
fprintf(stderr, "*** This program needs to run under memcheck.\n");
return 1;
}
setbuf(stdout, NULL); // make stdout unbuffered
fixup_irops(); // determine need for special handling
// Iterate over all primops
IROp first = Iop_INVALID + 1;
IROp last = Iop_LAST;
IROp opkind;
if (0) { // overwrite for debugging
first = Iop_CasCmpEQ8; last = first + 1;
}
// Iterate over all IROps in the enum type. That is the only way to
// make sure the operator is tested on at least one platform.
// Loop assumes no holes in the enumerator values
for (opkind = first; opkind < last; ++opkind) {
const irop_t *op = get_irop(opkind);
if (op == NULL) continue;
test_data_t *data = new_test_data(op);
if (op->undef_kind == UNDEF_UNKNOWN) {
fprintf(stderr, "...skipping %s; unknown undef propagation\n",
op->name);
continue;
}
if (verbose > 1) printf("Testing operator %s\n", op->name);
IRICB iricb = new_iricb(op, data);
valgrind_vex_init_for_iri(&iricb);
switch (iricb.num_operands) {
case 1:
num_unary_tests += test_unary_op(op, data);
break;
case 2:
num_binary_tests += test_binary_op(op, data);
break;
case 3:
num_ternary_tests += test_ternary_op(op, data);
break;
case 4:
num_qernary_tests += test_qernary_op(op, data);
break;
default:
panic("operator not handled");
}
free(data);
}
if (verbose)
printf("\nvbit-test ran %d unary, %d binary, %d ternary and %d qernary tests.\n",
num_unary_tests, num_binary_tests, num_ternary_tests,
num_qernary_tests);
return 0;
}
@@ -0,0 +1,68 @@
/* -*- mode: C; c-basic-offset: 3; -*- */
#include <assert.h>
#include "vtest.h"
/* Check the result of a quarternary operation. */
static void
check_result_for_qernary(const irop_t *op, const test_data_t *data)
{
const opnd_t *result = &data->result;
const opnd_t *opnd1 = &data->opnds[0];
const opnd_t *opnd2 = &data->opnds[1];
const opnd_t *opnd3 = &data->opnds[2];
const opnd_t *opnd4 = &data->opnds[3];
vbits_t expected_vbits;
/* Only handle those undef-kinds that actually occur. */
switch (op->undef_kind) {
case UNDEF_ALL:
expected_vbits = undefined_vbits(result->vbits.num_bits);
break;
case UNDEF_SAME:
// SAME with respect to the 1-bits in all operands
expected_vbits = or_vbits(or_vbits(or_vbits(opnd1->vbits, opnd2->vbits),
opnd3->vbits), opnd4->vbits);
break;
default:
panic(__func__);
}
if (! equal_vbits(result->vbits, expected_vbits))
complain(op, data, expected_vbits);
}
int
test_qernary_op(const irop_t *op, test_data_t *data)
{
unsigned num_input_bits, i, bitpos;
opnd_t *opnds = data->opnds;
int tests_done = 0;
/* For each operand, set a single bit to undefined and observe how
that propagates to the output. Do this for all bits in each
operand. */
for (i = 0; i < 4; ++i) {
num_input_bits = bitsof_irtype(opnds[i].type);
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
opnds[2].vbits = defined_vbits(bitsof_irtype(opnds[2].type));
opnds[3].vbits = defined_vbits(bitsof_irtype(opnds[3].type));
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
opnds[i].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[i].type));
valgrind_execute_test(op, data);
check_result_for_qernary(op, data);
tests_done++;
}
}
return tests_done;
}
@@ -0,0 +1,66 @@
/* -*- mode: C; c-basic-offset: 3; -*- */
#include <assert.h>
#include "vtest.h"
/* Check the result of a ternary operation. */
static void
check_result_for_ternary(const irop_t *op, const test_data_t *data)
{
const opnd_t *result = &data->result;
const opnd_t *opnd1 = &data->opnds[0];
const opnd_t *opnd2 = &data->opnds[1];
const opnd_t *opnd3 = &data->opnds[2];
vbits_t expected_vbits;
/* Only handle those undef-kinds that actually occur. */
switch (op->undef_kind) {
case UNDEF_ALL:
expected_vbits = undefined_vbits(result->vbits.num_bits);
break;
case UNDEF_SAME:
// SAME with respect to the 1-bits in all operands
expected_vbits = or_vbits(or_vbits(opnd1->vbits, opnd2->vbits),
opnd3->vbits);
break;
default:
panic(__func__);
}
if (! equal_vbits(result->vbits, expected_vbits))
complain(op, data, expected_vbits);
}
int
test_ternary_op(const irop_t *op, test_data_t *data)
{
unsigned num_input_bits, i, bitpos;
opnd_t *opnds = data->opnds;
int tests_done = 0;
/* For each operand, set a single bit to undefined and observe how
that propagates to the output. Do this for all bits in each
operand. */
for (i = 0; i < 3; ++i) {
num_input_bits = bitsof_irtype(opnds[i].type);
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
opnds[1].vbits = defined_vbits(bitsof_irtype(opnds[1].type));
opnds[2].vbits = defined_vbits(bitsof_irtype(opnds[2].type));
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
opnds[i].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[i].type));
valgrind_execute_test(op, data);
check_result_for_ternary(op, data);
tests_done++;
}
}
return tests_done;
}
@@ -0,0 +1,73 @@
/* -*- mode: C; c-basic-offset: 3; -*- */
#include <assert.h>
#include "vtest.h"
/* Check the result of a unary operation. */
static void
check_result_for_unary(const irop_t *op, const test_data_t *data)
{
const opnd_t *result = &data->result;
const opnd_t *opnd = &data->opnds[0];
unsigned num_bits = result->vbits.num_bits;
vbits_t expected_vbits;
/* Only handle those undef-kinds that actually occur. */
switch (op->undef_kind) {
case UNDEF_ALL:
expected_vbits = undefined_vbits(num_bits);
break;
case UNDEF_SAME:
expected_vbits = opnd->vbits;
break;
case UNDEF_TRUNC:
expected_vbits = truncate_vbits(opnd->vbits, num_bits);
break;
case UNDEF_LEFT:
expected_vbits = left_vbits(opnd->vbits, num_bits);
break;
case UNDEF_UPPER:
assert(num_bits * 2 == opnd->vbits.num_bits);
expected_vbits = upper_vbits(opnd->vbits);
break;
case UNDEF_SEXT:
expected_vbits = sextend_vbits(opnd->vbits, num_bits);
break;
case UNDEF_ZEXT:
expected_vbits = zextend_vbits(opnd->vbits, num_bits);
break;
default:
panic(__func__);
}
if (! equal_vbits(result->vbits, expected_vbits))
complain(op, data, expected_vbits);
}
int
test_unary_op(const irop_t *op, test_data_t *data)
{
unsigned num_input_bits, bitpos;
int tests_done = 0;
num_input_bits = bitsof_irtype(data->opnds[0].type);
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
data->opnds[0].vbits = onehot_vbits(bitpos, num_input_bits);
valgrind_execute_test(op, data);
check_result_for_unary(op, data);
tests_done++;
}
return tests_done;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,118 @@
/* -*- mode: C; c-basic-offset: 3; -*- */
#include <assert.h>
#include "memcheck.h" // VALGRIND_SET_VBITS
#include "vtest.h"
/* Return a completely initialised control block */
IRICB
new_iricb(const irop_t *op, test_data_t *data)
{
IRICB cb;
cb.op = op->op;
cb.result = (HWord)&data->result.value;
cb.opnd1 = (HWord)&data->opnds[0].value;
cb.opnd2 = (HWord)&data->opnds[1].value;
cb.opnd3 = (HWord)&data->opnds[2].value;
cb.opnd4 = (HWord)&data->opnds[3].value;
cb.t_result = data->result.type;
cb.t_opnd1 = data->opnds[0].type;
cb.t_opnd2 = data->opnds[1].type;
cb.t_opnd3 = data->opnds[2].type;
cb.t_opnd4 = data->opnds[3].type;
cb.rounding_mode = data->rounding_mode;
cb.num_operands = get_num_operands(op->op);
cb.shift_amount_is_immediate = op->shift_amount_is_immediate;
return cb;
}
/* Ity_I1 values cannot be stored or loaded. So vex_inject_ir will load/store
such a value from/to a 4-byte container. It uses 32to1 and 1Uto32,
respectively. */
static void
valgrind_set_vbits(opnd_t *opnd)
{
unsigned rc, num_bytes;
/* 1-bit wide values cannot be read. So we read a 4 bytes here */
num_bytes = opnd->type == Ity_I1 ? 4 : sizeof_irtype(opnd->type);
rc = VALGRIND_SET_VBITS(&opnd->value, &opnd->vbits.bits, num_bytes);
assert(rc == 1);
// Make sure the v-bits were set correctly
vbits_t actual = { .num_bits = opnd->vbits.num_bits };
rc = VALGRIND_GET_VBITS(&opnd->value, &actual.bits, num_bytes);
assert(rc == 1);
assert(equal_vbits(opnd->vbits, actual));
}
static void
valgrind_get_vbits(opnd_t *opnd)
{
unsigned rc, num_bytes;
/* 1-bit wide values cannot be stored. So we store them by writing a
single byte */
num_bytes = opnd->type == Ity_I1 ? 4 : sizeof_irtype(opnd->type);
opnd->vbits.num_bits = bitsof_irtype(opnd->type);
rc = VALGRIND_GET_VBITS(&opnd->value, &opnd->vbits.bits, num_bytes);
assert(rc == 1);
}
/* Insert a client request that will initialize VEX for IR injection */
void
valgrind_vex_init_for_iri(IRICB *cb)
{
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__VEX_INIT_FOR_IRI, cb, 0,0,0,0);
}
/* Insert a special opcode that will cause VEX to inject an IR stmt based
on the information passed in the IRICB (in valgrind_vex_init_for_iri). */
static void
valgrind_vex_inject_ir(void)
{
VALGRIND_VEX_INJECT_IR();
}
/* Execute the test under valgrind. Well, yes, we're not really executing
it here, just preparing for it... */
void
valgrind_execute_test(const irop_t *op, test_data_t *data)
{
unsigned i, num_operands;
if (verbose > 2) printf("---------- Running a test\n");
num_operands = get_num_operands(op->op);
for (i = 0; i < num_operands; ++i) {
valgrind_set_vbits(&data->opnds[i]);
if (verbose > 2) {
printf("opnd #%u: ", i);
print_opnd(stdout, &data->opnds[i]);
printf("\n");
}
}
if (verbose > 2)
if (data->rounding_mode != NO_ROUNDING_MODE)
printf("rounding mode %u\n", data->rounding_mode);
valgrind_vex_inject_ir();
valgrind_get_vbits(&data->result);
if (verbose > 2) {
printf("result: ");
print_opnd(stdout, &data->result);
printf("\n");
}
}
Binary file not shown.
@@ -0,0 +1,2 @@
prog: vbit-test
vgopts: -q
@@ -0,0 +1,778 @@
/* -*- mode: C; c-basic-offset: 3; -*- */
#include <stdio.h> // fprintf
#include <assert.h> // assert
#if defined(__APPLE__)
#include <machine/endian.h>
#define __BYTE_ORDER BYTE_ORDER
#define __LITTLE_ENDIAN LITTLE_ENDIAN
#elif defined(__sun)
#define __LITTLE_ENDIAN 1234
#define __BIG_ENDIAN 4321
# if defined(_LITTLE_ENDIAN)
# define __BYTE_ORDER __LITTLE_ENDIAN
# else
# define __BYTE_ORDER __BIG_ENDIAN
# endif
#else
#include <endian.h>
#endif
#include <inttypes.h>
#include "vbits.h"
#include "vtest.h"
/* Return the bits of V if they fit into 64-bit. If V has fewer than
64 bits, the bit pattern is zero-extended to the left. */
static uint64_t
get_bits64(vbits_t v)
{
switch (v.num_bits) {
case 1: return v.bits.u32;
case 8: return v.bits.u8;
case 16: return v.bits.u16;
case 32: return v.bits.u32;
case 64: return v.bits.u64;
case 128:
case 256:
/* fall through */
default:
panic(__func__);
}
}
void
print_vbits(FILE *fp, vbits_t v)
{
switch (v.num_bits) {
case 1: fprintf(fp, "%08x", v.bits.u32); break;
case 8: fprintf(fp, "%02x", v.bits.u8); break;
case 16: fprintf(fp, "%04x", v.bits.u16); break;
case 32: fprintf(fp, "%08x", v.bits.u32); break;
case 64: fprintf(fp, "%016"PRIx64, v.bits.u64); break;
case 128:
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
fprintf(fp, "%016"PRIx64, v.bits.u128[1]);
fprintf(fp, "%016"PRIx64, v.bits.u128[0]);
} else {
fprintf(fp, "%016"PRIx64, v.bits.u128[0]);
fprintf(fp, "%016"PRIx64, v.bits.u128[1]);
}
break;
case 256:
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
fprintf(fp, "%016"PRIx64, v.bits.u256[3]);
fprintf(fp, "%016"PRIx64, v.bits.u256[2]);
fprintf(fp, "%016"PRIx64, v.bits.u256[1]);
fprintf(fp, "%016"PRIx64, v.bits.u256[0]);
} else {
fprintf(fp, "%016"PRIx64, v.bits.u256[0]);
fprintf(fp, "%016"PRIx64, v.bits.u256[1]);
fprintf(fp, "%016"PRIx64, v.bits.u256[2]);
fprintf(fp, "%016"PRIx64, v.bits.u256[3]);
}
break;
default:
panic(__func__);
}
}
/* Return a value where all bits are set to undefined. */
vbits_t
undefined_vbits(unsigned num_bits)
{
vbits_t new = { .num_bits = num_bits };
switch (num_bits) {
case 1: new.bits.u32 = 0x01; break;
case 8: new.bits.u8 = 0xff; break;
case 16: new.bits.u16 = 0xffff; break;
case 32: new.bits.u32 = ~0; break;
case 64: new.bits.u64 = ~0ull; break;
case 128: new.bits.u128[0] = ~0ull;
new.bits.u128[1] = ~0ull;
break;
case 256: new.bits.u256[0] = ~0ull;
new.bits.u256[1] = ~0ull;
new.bits.u256[2] = ~0ull;
new.bits.u256[3] = ~0ull;
break;
default:
panic(__func__);
}
return new;
}
/* Return a value where all bits are set to defined. */
vbits_t
defined_vbits(unsigned num_bits)
{
vbits_t new = { .num_bits = num_bits };
switch (num_bits) {
case 1: new.bits.u32 = 0x0; break;
case 8: new.bits.u8 = 0x0; break;
case 16: new.bits.u16 = 0x0; break;
case 32: new.bits.u32 = 0x0; break;
case 64: new.bits.u64 = 0x0; break;
case 128: new.bits.u128[0] = 0x0;
new.bits.u128[1] = 0x0;
break;
case 256: new.bits.u256[0] = 0x0;
new.bits.u256[1] = 0x0;
new.bits.u256[2] = 0x0;
new.bits.u256[3] = 0x0;
break;
default:
panic(__func__);
}
return new;
}
/* Return 1, if equal. */
int
equal_vbits(vbits_t v1, vbits_t v2)
{
assert(v1.num_bits == v2.num_bits);
switch (v1.num_bits) {
case 1: return v1.bits.u32 == v2.bits.u32;
case 8: return v1.bits.u8 == v2.bits.u8;
case 16: return v1.bits.u16 == v2.bits.u16;
case 32: return v1.bits.u32 == v2.bits.u32;
case 64: return v1.bits.u64 == v2.bits.u64;
case 128: return v1.bits.u128[0] == v2.bits.u128[0] &&
v1.bits.u128[1] == v2.bits.u128[1];
case 256: return v1.bits.u256[0] == v2.bits.u256[0] &&
v1.bits.u256[1] == v2.bits.u256[1] &&
v1.bits.u256[2] == v2.bits.u256[2] &&
v1.bits.u256[3] == v2.bits.u256[3];
default:
panic(__func__);
}
}
/* Truncate the bit pattern in V1 to NUM_BITS bits */
vbits_t
truncate_vbits(vbits_t v, unsigned num_bits)
{
assert(num_bits <= v.num_bits);
if (num_bits == v.num_bits) return v;
vbits_t new = { .num_bits = num_bits };
if (num_bits <= 64) {
uint64_t bits;
if (v.num_bits <= 64)
bits = get_bits64(v);
else if (v.num_bits == 128)
if (__BYTE_ORDER == __LITTLE_ENDIAN)
bits = v.bits.u128[0];
else
bits = v.bits.u128[1];
else if (v.num_bits == 256)
if (__BYTE_ORDER == __LITTLE_ENDIAN)
bits = v.bits.u256[0];
else
bits = v.bits.u256[3];
else
panic(__func__);
switch (num_bits) {
case 1: new.bits.u32 = bits & 0x01; break;
case 8: new.bits.u8 = bits & 0xff; break;
case 16: new.bits.u16 = bits & 0xffff; break;
case 32: new.bits.u32 = bits & ~0u; break;
case 64: new.bits.u64 = bits & ~0ll; break;
default:
panic(__func__);
}
return new;
}
if (num_bits == 128) {
assert(v.num_bits == 256);
/* From 256 bits to 128 */
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
new.bits.u128[0] = v.bits.u256[0];
new.bits.u128[1] = v.bits.u256[1];
} else {
new.bits.u128[0] = v.bits.u256[2];
new.bits.u128[1] = v.bits.u256[3];
}
return new;
}
/* Cannot truncate to 256 bits from something larger */
panic(__func__);
}
/* Helper function to compute left_vbits */
static uint64_t
left64(uint64_t x)
{
// left(x) = x | -x
return x | (~x + 1);
}
vbits_t
left_vbits(vbits_t v, unsigned num_bits)
{
assert(num_bits >= v.num_bits);
vbits_t new = { .num_bits = num_bits };
if (v.num_bits <= 64) {
uint64_t bits = left64(get_bits64(v));
switch (num_bits) {
case 8: new.bits.u8 = bits & 0xff; break;
case 16: new.bits.u16 = bits & 0xffff; break;
case 32: new.bits.u32 = bits & ~0u; break;
case 64: new.bits.u64 = bits & ~0ll; break;
case 128:
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
new.bits.u128[0] = bits;
if (bits & (1ull << 63)) { // MSB is set
new.bits.u128[1] = ~0ull;
} else {
new.bits.u128[1] = 0;
}
} else {
new.bits.u128[1] = bits;
if (bits & (1ull << 63)) { // MSB is set
new.bits.u128[0] = ~0ull;
} else {
new.bits.u128[0] = 0;
}
}
break;
case 256:
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
new.bits.u256[0] = bits;
if (bits & (1ull << 63)) { // MSB is set
new.bits.u256[1] = ~0ull;
new.bits.u256[2] = ~0ull;
new.bits.u256[3] = ~0ull;
} else {
new.bits.u256[1] = 0;
new.bits.u256[2] = 0;
new.bits.u256[3] = 0;
}
} else {
new.bits.u256[3] = bits;
if (bits & (1ull << 63)) { // MSB is set
new.bits.u256[0] = ~0ull;
new.bits.u256[1] = ~0ull;
new.bits.u256[2] = ~0ull;
} else {
new.bits.u256[0] = 0;
new.bits.u256[1] = 0;
new.bits.u256[2] = 0;
}
}
break;
default:
panic(__func__);
}
return new;
}
if (v.num_bits == 128) {
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
if (v.bits.u128[1] != 0) {
new.bits.u128[0] = v.bits.u128[0];
new.bits.u128[1] = left64(v.bits.u128[1]);
} else {
new.bits.u128[0] = left64(v.bits.u128[0]);
if (new.bits.u128[0] & (1ull << 63)) { // MSB is set
new.bits.u128[1] = ~0ull;
} else {
new.bits.u128[1] = 0;
}
}
} else {
if (v.bits.u128[0] != 0) {
new.bits.u128[0] = left64(v.bits.u128[0]);
new.bits.u128[1] = v.bits.u128[1];
} else {
new.bits.u128[1] = left64(v.bits.u128[1]);
if (new.bits.u128[1] & (1ull << 63)) { // MSB is set
new.bits.u128[0] = ~0ull;
} else {
new.bits.u128[0] = 0;
}
}
}
if (num_bits == 128) return new;
assert(num_bits == 256);
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
uint64_t b1 = new.bits.u128[1];
uint64_t b0 = new.bits.u128[0];
new.bits.u256[0] = b0;
new.bits.u256[1] = b1;
if (new.bits.u256[1] & (1ull << 63)) { // MSB is set
new.bits.u256[2] = ~0ull;
new.bits.u256[3] = ~0ull;
} else {
new.bits.u256[2] = 0;
new.bits.u256[3] = 0;
}
} else {
uint64_t b1 = new.bits.u128[0];
uint64_t b0 = new.bits.u128[1];
new.bits.u256[2] = b0;
new.bits.u256[3] = b1;
if (new.bits.u256[2] & (1ull << 63)) { // MSB is set
new.bits.u256[0] = ~0ull;
new.bits.u256[1] = ~0ull;
} else {
new.bits.u256[0] = 0;
new.bits.u256[1] = 0;
}
}
return new;
}
panic(__func__);
}
vbits_t
or_vbits(vbits_t v1, vbits_t v2)
{
assert(v1.num_bits == v2.num_bits);
vbits_t new = { .num_bits = v1.num_bits };
switch (v1.num_bits) {
case 8: new.bits.u8 = v1.bits.u8 | v2.bits.u8; break;
case 16: new.bits.u16 = v1.bits.u16 | v2.bits.u16; break;
case 32: new.bits.u32 = v1.bits.u32 | v2.bits.u32; break;
case 64: new.bits.u64 = v1.bits.u64 | v2.bits.u64; break;
case 128: new.bits.u128[0] = v1.bits.u128[0] | v2.bits.u128[0];
new.bits.u128[1] = v1.bits.u128[1] | v2.bits.u128[1];
break;
case 256: new.bits.u256[0] = v1.bits.u256[0] | v2.bits.u256[0];
new.bits.u256[1] = v1.bits.u256[1] | v2.bits.u256[1];
new.bits.u256[2] = v1.bits.u256[2] | v2.bits.u256[2];
new.bits.u256[3] = v1.bits.u256[3] | v2.bits.u256[3];
break;
default:
panic(__func__);
}
return new;
}
vbits_t
and_vbits(vbits_t v1, vbits_t v2)
{
assert(v1.num_bits == v2.num_bits);
vbits_t new = { .num_bits = v1.num_bits };
switch (v1.num_bits) {
case 8: new.bits.u8 = v1.bits.u8 & v2.bits.u8; break;
case 16: new.bits.u16 = v1.bits.u16 & v2.bits.u16; break;
case 32: new.bits.u32 = v1.bits.u32 & v2.bits.u32; break;
case 64: new.bits.u64 = v1.bits.u64 & v2.bits.u64; break;
case 128: new.bits.u128[0] = v1.bits.u128[0] & v2.bits.u128[0];
new.bits.u128[1] = v1.bits.u128[1] & v2.bits.u128[1];
break;
case 256: new.bits.u256[0] = v1.bits.u256[0] & v2.bits.u256[0];
new.bits.u256[1] = v1.bits.u256[1] & v2.bits.u256[1];
new.bits.u256[2] = v1.bits.u256[2] & v2.bits.u256[2];
new.bits.u256[3] = v1.bits.u256[3] & v2.bits.u256[3];
break;
default:
panic(__func__);
}
return new;
}
vbits_t
concat_vbits(vbits_t v1, vbits_t v2)
{
assert(v1.num_bits == v2.num_bits);
vbits_t new = { .num_bits = v1.num_bits * 2 };
switch (v1.num_bits) {
case 8: new.bits.u16 = v1.bits.u8;
new.bits.u16 = (new.bits.u16 << 8) | v2.bits.u8; break;
case 16: new.bits.u32 = v1.bits.u16;
new.bits.u32 = (new.bits.u32 << 16) | v2.bits.u16; break;
case 32: new.bits.u64 = v1.bits.u32;
new.bits.u64 = (new.bits.u64 << 32) | v2.bits.u32; break;
case 64:
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
new.bits.u128[0] = v2.bits.u64;
new.bits.u128[1] = v1.bits.u64;
} else {
new.bits.u128[0] = v1.bits.u64;
new.bits.u128[1] = v2.bits.u64;
}
break;
case 128:
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
new.bits.u256[0] = v2.bits.u128[0];
new.bits.u256[1] = v2.bits.u128[1];
new.bits.u256[2] = v1.bits.u128[0];
new.bits.u256[3] = v1.bits.u128[1];
} else {
new.bits.u256[0] = v1.bits.u128[0];
new.bits.u256[1] = v1.bits.u128[1];
new.bits.u256[2] = v2.bits.u128[0];
new.bits.u256[3] = v2.bits.u128[1];
}
break;
case 256: /* Fall through */
default:
panic(__func__);
}
return new;
}
vbits_t
upper_vbits(vbits_t v)
{
vbits_t new = { .num_bits = v.num_bits / 2 };
switch (v.num_bits) {
case 16: new.bits.u8 = v.bits.u16 >> 8; break;
case 32: new.bits.u16 = v.bits.u32 >> 16; break;
case 64: new.bits.u32 = v.bits.u64 >> 32; break;
case 128:
if (__BYTE_ORDER == __LITTLE_ENDIAN)
new.bits.u64 = v.bits.u128[1];
else
new.bits.u64 = v.bits.u128[0];
break;
case 256:
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
new.bits.u128[0] = v.bits.u256[2];
new.bits.u128[1] = v.bits.u256[3];
} else {
new.bits.u128[0] = v.bits.u256[0];
new.bits.u128[1] = v.bits.u256[1];
}
break;
case 8:
default:
panic(__func__);
}
return new;
}
vbits_t
zextend_vbits(vbits_t v, unsigned num_bits)
{
assert(num_bits >= v.num_bits);
if (num_bits == v.num_bits) return v;
vbits_t new = { .num_bits = num_bits };
if (v.num_bits <= 64) {
uint64_t bits = get_bits64(v);
switch (num_bits) {
case 8: new.bits.u8 = bits; break;
case 16: new.bits.u16 = bits; break;
case 32: new.bits.u32 = bits; break;
case 64: new.bits.u64 = bits; break;
case 128:
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
new.bits.u128[0] = bits;
new.bits.u128[1] = 0;
} else {
new.bits.u128[0] = 0;
new.bits.u128[1] = bits;
}
break;
case 256:
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
new.bits.u256[0] = bits;
new.bits.u256[1] = 0;
new.bits.u256[2] = 0;
new.bits.u256[3] = 0;
} else {
new.bits.u256[0] = 0;
new.bits.u256[1] = 0;
new.bits.u256[2] = 0;
new.bits.u256[3] = bits;
}
break;
default:
panic(__func__);
}
return new;
}
if (v.num_bits == 128) {
assert(num_bits == 256);
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
new.bits.u256[0] = v.bits.u128[0];
new.bits.u256[1] = v.bits.u128[1];
new.bits.u256[2] = 0;
new.bits.u256[3] = 0;
} else {
new.bits.u256[0] = 0;
new.bits.u256[1] = 0;
new.bits.u256[2] = v.bits.u128[1];
new.bits.u256[3] = v.bits.u128[0];
}
return new;
}
/* Cannot zero-extend a 256-bit value to something larger */
panic(__func__);
}
vbits_t
sextend_vbits(vbits_t v, unsigned num_bits)
{
assert(num_bits >= v.num_bits);
int sextend = 0;
switch (v.num_bits) {
case 8: if (v.bits.u8 == 0x80) sextend = 1; break;
case 16: if (v.bits.u16 == 0x8000) sextend = 1; break;
case 32: if (v.bits.u32 == 0x80000000) sextend = 1; break;
case 64: if (v.bits.u64 == (1ull << 63)) sextend = 1; break;
case 128: if (v.bits.u128[1] == (1ull << 63)) sextend = 1; break;
case 256: if (v.bits.u256[3] == (1ull << 63)) sextend = 1; break;
default:
panic(__func__);
}
return sextend ? left_vbits(v, num_bits) : zextend_vbits(v, num_bits);
}
vbits_t
onehot_vbits(unsigned bitno, unsigned num_bits)
{
assert(bitno < num_bits);
vbits_t new = { .num_bits = num_bits };
switch (num_bits) {
case 1: new.bits.u32 = 1 << bitno; break;
case 8: new.bits.u8 = 1 << bitno; break;
case 16: new.bits.u16 = 1 << bitno; break;
case 32: new.bits.u32 = 1u << bitno; break;
case 64: new.bits.u64 = 1ull << bitno; break;
case 128:
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
if (bitno < 64) {
new.bits.u128[0] = 1ull << bitno;
new.bits.u128[1] = 0;
} else {
new.bits.u128[0] = 0;
new.bits.u128[1] = 1ull << (bitno - 64);
}
} else {
if (bitno < 64) {
new.bits.u128[0] = 0;
new.bits.u128[1] = 1ull << bitno;
} else {
new.bits.u128[0] = 1ull << (bitno - 64);
new.bits.u128[1] = 0;
}
}
break;
case 256:
if (__BYTE_ORDER == __LITTLE_ENDIAN) {
if (bitno < 64) {
new.bits.u256[0] = 1ull << bitno;
new.bits.u256[1] = 0;
new.bits.u256[2] = 0;
new.bits.u256[3] = 0;
} else if (bitno < 128) {
new.bits.u256[0] = 0;
new.bits.u256[1] = 1ull << (bitno - 64);
new.bits.u256[2] = 0;
new.bits.u256[3] = 0;
} else if (bitno < 192) {
new.bits.u256[0] = 0;
new.bits.u256[1] = 0;
new.bits.u256[2] = 1ull << (bitno - 128);
new.bits.u256[3] = 0;
} else {
new.bits.u256[0] = 0;
new.bits.u256[1] = 0;
new.bits.u256[2] = 0;
new.bits.u256[3] = 1ull << (bitno - 192);
}
} else {
if (bitno < 64) {
new.bits.u256[0] = 0;
new.bits.u256[1] = 0;
new.bits.u256[2] = 0;
new.bits.u256[3] = 1ull << bitno;
} else if (bitno < 128) {
new.bits.u256[0] = 0;
new.bits.u256[1] = 0;
new.bits.u256[2] = 1ull << (bitno - 64);
new.bits.u256[3] = 0;
} else if (bitno < 192) {
new.bits.u256[0] = 0;
new.bits.u256[1] = 1ull << (bitno - 128);
new.bits.u256[2] = 0;
new.bits.u256[3] = 0;
} else {
new.bits.u256[0] = 1ull << (bitno - 192);
new.bits.u256[1] = 0;
new.bits.u256[2] = 0;
new.bits.u256[3] = 0;
}
}
break;
default:
panic(__func__);
}
return new;
}
int
completely_defined_vbits(vbits_t v)
{
return equal_vbits(v, defined_vbits(v.num_bits));
}
vbits_t
shl_vbits(vbits_t v, unsigned shift_amount)
{
assert(shift_amount < v.num_bits);
vbits_t new = v;
switch (v.num_bits) {
case 8: new.bits.u8 <<= shift_amount; break;
case 16: new.bits.u16 <<= shift_amount; break;
case 32: new.bits.u32 <<= shift_amount; break;
case 64: new.bits.u64 <<= shift_amount; break;
case 128: /* fall through */
case 256: /* fall through */
default:
panic(__func__);
}
return new;
}
vbits_t
shr_vbits(vbits_t v, unsigned shift_amount)
{
assert(shift_amount < v.num_bits);
vbits_t new = v;
switch (v.num_bits) {
case 8: new.bits.u8 >>= shift_amount; break;
case 16: new.bits.u16 >>= shift_amount; break;
case 32: new.bits.u32 >>= shift_amount; break;
case 64: new.bits.u64 >>= shift_amount; break;
case 128: /* fall through */
case 256: /* fall through */
default:
panic(__func__);
}
return new;
}
vbits_t
sar_vbits(vbits_t v, unsigned shift_amount)
{
assert(shift_amount < v.num_bits);
vbits_t new = v;
int msb;
switch (v.num_bits) {
case 8:
new.bits.u8 >>= shift_amount;
msb = (v.bits.u8 & 0x80) != 0;
break;
case 16:
new.bits.u16 >>= shift_amount;
msb = (v.bits.u16 & 0x8000) != 0;
break;
case 32:
new.bits.u32 >>= shift_amount;
msb = (v.bits.u32 & (1u << 31)) != 0;
break;
case 64:
new.bits.u64 >>= shift_amount;
msb = (v.bits.u64 & (1ull << 63)) != 0;
break;
case 128: /* fall through */
case 256: /* fall through */
default:
panic(__func__);
}
if (msb)
new = left_vbits(new, new.num_bits);
return new;
}
/* Return a value for the POWER Iop_CmpORD class iops */
vbits_t
cmpord_vbits(unsigned v1_num_bits, unsigned v2_num_bits)
{
vbits_t new = { .num_bits = v1_num_bits };
/* Size of values being compared must be the same */
assert( v1_num_bits == v2_num_bits);
/* Comparison only produces 32-bit or 64-bit value where
* the lower 3 bits are set to indicate, less than, equal and greater then.
*/
switch (v1_num_bits) {
case 32:
new.bits.u32 = 0xE;
break;
case 64:
new.bits.u64 = 0xE;
break;
default:
panic(__func__);
}
return new;
}
@@ -0,0 +1,58 @@
/* -*- mode: C; c-basic-offset: 3; -*- */
#ifndef VBITS_H
#define VBITS_H
#include <stdint.h>
#include <stdio.h>
typedef uint64_t uint128_t[2];
typedef uint64_t uint256_t[4];
/* A type to represent V-bits */
typedef struct {
unsigned num_bits;
union {
uint8_t u8;
uint16_t u16;
uint32_t u32;
uint64_t u64;
uint128_t u128;
uint256_t u256;
} bits;
} vbits_t;
/* A type large enough to hold any IRtype'd value. At this point
we do not expect to test with specific floating point values.
So we don't need to represent them. */
typedef union {
uint8_t u8;
uint16_t u16;
uint32_t u32;
uint64_t u64;
uint128_t u128;
uint256_t u256;
} value_t;
void print_vbits(FILE *, vbits_t);
vbits_t undefined_vbits(unsigned num_bits);
vbits_t defined_vbits(unsigned num_bits);
int equal_vbits(vbits_t, vbits_t);
vbits_t truncate_vbits(vbits_t, unsigned num_bits);
vbits_t left_vbits(vbits_t, unsigned num_bits);
vbits_t or_vbits(vbits_t, vbits_t);
vbits_t and_vbits(vbits_t, vbits_t);
vbits_t concat_vbits(vbits_t, vbits_t);
vbits_t upper_vbits(vbits_t);
vbits_t sextend_vbits(vbits_t, unsigned num_bits);
vbits_t zextend_vbits(vbits_t, unsigned num_bits);
vbits_t onehot_vbits(unsigned bitno, unsigned num_bits);
vbits_t shl_vbits(vbits_t, unsigned amount);
vbits_t shr_vbits(vbits_t, unsigned amount);
vbits_t sar_vbits(vbits_t, unsigned amount);
int completely_defined_vbits(vbits_t);
vbits_t cmpord_vbits(unsigned v1_num_bits, unsigned v2_num_bits);
#endif // VBITS_H
@@ -0,0 +1,137 @@
/* -*- mode: C; c-basic-offset: 3; -*- */
#ifndef VTEST_H
#define VTEST_H
/* Main header file for the V-bit tester */
#include <stdint.h> // uint64_t
#include "libvex.h" // IROp
#include "vbits.h" // vbits_t
/* How undefinedness propagates from input to output */
typedef enum {
// For any undefined input bit, all output bits are defined.
UNDEF_NONE,
// For any undefined input bit, all output bits are undefined.
UNDEF_ALL,
// For each undefined input bit, the corresponding output bit
// in the same position is undefined. No other bit is undefined.
UNDEF_SAME,
// For each undefined input bit, the corresponding output bit
// in the same position is undefined. No other bit is undefined.
// If the corresponding output bit does not exist, the input bit
// does not cause any output bits to be undefined.
UNDEF_TRUNC,
// For each undefined input bit, the corresponding output bit
// in the same position is undefined. No other bit is undefined.
// Output bits that do no not have a corresponding input bit are
// defined.
UNDEF_ZEXT,
// For each undefined input bit, the corresponding output bit
// in the same position is undefined. If the MSB of the input value
// is undefined, so are all output bits with higher significance
// than the MSB input bit.
UNDEF_SEXT,
// For each undefined input bit, the corresponding output bit
// and all output bits with higher significance are undefined.
UNDEF_LEFT,
UNDEF_CONCAT, // nHLto2n ops e.g. Iop_32HLto64
UNDEF_UPPER, // 2nHIton ops e.g. Iop_64HIto32
UNDEF_SHL, // shift-left
UNDEF_SHR, // logical shift-right
UNDEF_SAR, // arithmetic shift-right
UNDEF_OR, // bitwise OR operation
UNDEF_AND, // bitwise AND operation
UNDEF_ORD, // Iop_CmpORD compare
// For IROps I don't know anything about
UNDEF_UNKNOWN
} undef_t;
// Everything we want to know about an IROp
typedef struct {
IROp op;
const char *name;
undef_t undef_kind;
int shift_amount_is_immediate;
// Indicate whether IROp can be tested on a particular architecture
unsigned s390x : 1;
unsigned amd64 : 1;
unsigned ppc32 : 1;
unsigned ppc64 : 1;
unsigned arm : 1;
unsigned arm64 : 1;
unsigned x86 : 1;
unsigned mips32 : 1;
unsigned mips64 : 1;
unsigned tilegx : 1;
} irop_t;
/* The maximum number of input operands */
#define MAX_OPERANDS 4
/* An operand of an IROp (also used for the result) */
typedef struct {
IRType type;
vbits_t vbits;
value_t value;
} opnd_t;
/* Carries the data needed to execute and evaluate a test. I.e.
inputs and results (V-bits and actual value). */
typedef struct {
opnd_t result;
opnd_t opnds[MAX_OPERANDS];
unsigned rounding_mode;
} test_data_t;
/* Function prototypes */
irop_t *get_irop(IROp);
int is_floating_point_op_with_rounding_mode(IROp);
int get_num_operands(IROp);
void print_opnd(FILE *, const opnd_t *);
int test_unary_op(const irop_t *, test_data_t *);
int test_binary_op(const irop_t *, test_data_t *);
int test_ternary_op(const irop_t *, test_data_t *);
int test_qernary_op(const irop_t *, test_data_t *);
void valgrind_vex_init_for_iri(IRICB *);
void valgrind_execute_test(const irop_t *, test_data_t *);
IRICB new_iricb(const irop_t *, test_data_t *);
void panic(const char *) __attribute__((noreturn));
void complain(const irop_t *, const test_data_t *, vbits_t expected);
/* Imported from VEX */
unsigned sizeof_irtype(IRType);
void typeof_primop(IROp, IRType *t_dst, IRType *t_arg1, IRType *t_arg2,
IRType *t_arg3, IRType *t_arg4);
static __inline__ unsigned bitsof_irtype(IRType type)
{
return type == Ity_I1 ? 1 : sizeof_irtype(type) * 8;
}
/* Exported variables */
extern int verbose;
#endif // VTEST_H