1 /* -*- mode: C; c-basic-offset: 3; -*- */
2
3 #include <assert.h> // assert
4 #include <stdio.h> // printf
5 #include <stdlib.h> // malloc
6 #include <string.h> // memset
7 #include "valgrind.h" // RUNNING_ON_VALGRIND
8 #include "vtest.h"
9
10
11 static test_data_t *
new_test_data(const irop_t * op)12 new_test_data(const irop_t *op)
13 {
14 test_data_t *data = malloc(sizeof *data);
15
16 memset(data, 0x0, sizeof *data); // initialise
17
18 /* Obtain the operand types and set them */
19 IRType t_dst, t1, t2, t3, t4;
20
21 typeof_primop(op->op, &t_dst, &t1, &t2, &t3, &t4);
22 assert(t_dst != Ity_INVALID);
23 assert(t1 != Ity_INVALID);
24
25 data->result.type = t_dst;
26 if (is_floating_point_op_with_rounding_mode(op->op)) {
27 data->opnds[0].type = t2;
28 data->opnds[1].type = t3;
29 data->opnds[2].type = t4;
30 data->opnds[3].type = Ity_INVALID;
31 } else {
32 data->opnds[0].type = t1;
33 data->opnds[1].type = t2;
34 data->opnds[2].type = t3;
35 data->opnds[3].type = t4;
36 }
37
38 /* Set the rounding mode if the operation requires one.
39 FIXME: We should iterate over all rounding modes. For that need
40 FIXME: to distinguish between binary and decimal floating point */
41 if (is_floating_point_op_with_rounding_mode(op->op)) {
42 // for now just pick one
43 data->rounding_mode = Irrm_NEAREST; // same as Irrm_DFP_NEAREST
44 } else {
45 data->rounding_mode = NO_ROUNDING_MODE;
46 }
47
48 return data;
49 }
50
51 int verbose = 0;
52
53
54 /* Certain IROps require special handling. */
55 static void
fixup_irops(void)56 fixup_irops(void)
57 {
58 #ifdef __powerpc__
59 get_irop(Iop_ShlD64)->shift_amount_is_immediate = 1;
60 get_irop(Iop_ShrD64)->shift_amount_is_immediate = 1;
61 get_irop(Iop_ShlD128)->shift_amount_is_immediate = 1;
62 get_irop(Iop_ShrD128)->shift_amount_is_immediate = 1;
63 #endif
64 }
65
66
67 int
main(int argc,char * argv[])68 main(int argc, char *argv[])
69 {
70 assert(sizeof(long long) == 8);
71 int num_unary_tests = 0, num_binary_tests = 0;
72 int num_ternary_tests = 0, num_qernary_tests = 0;
73
74 for (int i = 1; i < argc; ++i) {
75 if (strcmp(argv[i], "-v") == 0) ++verbose;
76 else if (strcmp(argv[i], "--help") == 0) {
77 printf("\nvbit-test [ -v | --help ]\n");
78 printf("\n\t-v verbose mode; show number of 1, 2, 3 and 4 operand tests\n");
79 printf("\n\t-v -v verbose mode; shows IROps being tested\n");
80 printf("\n\t-v -v -v verbose mode, extreme edition\n\n");
81 return 0;
82 } else {
83 printf("%s ? Nothing happens.\n", argv[i]);
84 return 1;
85 }
86 }
87
88 if (! RUNNING_ON_VALGRIND) {
89 fprintf(stderr, "*** This program needs to run under memcheck.\n");
90 return 1;
91 }
92
93 setbuf(stdout, NULL); // make stdout unbuffered
94
95 fixup_irops(); // determine need for special handling
96
97 // Iterate over all primops
98 IROp first = Iop_INVALID + 1;
99 IROp last = Iop_LAST;
100 IROp opkind;
101
102 if (0) { // overwrite for debugging
103 first = Iop_CasCmpEQ8; last = first + 1;
104 }
105
106 // Iterate over all IROps in the enum type. That is the only way to
107 // make sure the operator is tested on at least one platform.
108
109 // Loop assumes no holes in the enumerator values
110 for (opkind = first; opkind < last; ++opkind) {
111
112 const irop_t *op = get_irop(opkind);
113 if (op == NULL) continue;
114
115 test_data_t *data = new_test_data(op);
116
117 if (op->undef_kind == UNDEF_UNKNOWN) {
118 fprintf(stderr, "...skipping %s; unknown undef propagation\n",
119 op->name);
120 continue;
121 }
122
123 if (verbose > 1) printf("Testing operator %s\n", op->name);
124
125 IRICB iricb = new_iricb(op, data);
126
127 valgrind_vex_init_for_iri(&iricb);
128
129 switch (iricb.num_operands) {
130 case 1:
131 num_unary_tests += test_unary_op(op, data);
132 break;
133
134 case 2:
135 num_binary_tests += test_binary_op(op, data);
136 break;
137
138 case 3:
139 num_ternary_tests += test_ternary_op(op, data);
140 break;
141
142 case 4:
143 num_qernary_tests += test_qernary_op(op, data);
144 break;
145
146 default:
147 panic("operator not handled");
148 }
149
150 free(data);
151 }
152
153 if (verbose)
154 printf("\nvbit-test ran %d unary, %d binary, %d ternary and %d qernary tests.\n",
155 num_unary_tests, num_binary_tests, num_ternary_tests,
156 num_qernary_tests);
157 return 0;
158 }
159