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. */ 50void __attribute__((noreturn)) 51panic(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. */ 60void 61complain(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 81static void 82print_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 118void 119print_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 132static int 133is_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 150int 151is_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. */ 175int 176get_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 194unsigned 195sizeof_irtype(IRType ty) 196{ 197 return sizeofIRType(ty); 198} 199 200 201void 202typeof_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