1/* -*- mode: C; c-basic-offset: 3; -*- */ 2 3/* 4 This file is part of MemCheck, a heavyweight Valgrind tool for 5 detecting memory errors. 6 7 Copyright (C) 2012-2015 Florian Krohm 8 9 This program is free software; you can redistribute it and/or 10 modify it under the terms of the GNU General Public License as 11 published by the Free Software Foundation; either version 2 of the 12 License, or (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, but 15 WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 22 02111-1307, USA. 23 24 The GNU General Public License is contained in the file COPYING. 25*/ 26 27#include <assert.h> // assert 28#include <stdio.h> // printf 29#include <stdlib.h> // malloc 30#include <string.h> // memset 31#include "valgrind.h" // RUNNING_ON_VALGRIND 32#include "vtest.h" 33 34 35static test_data_t * 36new_test_data(const irop_t *op) 37{ 38 test_data_t *data = malloc(sizeof *data); 39 40 memset(data, 0x0, sizeof *data); // initialise 41 42 /* Obtain the operand types and set them */ 43 IRType t_dst, t1, t2, t3, t4; 44 45 typeof_primop(op->op, &t_dst, &t1, &t2, &t3, &t4); 46 assert(t_dst != Ity_INVALID); 47 assert(t1 != Ity_INVALID); 48 49 data->result.type = t_dst; 50 if (is_floating_point_op_with_rounding_mode(op->op)) { 51 data->opnds[0].type = t2; 52 data->opnds[1].type = t3; 53 data->opnds[2].type = t4; 54 data->opnds[3].type = Ity_INVALID; 55 } else { 56 data->opnds[0].type = t1; 57 data->opnds[1].type = t2; 58 data->opnds[2].type = t3; 59 data->opnds[3].type = t4; 60 } 61 62 /* Set the rounding mode if the operation requires one. 63 FIXME: We should iterate over all rounding modes. For that need 64 FIXME: to distinguish between binary and decimal floating point */ 65 if (is_floating_point_op_with_rounding_mode(op->op)) { 66 // for now just pick one 67 data->rounding_mode = Irrm_NEAREST; // same as Irrm_DFP_NEAREST 68 } else { 69 data->rounding_mode = NO_ROUNDING_MODE; 70 } 71 72 return data; 73} 74 75int verbose = 0; 76 77 78/* Certain IROps require special handling. */ 79static void 80fixup_irops(void) 81{ 82#ifdef __powerpc__ 83 get_irop(Iop_ShlD64)->shift_amount_is_immediate = 1; 84 get_irop(Iop_ShrD64)->shift_amount_is_immediate = 1; 85 get_irop(Iop_ShlD128)->shift_amount_is_immediate = 1; 86 get_irop(Iop_ShrD128)->shift_amount_is_immediate = 1; 87#endif 88} 89 90 91int 92main(int argc, char *argv[]) 93{ 94 assert(sizeof(long long) == 8); 95 int num_unary_tests = 0, num_binary_tests = 0; 96 int num_ternary_tests = 0, num_qernary_tests = 0; 97 98 for (int i = 1; i < argc; ++i) { 99 if (strcmp(argv[i], "-v") == 0) ++verbose; 100 else if (strcmp(argv[i], "--help") == 0) { 101 printf("\nvbit-test [ -v | --help ]\n"); 102 printf("\n\t-v verbose mode; show number of tests\n"); 103 printf("\n\t-v -v verbose mode; shows IROps being tested\n"); 104 printf("\n\t-v -v -v verbose mode, extreme edition\n\n"); 105 return 0; 106 } else { 107 printf("%s ? Nothing happens.\n", argv[i]); 108 return 1; 109 } 110 } 111 112 if (! RUNNING_ON_VALGRIND) { 113 fprintf(stderr, "*** This program needs to run under memcheck.\n"); 114 return 1; 115 } 116 117 setbuf(stdout, NULL); // make stdout unbuffered 118 119 fixup_irops(); // determine need for special handling 120 121 // Iterate over all primops 122 IROp first = Iop_INVALID + 1; 123 IROp last = Iop_LAST; 124 IROp opkind; 125 126 if (0) { // overwrite for debugging 127 first = Iop_CasCmpEQ8; last = first + 1; 128 } 129 130 // Iterate over all IROps in the enum type. That is the only way to 131 // make sure the operator is tested on at least one platform. 132 133 // Loop assumes no holes in the enumerator values 134 for (opkind = first; opkind < last; ++opkind) { 135 136 const irop_t *op = get_irop(opkind); 137 if (op == NULL) continue; 138 139 if (op->undef_kind == UNDEF_UNKNOWN) { 140 fprintf(stderr, "...skipping %s; unknown undef propagation\n", 141 op->name); 142 continue; 143 } 144 145 test_data_t *data = new_test_data(op); 146 147 if (verbose > 1) printf("Testing operator %s\n", op->name); 148 149 IRICB iricb = new_iricb(op, data); 150 151 valgrind_vex_init_for_iri(&iricb); 152 153 switch (iricb.num_operands) { 154 case 1: 155 num_unary_tests += test_unary_op(op, data); 156 break; 157 158 case 2: 159 num_binary_tests += test_binary_op(op, data); 160 break; 161 162 case 3: 163 num_ternary_tests += test_ternary_op(op, data); 164 break; 165 166 case 4: 167 num_qernary_tests += test_qernary_op(op, data); 168 break; 169 170 default: 171 panic("operator not handled"); 172 } 173 174 free(data); 175 } 176 177 if (verbose) 178 printf("\nvbit-test ran %d unary, %d binary, %d ternary and" 179 " %d qernary tests.\n\n", 180 num_unary_tests, num_binary_tests, num_ternary_tests, 181 num_qernary_tests); 182 return 0; 183} 184