florian | bb913cd | 2012-08-28 16:50:39 +0000 | [diff] [blame] | 1 | /* -*- mode: C; c-basic-offset: 3; -*- */ |
| 2 | |
florian | 5aa9d1e | 2015-09-22 07:21:50 +0000 | [diff] [blame] | 3 | /* |
| 4 | This file is part of MemCheck, a heavyweight Valgrind tool for |
| 5 | detecting memory errors. |
| 6 | |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame^] | 7 | Copyright (C) 2012-2017 Florian Krohm |
florian | 5aa9d1e | 2015-09-22 07:21:50 +0000 | [diff] [blame] | 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 | |
florian | bb913cd | 2012-08-28 16:50:39 +0000 | [diff] [blame] | 27 | #include <stdio.h> // fprintf |
| 28 | #include <stdlib.h> // exit |
| 29 | #include <assert.h> // assert |
florian | 909e0fc | 2012-08-30 15:12:59 +0000 | [diff] [blame] | 30 | #if defined(__APPLE__) |
| 31 | #include <machine/endian.h> |
| 32 | #define __BYTE_ORDER BYTE_ORDER |
| 33 | #define __LITTLE_ENDIAN LITTLE_ENDIAN |
sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 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 |
florian | 909e0fc | 2012-08-30 15:12:59 +0000 | [diff] [blame] | 42 | #else |
florian | bb913cd | 2012-08-28 16:50:39 +0000 | [diff] [blame] | 43 | #include <endian.h> |
florian | 909e0fc | 2012-08-30 15:12:59 +0000 | [diff] [blame] | 44 | #endif |
florian | 504f829 | 2012-08-29 15:21:15 +0000 | [diff] [blame] | 45 | #include <inttypes.h> |
florian | bb913cd | 2012-08-28 16:50:39 +0000 | [diff] [blame] | 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; |
florian | 504f829 | 2012-08-29 15:21:15 +0000 | [diff] [blame] | 89 | case 64: fprintf(fp, "%016"PRIx64, val.u64); break; |
florian | bb913cd | 2012-08-28 16:50:39 +0000 | [diff] [blame] | 90 | case 128: |
| 91 | if (__BYTE_ORDER == __LITTLE_ENDIAN) { |
florian | 504f829 | 2012-08-29 15:21:15 +0000 | [diff] [blame] | 92 | fprintf(fp, "%016"PRIx64, val.u128[1]); |
| 93 | fprintf(fp, "%016"PRIx64, val.u128[0]); |
florian | bb913cd | 2012-08-28 16:50:39 +0000 | [diff] [blame] | 94 | } else { |
florian | 504f829 | 2012-08-29 15:21:15 +0000 | [diff] [blame] | 95 | fprintf(fp, "%016"PRIx64, val.u128[0]); |
| 96 | fprintf(fp, "%016"PRIx64, val.u128[1]); |
florian | bb913cd | 2012-08-28 16:50:39 +0000 | [diff] [blame] | 97 | } |
| 98 | break; |
| 99 | case 256: |
| 100 | if (__BYTE_ORDER == __LITTLE_ENDIAN) { |
florian | 504f829 | 2012-08-29 15:21:15 +0000 | [diff] [blame] | 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]); |
florian | bb913cd | 2012-08-28 16:50:39 +0000 | [diff] [blame] | 105 | } else { |
florian | 504f829 | 2012-08-29 15:21:15 +0000 | [diff] [blame] | 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]); |
florian | bb913cd | 2012-08-28 16:50:39 +0000 | [diff] [blame] | 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 | |
florian | bb913cd | 2012-08-28 16:50:39 +0000 | [diff] [blame] | 194 | unsigned |
| 195 | sizeof_irtype(IRType ty) |
| 196 | { |
florian | 137e3e7 | 2015-10-16 17:29:54 +0000 | [diff] [blame] | 197 | return sizeofIRType(ty); |
florian | bb913cd | 2012-08-28 16:50:39 +0000 | [diff] [blame] | 198 | } |
| 199 | |
| 200 | |
florian | bb913cd | 2012-08-28 16:50:39 +0000 | [diff] [blame] | 201 | void |
| 202 | typeof_primop(IROp op, IRType *t_dst, IRType *t_arg1, IRType *t_arg2, |
| 203 | IRType *t_arg3, IRType *t_arg4) |
| 204 | { |
florian | 137e3e7 | 2015-10-16 17:29:54 +0000 | [diff] [blame] | 205 | return typeOfPrimop(op, t_dst, t_arg1, t_arg2, t_arg3, t_arg4); |
florian | bb913cd | 2012-08-28 16:50:39 +0000 | [diff] [blame] | 206 | } |