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 <stdio.h> // fprintf 28 #include <stdlib.h> // exit 29 #include <assert.h> // assert 30 #if defined(__APPLE__) 31 #include <machine/endian.h> 32 #define __BYTE_ORDER BYTE_ORDER 33 #define __LITTLE_ENDIAN LITTLE_ENDIAN 34 #elif defined(__sun) 35 #define __LITTLE_ENDIAN 1234 36 #define __BIG_ENDIAN 4321 37 # if defined(_LITTLE_ENDIAN) 38 # define __BYTE_ORDER __LITTLE_ENDIAN 39 # else 40 # define __BYTE_ORDER __BIG_ENDIAN 41 # endif 42 #else 43 #include <endian.h> 44 #endif 45 #include <inttypes.h> 46 #include "vtest.h" 47 48 49 /* Something bad happened. Cannot continue. */ 50 void __attribute__((noreturn)) 51 panic(const char *string) 52 { 53 fprintf(stderr, "*** OOPS: %s\n", string); 54 exit(1); 55 } 56 57 58 /* Issue a complaint because the V-bits of the result of an operation 59 differ from what was expected. */ 60 void 61 complain(const irop_t *op, const test_data_t *data, vbits_t expected) 62 { 63 fprintf(stderr, "*** Incorrect result for operator %s\n", op->name); 64 65 int num_operands = get_num_operands(op->op); 66 67 for (unsigned i = 0; i < num_operands; ++i) { 68 fprintf(stderr, " opnd %u: ", i); 69 print_opnd(stderr, &data->opnds[i]); 70 fprintf(stderr, "\n"); 71 } 72 fprintf(stderr, " result: "); 73 print_opnd(stderr, &data->result); 74 fprintf(stderr, "\n"); 75 fprintf(stderr, " expect: vbits = "); 76 print_vbits(stderr, expected); 77 fprintf(stderr, "\n"); 78 } 79 80 81 static void 82 print_value(FILE *fp, value_t val, unsigned num_bits) 83 { 84 switch (num_bits) { 85 case 1: fprintf(fp, "%02x", val.u8); break; 86 case 8: fprintf(fp, "%02x", val.u8); break; 87 case 16: fprintf(fp, "%04x", val.u16); break; 88 case 32: fprintf(fp, "%08x", val.u32); break; 89 case 64: fprintf(fp, "%016"PRIx64, val.u64); break; 90 case 128: 91 if (__BYTE_ORDER == __LITTLE_ENDIAN) { 92 fprintf(fp, "%016"PRIx64, val.u128[1]); 93 fprintf(fp, "%016"PRIx64, val.u128[0]); 94 } else { 95 fprintf(fp, "%016"PRIx64, val.u128[0]); 96 fprintf(fp, "%016"PRIx64, val.u128[1]); 97 } 98 break; 99 case 256: 100 if (__BYTE_ORDER == __LITTLE_ENDIAN) { 101 fprintf(fp, "%016"PRIx64, val.u256[3]); 102 fprintf(fp, "%016"PRIx64, val.u256[2]); 103 fprintf(fp, "%016"PRIx64, val.u256[1]); 104 fprintf(fp, "%016"PRIx64, val.u256[0]); 105 } else { 106 fprintf(fp, "%016"PRIx64, val.u256[0]); 107 fprintf(fp, "%016"PRIx64, val.u256[1]); 108 fprintf(fp, "%016"PRIx64, val.u256[2]); 109 fprintf(fp, "%016"PRIx64, val.u256[3]); 110 } 111 break; 112 default: 113 panic(__func__); 114 } 115 } 116 117 118 void 119 print_opnd(FILE *fp, const opnd_t *opnd) 120 { 121 fprintf(fp, "vbits = "); 122 print_vbits(fp, opnd->vbits); 123 /* Write the value only if it is defined. Otherwise, there will be error 124 messages about it being undefined */ 125 if (equal_vbits(opnd->vbits, defined_vbits(opnd->vbits.num_bits))) { 126 fprintf(fp, " value = "); 127 print_value(fp, opnd->value, opnd->vbits.num_bits); 128 } 129 } 130 131 132 static int 133 is_floating_point_type(IRType type) 134 { 135 switch (type) { 136 case Ity_F32: 137 case Ity_F64: 138 case Ity_F128: 139 case Ity_D32: 140 case Ity_D64: 141 case Ity_D128: 142 return 1; 143 144 default: 145 return 0; 146 } 147 } 148 149 150 int 151 is_floating_point_op_with_rounding_mode(IROp op) 152 { 153 IRType t_dst, t_arg1, t_arg2, t_arg3, t_arg4; 154 155 typeof_primop(op, &t_dst, &t_arg1, &t_arg2, &t_arg3, &t_arg4); 156 157 // A unary operator cannot have a rounding mode 158 if (t_arg2 == Ity_INVALID) return 0; 159 160 if (is_floating_point_type(t_dst) || 161 is_floating_point_type(t_arg1) || 162 is_floating_point_type(t_arg2) || 163 is_floating_point_type(t_arg3) || 164 is_floating_point_type(t_arg4)) { 165 // Rounding mode, if present, is the 1st operand 166 return t_arg1 == Ity_I32; 167 } 168 return 0; 169 } 170 171 172 /* Return the number of operands for which input values can 173 be freely chosen. For floating point ops, the rounding mode 174 is not counted here, as it is restricted. */ 175 int 176 get_num_operands(IROp op) 177 { 178 IRType unused, t1, t2, t3, t4; 179 180 typeof_primop(op, &unused, &t1, &t2, &t3, &t4); 181 182 int num_operands = 4; 183 if (t4 == Ity_INVALID) num_operands = 3; 184 if (t3 == Ity_INVALID) num_operands = 2; 185 if (t2 == Ity_INVALID) num_operands = 1; 186 187 if (is_floating_point_op_with_rounding_mode(op)) 188 -- num_operands; 189 190 return num_operands; 191 } 192 193 194 unsigned 195 sizeof_irtype(IRType ty) 196 { 197 return sizeofIRType(ty); 198 } 199 200 201 void 202 typeof_primop(IROp op, IRType *t_dst, IRType *t_arg1, IRType *t_arg2, 203 IRType *t_arg3, IRType *t_arg4) 204 { 205 return typeOfPrimop(op, t_dst, t_arg1, t_arg2, t_arg3, t_arg4); 206 } 207