blob: 38b28448b7e8348cc9ab05b166bea02952b54f80 [file] [log] [blame]
sewardjc97096c2004-06-30 09:28:04 +00001
2/*---------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00003/*--- begin test_main.c ---*/
sewardjc97096c2004-06-30 09:28:04 +00004/*---------------------------------------------------------------*/
5
sewardj752f9062010-05-03 21:38:49 +00006/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj25e54732012-08-05 15:36:51 +000010 Copyright (C) 2004-2012 OpenWorks LLP
sewardj752f9062010-05-03 21:38:49 +000011 info@open-works.net
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
34*/
35
sewardjc97096c2004-06-30 09:28:04 +000036#include <stdio.h>
37#include <stdlib.h>
sewardjced9fe52004-07-07 11:55:36 +000038#include <assert.h>
sewardj9b1004e2004-10-30 22:25:40 +000039#include <string.h>
sewardjc97096c2004-06-30 09:28:04 +000040
sewardjced9fe52004-07-07 11:55:36 +000041#include "libvex_basictypes.h"
42#include "libvex.h"
sewardjc97096c2004-06-30 09:28:04 +000043
sewardjabe017e2004-10-29 23:42:36 +000044#include "test_main.h"
45
46
sewardjc97096c2004-06-30 09:28:04 +000047/*---------------------------------------------------------------*/
48/*--- Test ---*/
49/*---------------------------------------------------------------*/
50
sewardjce605f92004-07-05 14:39:15 +000051
sewardj2b515872004-07-05 20:50:45 +000052__attribute__ ((noreturn))
sewardj41f43bc2004-07-08 14:23:22 +000053static
sewardjce605f92004-07-05 14:39:15 +000054void failure_exit ( void )
55{
56 fprintf(stdout, "VEX did failure_exit. Bye.\n");
57 exit(1);
58}
59
sewardj41f43bc2004-07-08 14:23:22 +000060static
sewardj58277842005-02-07 03:11:17 +000061void log_bytes ( HChar* bytes, Int nbytes )
sewardjce605f92004-07-05 14:39:15 +000062{
63 fwrite ( bytes, 1, nbytes, stdout );
64}
65
sewardjced9fe52004-07-07 11:55:36 +000066#define N_LINEBUF 10000
sewardjde8c9872005-03-25 13:48:55 +000067static HChar linebuf[N_LINEBUF];
sewardjced9fe52004-07-07 11:55:36 +000068
cerion094d1392005-06-20 13:45:57 +000069#define N_ORIGBUF 10000
sewardj4459baa2004-09-10 20:00:46 +000070#define N_TRANSBUF 5000
sewardjced9fe52004-07-07 11:55:36 +000071
sewardj4459baa2004-09-10 20:00:46 +000072static UChar origbuf[N_ORIGBUF];
73static UChar transbuf[N_TRANSBUF];
sewardjced9fe52004-07-07 11:55:36 +000074
sewardj1f40a0a2004-07-21 12:28:07 +000075static Bool verbose = True;
sewardjced9fe52004-07-07 11:55:36 +000076
sewardj9b1004e2004-10-30 22:25:40 +000077/* Forwards */
sewardj478646f2008-05-01 20:13:04 +000078#if 1 /* UNUSED */
sewardj5f438dd2011-06-16 11:36:23 +000079//static IRSB* ac_instrument ( IRSB*, VexGuestLayout*, IRType );
sewardj478646f2008-05-01 20:13:04 +000080static
81IRSB* mc_instrument ( void* closureV,
82 IRSB* bb_in, VexGuestLayout* layout,
83 VexGuestExtents* vge,
84 IRType gWordTy, IRType hWordTy );
cerionaee45242005-03-17 14:03:36 +000085#endif
sewardj9b1004e2004-10-30 22:25:40 +000086
sewardjbc161a42011-06-07 21:28:38 +000087static Bool chase_into_not_ok ( void* opaque, Addr64 dst ) {
88 return False;
89}
90static UInt needs_self_check ( void* opaque, VexGuestExtents* vge ) {
91 return 0;
92}
sewardj9b1004e2004-10-30 22:25:40 +000093
sewardjced9fe52004-07-07 11:55:36 +000094int main ( int argc, char** argv )
sewardjce605f92004-07-05 14:39:15 +000095{
sewardjced9fe52004-07-07 11:55:36 +000096 FILE* f;
97 Int i;
sewardj4459baa2004-09-10 20:00:46 +000098 UInt u, sum;
sewardjced9fe52004-07-07 11:55:36 +000099 Addr32 orig_addr;
sewardjabe017e2004-10-29 23:42:36 +0000100 Int bb_number, n_bbs_done = 0;
sewardj72c72812005-01-19 11:49:45 +0000101 Int orig_nbytes, trans_used;
sewardjd887b862005-01-17 18:34:34 +0000102 VexTranslateResult tres;
sewardjb5bf2e02004-10-25 13:06:17 +0000103 VexControl vcon;
sewardj72c72812005-01-19 11:49:45 +0000104 VexGuestExtents vge;
sewardj9e6491a2005-07-02 19:24:10 +0000105 VexArchInfo vai_x86, vai_amd64, vai_ppc32;
sewardjdd40fdf2006-12-24 02:20:24 +0000106 VexAbiInfo vbi;
sewardj17c7f952005-12-15 14:02:34 +0000107 VexTranslateArgs vta;
sewardjced9fe52004-07-07 11:55:36 +0000108
109 if (argc != 2) {
sewardjc6f970f2012-04-02 21:54:49 +0000110 fprintf(stderr, "usage: vex file.orig\n");
sewardjced9fe52004-07-07 11:55:36 +0000111 exit(1);
112 }
113 f = fopen(argv[1], "r");
114 if (!f) {
115 fprintf(stderr, "can't open `%s'\n", argv[1]);
116 exit(1);
117 }
118
sewardjb5bf2e02004-10-25 13:06:17 +0000119 /* Run with default params. However, we can't allow bb chasing
120 since that causes the front end to get segfaults when it tries
sewardj5bd4d162004-11-10 13:02:48 +0000121 to read code outside the initial BB we hand it. So when calling
122 LibVEX_Translate, send in a chase-into predicate that always
123 returns False. */
sewardjb5bf2e02004-10-25 13:06:17 +0000124 LibVEX_default_VexControl ( &vcon );
sewardjb4952402004-10-26 13:24:50 +0000125 vcon.iropt_level = 2;
sewardjc279b3f2005-03-16 18:10:45 +0000126 vcon.guest_max_insns = 50;
sewardjb5bf2e02004-10-25 13:06:17 +0000127
sewardjced9fe52004-07-07 11:55:36 +0000128 LibVEX_Init ( &failure_exit, &log_bytes,
sewardj1f40a0a2004-07-21 12:28:07 +0000129 1, /* debug_paranoia */
sewardjabe017e2004-10-29 23:42:36 +0000130 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +0000131 &vcon );
sewardjced9fe52004-07-07 11:55:36 +0000132
sewardjea64e142004-07-22 16:47:21 +0000133
sewardjced9fe52004-07-07 11:55:36 +0000134 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +0000135
sewardj5f438dd2011-06-16 11:36:23 +0000136 __attribute__((unused))
137 char* unused1 = fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +0000138 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +0000139 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +0000140
141 if (n_bbs_done == TEST_N_BBS) break;
142 n_bbs_done++;
143
sewardjced9fe52004-07-07 11:55:36 +0000144 /* first line is: . bb-number bb-addr n-bytes */
145 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
146 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000147 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000148 assert(orig_nbytes >= 1);
149 assert(!feof(f));
sewardj5f438dd2011-06-16 11:36:23 +0000150 __attribute__((unused))
151 char* unused2 = fgets(linebuf, N_LINEBUF,f);
sewardjced9fe52004-07-07 11:55:36 +0000152 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000153
sewardjced9fe52004-07-07 11:55:36 +0000154 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000155 if (verbose)
sewardj07a54cc2005-02-04 21:18:55 +0000156 printf("============ Basic Block %d, Done %d, "
sewardj4459baa2004-09-10 20:00:46 +0000157 "Start %x, nbytes %2d ============",
sewardj07a54cc2005-02-04 21:18:55 +0000158 bb_number, n_bbs_done-1, orig_addr, orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000159
sewardjced9fe52004-07-07 11:55:36 +0000160 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
161 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000162 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
163 origbuf[i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000164 }
165
sewardj5117ce12006-01-27 21:20:15 +0000166 /* FIXME: put sensible values into the .hwcaps fields */
sewardj9e6491a2005-07-02 19:24:10 +0000167 LibVEX_default_VexArchInfo(&vai_x86);
sewardjc4356f02007-11-09 21:15:04 +0000168 vai_x86.hwcaps = VEX_HWCAPS_X86_SSE1
169 | VEX_HWCAPS_X86_SSE2 | VEX_HWCAPS_X86_SSE3;
sewardj9e6491a2005-07-02 19:24:10 +0000170
171 LibVEX_default_VexArchInfo(&vai_amd64);
sewardj5117ce12006-01-27 21:20:15 +0000172 vai_amd64.hwcaps = 0;
sewardj9e6491a2005-07-02 19:24:10 +0000173
174 LibVEX_default_VexArchInfo(&vai_ppc32);
sewardj5117ce12006-01-27 21:20:15 +0000175 vai_ppc32.hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000176 vai_ppc32.ppc_cache_line_szB = 128;
sewardj02ef7162005-06-30 12:50:50 +0000177
sewardjdd40fdf2006-12-24 02:20:24 +0000178 LibVEX_default_VexAbiInfo(&vbi);
sewardjc6f970f2012-04-02 21:54:49 +0000179 vbi.guest_stack_redzone_size = 128;
sewardjaca070a2006-10-17 00:28:22 +0000180
sewardj17c7f952005-12-15 14:02:34 +0000181 /* ----- Set up args for LibVEX_Translate ----- */
sewardjc6f970f2012-04-02 21:54:49 +0000182
sewardjc4356f02007-11-09 21:15:04 +0000183#if 0 /* ppc32 -> ppc32 */
sewardj17c7f952005-12-15 14:02:34 +0000184 vta.arch_guest = VexArchPPC32;
185 vta.archinfo_guest = vai_ppc32;
186 vta.arch_host = VexArchPPC32;
187 vta.archinfo_host = vai_ppc32;
sewardj07a54cc2005-02-04 21:18:55 +0000188#endif
sewardjc279b3f2005-03-16 18:10:45 +0000189#if 0 /* amd64 -> amd64 */
sewardj17c7f952005-12-15 14:02:34 +0000190 vta.arch_guest = VexArchAMD64;
191 vta.archinfo_guest = vai_amd64;
192 vta.arch_host = VexArchAMD64;
193 vta.archinfo_host = vai_amd64;
sewardj07a54cc2005-02-04 21:18:55 +0000194#endif
sewardjc4356f02007-11-09 21:15:04 +0000195#if 1 /* x86 -> x86 */
sewardj17c7f952005-12-15 14:02:34 +0000196 vta.arch_guest = VexArchX86;
197 vta.archinfo_guest = vai_x86;
198 vta.arch_host = VexArchX86;
199 vta.archinfo_host = vai_x86;
sewardjc279b3f2005-03-16 18:10:45 +0000200#endif
sewardjc6f970f2012-04-02 21:54:49 +0000201
sewardjdd40fdf2006-12-24 02:20:24 +0000202 vta.abiinfo_both = vbi;
sewardj17c7f952005-12-15 14:02:34 +0000203 vta.guest_bytes = origbuf;
204 vta.guest_bytes_addr = (Addr64)orig_addr;
sewardjc716aea2006-01-17 01:48:46 +0000205 vta.callback_opaque = NULL;
sewardj17c7f952005-12-15 14:02:34 +0000206 vta.chase_into_ok = chase_into_not_ok;
207 vta.guest_extents = &vge;
208 vta.host_bytes = transbuf;
209 vta.host_bytes_size = N_TRANSBUF;
210 vta.host_bytes_used = &trans_used;
sewardjc6f970f2012-04-02 21:54:49 +0000211
212#if 1 /* no instrumentation */
sewardj17c7f952005-12-15 14:02:34 +0000213 vta.instrument1 = NULL;
214 vta.instrument2 = NULL;
sewardj9e7448b2004-11-18 13:44:15 +0000215#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000216#if 0 /* addrcheck */
sewardj17c7f952005-12-15 14:02:34 +0000217 vta.instrument1 = ac_instrument;
218 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000219#endif
sewardjc6f970f2012-04-02 21:54:49 +0000220#if 0 /* memcheck */
sewardj17c7f952005-12-15 14:02:34 +0000221 vta.instrument1 = mc_instrument;
222 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000223#endif
sewardjbc161a42011-06-07 21:28:38 +0000224 vta.needs_self_check = needs_self_check;
sewardjc716aea2006-01-17 01:48:46 +0000225 vta.preamble_function = NULL;
sewardj17c7f952005-12-15 14:02:34 +0000226 vta.traceflags = TEST_FLAGS;
sewardjc6f970f2012-04-02 21:54:49 +0000227 vta.addProfInc = False;
228
229 vta.disp_cp_chain_me_to_slowEP = (void*)0x12345678;
230 vta.disp_cp_chain_me_to_fastEP = (void*)0x12345679;
231 vta.disp_cp_xindir = (void*)0x1234567A;
232 vta.disp_cp_xassisted = (void*)0x1234567B;
sewardj17c7f952005-12-15 14:02:34 +0000233
sewardjc4356f02007-11-09 21:15:04 +0000234 vta.finaltidy = NULL;
235
sewardj17c7f952005-12-15 14:02:34 +0000236 for (i = 0; i < TEST_N_ITERS; i++)
237 tres = LibVEX_Translate ( &vta );
sewardjabe017e2004-10-29 23:42:36 +0000238
sewardjbc161a42011-06-07 21:28:38 +0000239 if (tres.status != VexTransOK)
240 printf("\ntres = %d\n", (Int)tres.status);
241 assert(tres.status == VexTransOK);
242 assert(tres.n_sc_extents == 0);
sewardj72c72812005-01-19 11:49:45 +0000243 assert(vge.n_used == 1);
244 assert((UInt)(vge.len[0]) == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000245
sewardj4459baa2004-09-10 20:00:46 +0000246 sum = 0;
247 for (i = 0; i < trans_used; i++)
248 sum += (UInt)transbuf[i];
sewardjde8c9872005-03-25 13:48:55 +0000249 printf ( " %6.2f ... %u\n",
250 (double)trans_used / (double)vge.len[0], sum );
sewardjced9fe52004-07-07 11:55:36 +0000251 }
252
253 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000254 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000255 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000256
sewardjce605f92004-07-05 14:39:15 +0000257 return 0;
258}
sewardj9b1004e2004-10-30 22:25:40 +0000259
260//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000261//////////////////////////////////////////////////////////////////////
262//////////////////////////////////////////////////////////////////////
263//////////////////////////////////////////////////////////////////////
264//////////////////////////////////////////////////////////////////////
265//////////////////////////////////////////////////////////////////////
266//////////////////////////////////////////////////////////////////////
267//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000268
sewardj1ea1b612005-03-26 13:02:20 +0000269#if 0 /* UNUSED */
270
sewardj9b1004e2004-10-30 22:25:40 +0000271static
sewardjde8a5ae2004-11-06 14:20:54 +0000272__attribute((noreturn))
sewardjde8c9872005-03-25 13:48:55 +0000273void panic ( HChar* s )
sewardj9b1004e2004-10-30 22:25:40 +0000274{
275 printf("\npanic: %s\n", s);
276 failure_exit();
277}
278
279static
sewardjf6c8ebf2007-02-06 01:52:52 +0000280IRSB* ac_instrument (IRSB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000281{
282/* Use this rather than eg. -1 because it's a UInt. */
283#define INVALID_DATA_SIZE 999999
284
285 Int i;
286 Int sz;
287 IRCallee* helper;
288 IRStmt* st;
289 IRExpr* data;
290 IRExpr* addr;
291 Bool needSz;
292
293 /* Set up BB */
sewardjf6c8ebf2007-02-06 01:52:52 +0000294 IRSB* bb = emptyIRSB();
sewardj9b1004e2004-10-30 22:25:40 +0000295 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
296 bb->next = dopyIRExpr(bb_in->next);
297 bb->jumpkind = bb_in->jumpkind;
298
299 /* No loads to consider in ->next. */
sewardj496a58d2005-03-20 18:44:44 +0000300 assert(isIRAtom(bb_in->next));
sewardj9b1004e2004-10-30 22:25:40 +0000301
302 for (i = 0; i < bb_in->stmts_used; i++) {
303 st = bb_in->stmts[i];
304 if (!st) continue;
305
306 switch (st->tag) {
307
308 case Ist_Tmp:
309 data = st->Ist.Tmp.data;
310 if (data->tag == Iex_LDle) {
311 addr = data->Iex.LDle.addr;
312 sz = sizeofIRType(data->Iex.LDle.ty);
313 needSz = False;
314 switch (sz) {
315 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000316 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000317 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000318 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000319 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000320 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000321 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000322 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000323 needSz = True; break;
324 }
325 if (needSz) {
sewardjf6c8ebf2007-02-06 01:52:52 +0000326 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000327 bb,
328 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000329 unsafeIRDirty_0_N( helper->regparms,
330 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000331 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
332 ));
333 } else {
sewardjf6c8ebf2007-02-06 01:52:52 +0000334 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000335 bb,
336 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000337 unsafeIRDirty_0_N( helper->regparms,
338 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000339 mkIRExprVec_1(addr) )
340 ));
341 }
342 }
343 break;
344
345 case Ist_STle:
346 data = st->Ist.STle.data;
347 addr = st->Ist.STle.addr;
sewardj496a58d2005-03-20 18:44:44 +0000348 assert(isIRAtom(data));
349 assert(isIRAtom(addr));
sewardj9b1004e2004-10-30 22:25:40 +0000350 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
351 needSz = False;
352 switch (sz) {
353 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000354 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000355 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000356 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000357 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000358 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000359 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000360 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000361 needSz = True; break;
362 }
363 if (needSz) {
sewardjf6c8ebf2007-02-06 01:52:52 +0000364 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000365 bb,
366 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000367 unsafeIRDirty_0_N( helper->regparms,
368 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000369 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
370 ));
371 } else {
sewardjf6c8ebf2007-02-06 01:52:52 +0000372 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000373 bb,
374 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000375 unsafeIRDirty_0_N( helper->regparms,
376 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000377 mkIRExprVec_1(addr) )
378 ));
379 }
380 break;
381
382 case Ist_Put:
sewardj496a58d2005-03-20 18:44:44 +0000383 assert(isIRAtom(st->Ist.Put.data));
sewardj9b1004e2004-10-30 22:25:40 +0000384 break;
385
386 case Ist_PutI:
sewardj496a58d2005-03-20 18:44:44 +0000387 assert(isIRAtom(st->Ist.PutI.ix));
388 assert(isIRAtom(st->Ist.PutI.data));
sewardj9b1004e2004-10-30 22:25:40 +0000389 break;
390
391 case Ist_Exit:
sewardj496a58d2005-03-20 18:44:44 +0000392 assert(isIRAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000393 break;
394
395 case Ist_Dirty:
396 /* If the call doesn't interact with memory, we ain't
397 interested. */
398 if (st->Ist.Dirty.details->mFx == Ifx_None)
399 break;
400 goto unhandled;
401
402 default:
403 unhandled:
404 printf("\n");
405 ppIRStmt(st);
406 printf("\n");
407 panic("addrcheck: unhandled IRStmt");
408 }
409
sewardjf6c8ebf2007-02-06 01:52:52 +0000410 addStmtToIRSB( bb, dopyIRStmt(st));
sewardj9b1004e2004-10-30 22:25:40 +0000411 }
412
413 return bb;
414}
cerionaee45242005-03-17 14:03:36 +0000415#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +0000416
417//////////////////////////////////////////////////////////////////////
418//////////////////////////////////////////////////////////////////////
419//////////////////////////////////////////////////////////////////////
420//////////////////////////////////////////////////////////////////////
421//////////////////////////////////////////////////////////////////////
422//////////////////////////////////////////////////////////////////////
423//////////////////////////////////////////////////////////////////////
424//////////////////////////////////////////////////////////////////////
425
sewardj478646f2008-05-01 20:13:04 +0000426#if 1 /* UNUSED */
427
428static
429__attribute((noreturn))
430void panic ( HChar* s )
431{
432 printf("\npanic: %s\n", s);
433 failure_exit();
434}
sewardj1ea1b612005-03-26 13:02:20 +0000435
sewardj69f9e3e2004-12-30 02:05:34 +0000436#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000437#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000438#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000439#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000440#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000441
cerionaee45242005-03-17 14:03:36 +0000442
sewardjde8c9872005-03-25 13:48:55 +0000443static void MC_helperc_complain_undef ( void );
444static void MC_helperc_LOADV8 ( void );
445static void MC_helperc_LOADV4 ( void );
446static void MC_helperc_LOADV2 ( void );
447static void MC_helperc_LOADV1 ( void );
sewardj1ea1b612005-03-26 13:02:20 +0000448static void MC_helperc_STOREV8( void );
449static void MC_helperc_STOREV4( void );
450static void MC_helperc_STOREV2( void );
451static void MC_helperc_STOREV1( void );
sewardjde8c9872005-03-25 13:48:55 +0000452static void MC_helperc_value_check0_fail( void );
453static void MC_helperc_value_check1_fail( void );
454static void MC_helperc_value_check4_fail( void );
455
456static void MC_helperc_complain_undef ( void ) { }
457static void MC_helperc_LOADV8 ( void ) { }
458static void MC_helperc_LOADV4 ( void ) { }
459static void MC_helperc_LOADV2 ( void ) { }
460static void MC_helperc_LOADV1 ( void ) { }
sewardj1ea1b612005-03-26 13:02:20 +0000461static void MC_helperc_STOREV8( void ) { }
462static void MC_helperc_STOREV4( void ) { }
463static void MC_helperc_STOREV2( void ) { }
464static void MC_helperc_STOREV1( void ) { }
sewardjde8c9872005-03-25 13:48:55 +0000465static void MC_helperc_value_check0_fail( void ) { }
466static void MC_helperc_value_check1_fail( void ) { }
467static void MC_helperc_value_check4_fail( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000468
469
sewardj3598ef92004-11-11 02:13:30 +0000470/*--------------------------------------------------------------------*/
471/*--- Instrument IR to perform memory checking operations. ---*/
472/*--- mc_translate.c ---*/
473/*--------------------------------------------------------------------*/
474
475/*
476 This file is part of MemCheck, a heavyweight Valgrind tool for
477 detecting memory errors.
478
sewardj25e54732012-08-05 15:36:51 +0000479 Copyright (C) 2000-2012 Julian Seward
sewardj3598ef92004-11-11 02:13:30 +0000480 jseward@acm.org
481
482 This program is free software; you can redistribute it and/or
483 modify it under the terms of the GNU General Public License as
484 published by the Free Software Foundation; either version 2 of the
485 License, or (at your option) any later version.
486
487 This program is distributed in the hope that it will be useful, but
488 WITHOUT ANY WARRANTY; without even the implied warranty of
489 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
490 General Public License for more details.
491
492 You should have received a copy of the GNU General Public License
493 along with this program; if not, write to the Free Software
494 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
495 02111-1307, USA.
496
497 The GNU General Public License is contained in the file COPYING.
498*/
499
500//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000501
502
503/*------------------------------------------------------------*/
504/*--- Forward decls ---*/
505/*------------------------------------------------------------*/
506
507struct _MCEnv;
508
509static IRType shadowType ( IRType ty );
510static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
511
512
513/*------------------------------------------------------------*/
514/*--- Memcheck running state, and tmp management. ---*/
515/*------------------------------------------------------------*/
516
517/* Carries around state during memcheck instrumentation. */
518typedef
519 struct _MCEnv {
520 /* MODIFIED: the bb being constructed. IRStmts are added. */
sewardjf6c8ebf2007-02-06 01:52:52 +0000521 IRSB* bb;
sewardjde8a5ae2004-11-06 14:20:54 +0000522
523 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
524 original temps to their current their current shadow temp.
525 Initially all entries are IRTemp_INVALID. Entries are added
526 lazily since many original temps are not used due to
527 optimisation prior to instrumentation. Note that floating
528 point original tmps are shadowed by integer tmps of the same
529 size, and Bit-typed original tmps are shadowed by the type
530 Ity_I8. See comment below. */
531 IRTemp* tmpMap;
532 Int n_originalTmps; /* for range checking */
533
534 /* READONLY: the guest layout. This indicates which parts of
535 the guest state should be regarded as 'always defined'. */
536 VexGuestLayout* layout;
537 /* READONLY: the host word type. Needed for constructing
538 arguments of type 'HWord' to be passed to helper functions.
539 Ity_I32 or Ity_I64 only. */
540 IRType hWordTy;
541 }
542 MCEnv;
543
544/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
545 demand), as they are encountered. This is for two reasons.
546
547 (1) (less important reason): Many original tmps are unused due to
548 initial IR optimisation, and we do not want to spaces in tables
549 tracking them.
550
551 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
552 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000553 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000554 It is necessary to support making multiple assignments to a shadow
555 -- specifically, after testing a shadow for definedness, it needs
556 to be made defined. But IR's SSA property disallows this.
557
558 (2) (more important reason): Therefore, when a shadow needs to get
559 a new value, a new temporary is created, the value is assigned to
560 that, and the tmpMap is updated to reflect the new binding.
561
562 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000563 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000564 there's a read-before-write error in the original tmps. The IR
565 sanity checker should catch all such anomalies, however.
566*/
567
568/* Find the tmp currently shadowing the given original tmp. If none
569 so far exists, allocate one. */
570static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
571{
sewardj69f9e3e2004-12-30 02:05:34 +0000572 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000573 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000574 mce->tmpMap[orig]
575 = newIRTemp(mce->bb->tyenv,
576 shadowType(mce->bb->tyenv->types[orig]));
577 }
578 return mce->tmpMap[orig];
579}
580
581/* Allocate a new shadow for the given original tmp. This means any
582 previous shadow is abandoned. This is needed because it is
583 necessary to give a new value to a shadow once it has been tested
584 for undefinedness, but unfortunately IR's SSA property disallows
585 this. Instead we must abandon the old shadow, allocate a new one
586 and use that instead. */
587static void newShadowTmp ( MCEnv* mce, IRTemp orig )
588{
sewardj69f9e3e2004-12-30 02:05:34 +0000589 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000590 mce->tmpMap[orig]
591 = newIRTemp(mce->bb->tyenv,
592 shadowType(mce->bb->tyenv->types[orig]));
593}
594
595
596/*------------------------------------------------------------*/
597/*--- IRAtoms -- a subset of IRExprs ---*/
598/*------------------------------------------------------------*/
599
600/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj496a58d2005-03-20 18:44:44 +0000601 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardjde8a5ae2004-11-06 14:20:54 +0000602 input, most of this code deals in atoms. Usefully, a value atom
603 always has a V-value which is also an atom: constants are shadowed
604 by constants, and temps are shadowed by the corresponding shadow
605 temporary. */
606
607typedef IRExpr IRAtom;
608
609/* (used for sanity checks only): is this an atom which looks
610 like it's from original code? */
611static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
612{
613 if (a1->tag == Iex_Const)
614 return True;
sewardj478646f2008-05-01 20:13:04 +0000615 if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < mce->n_originalTmps)
sewardjde8a5ae2004-11-06 14:20:54 +0000616 return True;
617 return False;
618}
619
620/* (used for sanity checks only): is this an atom which looks
621 like it's from shadow code? */
622static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
623{
624 if (a1->tag == Iex_Const)
625 return True;
sewardj478646f2008-05-01 20:13:04 +0000626 if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= mce->n_originalTmps)
sewardjde8a5ae2004-11-06 14:20:54 +0000627 return True;
628 return False;
629}
630
631/* (used for sanity checks only): check that both args are atoms and
632 are identically-kinded. */
633static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
634{
sewardj478646f2008-05-01 20:13:04 +0000635 if (a1->tag == Iex_RdTmp && a1->tag == Iex_RdTmp)
sewardjde8a5ae2004-11-06 14:20:54 +0000636 return True;
637 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
638 return True;
639 return False;
640}
641
642
643/*------------------------------------------------------------*/
644/*--- Type management ---*/
645/*------------------------------------------------------------*/
646
647/* Shadow state is always accessed using integer types. This returns
648 an integer type with the same size (as per sizeofIRType) as the
649 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000650 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000651
652static IRType shadowType ( IRType ty )
653{
654 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000655 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000656 case Ity_I8:
657 case Ity_I16:
658 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000659 case Ity_I64: return ty;
660 case Ity_F32: return Ity_I32;
661 case Ity_F64: return Ity_I64;
662 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000663 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000664 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000665 }
666}
667
668/* Produce a 'defined' value of the given shadow type. Should only be
669 supplied shadow types (Bit/I8/I16/I32/UI64). */
670static IRExpr* definedOfType ( IRType ty ) {
671 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000672 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
673 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
674 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
675 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
676 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
677 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
678 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000679 }
680}
681
682
683/*------------------------------------------------------------*/
684/*--- Constructing IR fragments ---*/
685/*------------------------------------------------------------*/
686
687/* assign value to tmp */
688#define assign(_bb,_tmp,_expr) \
sewardj478646f2008-05-01 20:13:04 +0000689 addStmtToIRSB((_bb), IRStmt_WrTmp((_tmp),(_expr)))
sewardjde8a5ae2004-11-06 14:20:54 +0000690
691/* add stmt to a bb */
692#define stmt(_bb,_stmt) \
sewardjf6c8ebf2007-02-06 01:52:52 +0000693 addStmtToIRSB((_bb), (_stmt))
sewardjde8a5ae2004-11-06 14:20:54 +0000694
695/* build various kinds of expressions */
696#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
697#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
698#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
699#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
700#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
701#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000702#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardj478646f2008-05-01 20:13:04 +0000703#define mkexpr(_tmp) IRExpr_RdTmp((_tmp))
sewardjde8a5ae2004-11-06 14:20:54 +0000704
705/* bind the given expression to a new temporary, and return the
706 temporary. This effectively converts an arbitrary expression into
707 an atom. */
708static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
709 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
710 assign(mce->bb, t, e);
711 return mkexpr(t);
712}
713
714
715/*------------------------------------------------------------*/
716/*--- Constructing definedness primitive ops ---*/
717/*------------------------------------------------------------*/
718
719/* --------- Defined-if-either-defined --------- */
720
721static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000722 tl_assert(isShadowAtom(mce,a1));
723 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000724 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
725}
726
727static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000728 tl_assert(isShadowAtom(mce,a1));
729 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000730 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
731}
732
733static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000734 tl_assert(isShadowAtom(mce,a1));
735 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000736 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
737}
738
sewardj69f9e3e2004-12-30 02:05:34 +0000739static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
740 tl_assert(isShadowAtom(mce,a1));
741 tl_assert(isShadowAtom(mce,a2));
742 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
743}
744
sewardjf0c1c582005-02-07 23:47:38 +0000745static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000746 tl_assert(isShadowAtom(mce,a1));
747 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000748 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000749}
750
sewardjde8a5ae2004-11-06 14:20:54 +0000751/* --------- Undefined-if-either-undefined --------- */
752
753static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000754 tl_assert(isShadowAtom(mce,a1));
755 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000756 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
757}
758
759static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000760 tl_assert(isShadowAtom(mce,a1));
761 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000762 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
763}
764
765static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000766 tl_assert(isShadowAtom(mce,a1));
767 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000768 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
769}
770
771static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000772 tl_assert(isShadowAtom(mce,a1));
773 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000774 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
775}
776
sewardjf0c1c582005-02-07 23:47:38 +0000777static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000778 tl_assert(isShadowAtom(mce,a1));
779 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000780 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000781}
782
783static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000784 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000785 case Ity_I8: return mkUifU8(mce, a1, a2);
786 case Ity_I16: return mkUifU16(mce, a1, a2);
787 case Ity_I32: return mkUifU32(mce, a1, a2);
788 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardjf0c1c582005-02-07 23:47:38 +0000789 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000790 default:
791 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000792 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000793 }
794}
795
796/* --------- The Left-family of operations. --------- */
797
798static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000799 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000800 /* It's safe to duplicate a1 since it's only an atom */
801 return assignNew(mce, Ity_I8,
802 binop(Iop_Or8, a1,
803 assignNew(mce, Ity_I8,
804 /* unop(Iop_Neg8, a1)))); */
805 binop(Iop_Sub8, mkU8(0), a1) )));
806}
807
808static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000809 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000810 /* It's safe to duplicate a1 since it's only an atom */
811 return assignNew(mce, Ity_I16,
812 binop(Iop_Or16, a1,
813 assignNew(mce, Ity_I16,
814 /* unop(Iop_Neg16, a1)))); */
815 binop(Iop_Sub16, mkU16(0), a1) )));
816}
817
818static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000819 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000820 /* It's safe to duplicate a1 since it's only an atom */
821 return assignNew(mce, Ity_I32,
822 binop(Iop_Or32, a1,
823 assignNew(mce, Ity_I32,
824 /* unop(Iop_Neg32, a1)))); */
825 binop(Iop_Sub32, mkU32(0), a1) )));
826}
827
828/* --------- 'Improvement' functions for AND/OR. --------- */
829
830/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
831 defined (0); all other -> undefined (1).
832*/
833static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
834{
sewardj69f9e3e2004-12-30 02:05:34 +0000835 tl_assert(isOriginalAtom(mce, data));
836 tl_assert(isShadowAtom(mce, vbits));
837 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000838 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
839}
840
sewardj3598ef92004-11-11 02:13:30 +0000841static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
842{
sewardj69f9e3e2004-12-30 02:05:34 +0000843 tl_assert(isOriginalAtom(mce, data));
844 tl_assert(isShadowAtom(mce, vbits));
845 tl_assert(sameKindedAtoms(data, vbits));
sewardj3598ef92004-11-11 02:13:30 +0000846 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
847}
848
sewardjde8a5ae2004-11-06 14:20:54 +0000849static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
850{
sewardj69f9e3e2004-12-30 02:05:34 +0000851 tl_assert(isOriginalAtom(mce, data));
852 tl_assert(isShadowAtom(mce, vbits));
853 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000854 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
855}
856
sewardj69f9e3e2004-12-30 02:05:34 +0000857static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
858{
859 tl_assert(isOriginalAtom(mce, data));
860 tl_assert(isShadowAtom(mce, vbits));
861 tl_assert(sameKindedAtoms(data, vbits));
862 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
863}
864
sewardjf0c1c582005-02-07 23:47:38 +0000865static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000866{
867 tl_assert(isOriginalAtom(mce, data));
868 tl_assert(isShadowAtom(mce, vbits));
869 tl_assert(sameKindedAtoms(data, vbits));
sewardjf0c1c582005-02-07 23:47:38 +0000870 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj69f9e3e2004-12-30 02:05:34 +0000871}
872
sewardjde8a5ae2004-11-06 14:20:54 +0000873/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
874 defined (0); all other -> undefined (1).
875*/
876static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
877{
sewardj69f9e3e2004-12-30 02:05:34 +0000878 tl_assert(isOriginalAtom(mce, data));
879 tl_assert(isShadowAtom(mce, vbits));
880 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000881 return assignNew(
882 mce, Ity_I8,
883 binop(Iop_Or8,
884 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
885 vbits) );
886}
887
888static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
889{
sewardj69f9e3e2004-12-30 02:05:34 +0000890 tl_assert(isOriginalAtom(mce, data));
891 tl_assert(isShadowAtom(mce, vbits));
892 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000893 return assignNew(
894 mce, Ity_I16,
895 binop(Iop_Or16,
896 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
897 vbits) );
898}
899
900static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
901{
sewardj69f9e3e2004-12-30 02:05:34 +0000902 tl_assert(isOriginalAtom(mce, data));
903 tl_assert(isShadowAtom(mce, vbits));
904 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000905 return assignNew(
906 mce, Ity_I32,
907 binop(Iop_Or32,
908 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
909 vbits) );
910}
911
sewardj69f9e3e2004-12-30 02:05:34 +0000912static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
913{
914 tl_assert(isOriginalAtom(mce, data));
915 tl_assert(isShadowAtom(mce, vbits));
916 tl_assert(sameKindedAtoms(data, vbits));
917 return assignNew(
918 mce, Ity_I64,
919 binop(Iop_Or64,
920 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
921 vbits) );
922}
923
sewardjf0c1c582005-02-07 23:47:38 +0000924static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000925{
926 tl_assert(isOriginalAtom(mce, data));
927 tl_assert(isShadowAtom(mce, vbits));
928 tl_assert(sameKindedAtoms(data, vbits));
929 return assignNew(
930 mce, Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +0000931 binop(Iop_OrV128,
932 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj69f9e3e2004-12-30 02:05:34 +0000933 vbits) );
934}
935
sewardjde8a5ae2004-11-06 14:20:54 +0000936/* --------- Pessimising casts. --------- */
937
938static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
939{
sewardj8fc93742004-11-22 11:29:33 +0000940 IRType ty;
941 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000942 /* Note, dst_ty is a shadow type, not an original type. */
943 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000944 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000945 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
946 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000947 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000948 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000949 tmp1 = vbits;
950 break;
951 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000952 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000953 break;
954 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000955 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000956 break;
957 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000958 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000959 break;
960 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000961 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000962 break;
963 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000964 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000965 }
sewardj69f9e3e2004-12-30 02:05:34 +0000966 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000967 /* Now widen up to the dst type. */
968 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000969 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000970 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000971 case Ity_I8:
972 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000973 case Ity_I16:
974 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
975 case Ity_I32:
976 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
977 case Ity_I64:
978 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000979 case Ity_V128:
980 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardjf0c1c582005-02-07 23:47:38 +0000981 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000982 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000983 default:
984 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000985 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +0000986 }
987}
988
989
990/*------------------------------------------------------------*/
991/*--- Emit a test and complaint if something is undefined. ---*/
992/*------------------------------------------------------------*/
993
994/* Set the annotations on a dirty helper to indicate that the stack
995 pointer and instruction pointers might be read. This is the
996 behaviour of all 'emit-a-complaint' style functions we might
997 call. */
998
999static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
1000 di->nFxState = 2;
1001 di->fxState[0].fx = Ifx_Read;
1002 di->fxState[0].offset = mce->layout->offset_SP;
1003 di->fxState[0].size = mce->layout->sizeof_SP;
1004 di->fxState[1].fx = Ifx_Read;
1005 di->fxState[1].offset = mce->layout->offset_IP;
1006 di->fxState[1].size = mce->layout->sizeof_IP;
1007}
1008
1009
1010/* Check the supplied **original** atom for undefinedness, and emit a
1011 complaint if so. Once that happens, mark it as defined. This is
1012 possible because the atom is either a tmp or literal. If it's a
1013 tmp, it will be shadowed by a tmp, and so we can set the shadow to
1014 be defined. In fact as mentioned above, we will have to allocate a
1015 new tmp to carry the new 'defined' shadow value, and update the
1016 original->tmp mapping accordingly; we cannot simply assign a new
1017 value to an existing shadow tmp as this breaks SSAness -- resulting
1018 in the post-instrumentation sanity checker spluttering in disapproval.
1019*/
1020static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
1021{
sewardj8fc93742004-11-22 11:29:33 +00001022 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001023 IRType ty;
1024 Int sz;
sewardj8fc93742004-11-22 11:29:33 +00001025 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +00001026 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +00001027
sewardjde8a5ae2004-11-06 14:20:54 +00001028 /* Since the original expression is atomic, there's no duplicated
1029 work generated by making multiple V-expressions for it. So we
1030 don't really care about the possibility that someone else may
1031 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +00001032 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +00001033 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001034 tl_assert(isShadowAtom(mce, vatom));
1035 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001036
sewardj8fc93742004-11-22 11:29:33 +00001037 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +00001038
1039 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +00001040 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +00001041
sewardj8fc93742004-11-22 11:29:33 +00001042 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +00001043 /* cond will be 0 if all defined, and 1 if any not defined. */
1044
sewardj3598ef92004-11-11 02:13:30 +00001045 switch (sz) {
1046 case 0:
1047 di = unsafeIRDirty_0_N( 0/*regparms*/,
1048 "MC_(helperc_value_check0_fail)",
1049 &MC_(helperc_value_check0_fail),
1050 mkIRExprVec_0()
1051 );
1052 break;
1053 case 1:
1054 di = unsafeIRDirty_0_N( 0/*regparms*/,
1055 "MC_(helperc_value_check1_fail)",
1056 &MC_(helperc_value_check1_fail),
1057 mkIRExprVec_0()
1058 );
1059 break;
1060 case 4:
1061 di = unsafeIRDirty_0_N( 0/*regparms*/,
1062 "MC_(helperc_value_check4_fail)",
1063 &MC_(helperc_value_check4_fail),
1064 mkIRExprVec_0()
1065 );
1066 break;
1067 default:
1068 di = unsafeIRDirty_0_N( 1/*regparms*/,
1069 "MC_(helperc_complain_undef)",
1070 &MC_(helperc_complain_undef),
1071 mkIRExprVec_1( mkIRExpr_HWord( sz ))
1072 );
1073 break;
1074 }
sewardjde8a5ae2004-11-06 14:20:54 +00001075 di->guard = cond;
1076 setHelperAnns( mce, di );
1077 stmt( mce->bb, IRStmt_Dirty(di));
1078
1079 /* Set the shadow tmp to be defined. First, update the
1080 orig->shadow tmp mapping to reflect the fact that this shadow is
1081 getting a new value. */
sewardj496a58d2005-03-20 18:44:44 +00001082 tl_assert(isIRAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001083 /* sameKindedAtoms ... */
sewardj478646f2008-05-01 20:13:04 +00001084 if (vatom->tag == Iex_RdTmp) {
1085 tl_assert(atom->tag == Iex_RdTmp);
1086 newShadowTmp(mce, atom->Iex.RdTmp.tmp);
1087 assign(mce->bb, findShadowTmp(mce, atom->Iex.RdTmp.tmp),
sewardjde8a5ae2004-11-06 14:20:54 +00001088 definedOfType(ty));
1089 }
1090}
1091
1092
1093/*------------------------------------------------------------*/
1094/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
1095/*------------------------------------------------------------*/
1096
1097/* Examine the always-defined sections declared in layout to see if
1098 the (offset,size) section is within one. Note, is is an error to
1099 partially fall into such a region: (offset,size) should either be
1100 completely in such a region or completely not-in such a region.
1101*/
1102static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1103{
1104 Int minoffD, maxoffD, i;
1105 Int minoff = offset;
1106 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001107 tl_assert((minoff & ~0xFFFF) == 0);
1108 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001109
1110 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1111 minoffD = mce->layout->alwaysDefd[i].offset;
1112 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001113 tl_assert((minoffD & ~0xFFFF) == 0);
1114 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001115
1116 if (maxoff < minoffD || maxoffD < minoff)
1117 continue; /* no overlap */
1118 if (minoff >= minoffD && maxoff <= maxoffD)
1119 return True; /* completely contained in an always-defd section */
1120
sewardj69f9e3e2004-12-30 02:05:34 +00001121 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001122 }
1123 return False; /* could not find any containing section */
1124}
1125
1126
1127/* Generate into bb suitable actions to shadow this Put. If the state
1128 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001129 supplied V bits to the shadow state. We can pass in either an
1130 original atom or a V-atom, but not both. In the former case the
1131 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001132*/
1133static
sewardj3598ef92004-11-11 02:13:30 +00001134void do_shadow_PUT ( MCEnv* mce, Int offset,
1135 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001136{
sewardj8fc93742004-11-22 11:29:33 +00001137 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001138 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001139 tl_assert(!vatom);
1140 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001141 vatom = expr2vbits( mce, atom );
1142 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001143 tl_assert(vatom);
1144 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001145 }
1146
sewardj8fc93742004-11-22 11:29:33 +00001147 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001148 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001149 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1150 /* later: no ... */
1151 /* emit code to emit a complaint if any of the vbits are 1. */
1152 /* complainIfUndefined(mce, atom); */
1153 } else {
1154 /* Do a plain shadow Put. */
1155 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1156 }
1157}
1158
1159
1160/* Return an expression which contains the V bits corresponding to the
1161 given GETI (passed in in pieces).
1162*/
1163static
1164void do_shadow_PUTI ( MCEnv* mce,
sewardj478646f2008-05-01 20:13:04 +00001165 IRRegArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
sewardjde8a5ae2004-11-06 14:20:54 +00001166{
sewardj8fc93742004-11-22 11:29:33 +00001167 IRAtom* vatom;
1168 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001169 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001170
sewardj69f9e3e2004-12-30 02:05:34 +00001171 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001172 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001173 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001174 ty = descr->elemTy;
1175 tyS = shadowType(ty);
1176 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001177 tl_assert(ty != Ity_I1);
1178 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001179 complainIfUndefined(mce,ix);
1180 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1181 /* later: no ... */
1182 /* emit code to emit a complaint if any of the vbits are 1. */
1183 /* complainIfUndefined(mce, atom); */
1184 } else {
1185 /* Do a cloned version of the Put that refers to the shadow
1186 area. */
sewardj478646f2008-05-01 20:13:04 +00001187 IRRegArray* new_descr
1188 = mkIRRegArray( descr->base + mce->layout->total_sizeB,
sewardjde8a5ae2004-11-06 14:20:54 +00001189 tyS, descr->nElems);
florian4180af32012-12-24 00:25:34 +00001190 stmt( mce->bb, IRStmt_PutI( mkIRPutI( new_descr, ix, bias, vatom ) ));
sewardjde8a5ae2004-11-06 14:20:54 +00001191 }
1192}
1193
1194
1195/* Return an expression which contains the V bits corresponding to the
1196 given GET (passed in in pieces).
1197*/
1198static
1199IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1200{
1201 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001202 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001203 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1204 /* Always defined, return all zeroes of the relevant type */
1205 return definedOfType(tyS);
1206 } else {
1207 /* return a cloned version of the Get that refers to the shadow
1208 area. */
1209 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1210 }
1211}
1212
1213
1214/* Return an expression which contains the V bits corresponding to the
1215 given GETI (passed in in pieces).
1216*/
1217static
sewardj478646f2008-05-01 20:13:04 +00001218IRExpr* shadow_GETI ( MCEnv* mce, IRRegArray* descr, IRAtom* ix, Int bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001219{
1220 IRType ty = descr->elemTy;
1221 IRType tyS = shadowType(ty);
1222 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001223 tl_assert(ty != Ity_I1);
1224 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001225 complainIfUndefined(mce,ix);
1226 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1227 /* Always defined, return all zeroes of the relevant type */
1228 return definedOfType(tyS);
1229 } else {
1230 /* return a cloned version of the Get that refers to the shadow
1231 area. */
sewardj478646f2008-05-01 20:13:04 +00001232 IRRegArray* new_descr
1233 = mkIRRegArray( descr->base + mce->layout->total_sizeB,
sewardjde8a5ae2004-11-06 14:20:54 +00001234 tyS, descr->nElems);
1235 return IRExpr_GetI( new_descr, ix, bias );
1236 }
1237}
1238
1239
1240/*------------------------------------------------------------*/
1241/*--- Generating approximations for unknown operations, ---*/
1242/*--- using lazy-propagate semantics ---*/
1243/*------------------------------------------------------------*/
1244
1245/* Lazy propagation of undefinedness from two values, resulting in the
1246 specified shadow type.
1247*/
1248static
1249IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1250{
1251 /* force everything via 32-bit intermediaries. */
1252 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001253 tl_assert(isShadowAtom(mce,va1));
1254 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001255 at = mkPCastTo(mce, Ity_I32, va1);
1256 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1257 at = mkPCastTo(mce, finalVty, at);
1258 return at;
1259}
1260
1261
1262/* Do the lazy propagation game from a null-terminated vector of
1263 atoms. This is presumably the arguments to a helper call, so the
1264 IRCallee info is also supplied in order that we can know which
1265 arguments should be ignored (via the .mcx_mask field).
1266*/
1267static
1268IRAtom* mkLazyN ( MCEnv* mce,
1269 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1270{
1271 Int i;
1272 IRAtom* here;
1273 IRAtom* curr = definedOfType(Ity_I32);
1274 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001275 tl_assert(i < 32);
1276 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001277 /* Only take notice of this arg if the callee's mc-exclusion
1278 mask does not say it is to be excluded. */
1279 if (cee->mcx_mask & (1<<i)) {
1280 /* the arg is to be excluded from definedness checking. Do
1281 nothing. */
1282 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1283 } else {
1284 /* calculate the arg's definedness, and pessimistically merge
1285 it in. */
1286 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1287 curr = mkUifU32(mce, here, curr);
1288 }
1289 }
1290 return mkPCastTo(mce, finalVtype, curr );
1291}
1292
1293
1294/*------------------------------------------------------------*/
1295/*--- Generating expensive sequences for exact carry-chain ---*/
1296/*--- propagation in add/sub and related operations. ---*/
1297/*------------------------------------------------------------*/
1298
1299static
sewardj5f438dd2011-06-16 11:36:23 +00001300__attribute__((unused))
sewardjde8a5ae2004-11-06 14:20:54 +00001301IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1302 IRAtom* aa, IRAtom* bb )
1303{
sewardj69f9e3e2004-12-30 02:05:34 +00001304 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001305 IRType ty;
1306 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001307
sewardj69f9e3e2004-12-30 02:05:34 +00001308 tl_assert(isShadowAtom(mce,qaa));
1309 tl_assert(isShadowAtom(mce,qbb));
1310 tl_assert(isOriginalAtom(mce,aa));
1311 tl_assert(isOriginalAtom(mce,bb));
1312 tl_assert(sameKindedAtoms(qaa,aa));
1313 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001314
sewardj8fc93742004-11-22 11:29:33 +00001315 ty = Ity_I32;
1316 opAND = Iop_And32;
1317 opOR = Iop_Or32;
1318 opXOR = Iop_Xor32;
1319 opNOT = Iop_Not32;
1320 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001321
1322 // a_min = aa & ~qaa
1323 a_min = assignNew(mce,ty,
1324 binop(opAND, aa,
1325 assignNew(mce,ty, unop(opNOT, qaa))));
1326
1327 // b_min = bb & ~qbb
1328 b_min = assignNew(mce,ty,
1329 binop(opAND, bb,
1330 assignNew(mce,ty, unop(opNOT, qbb))));
1331
1332 // a_max = aa | qaa
1333 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1334
1335 // b_max = bb | qbb
1336 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1337
1338 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1339 return
1340 assignNew(mce,ty,
1341 binop( opOR,
1342 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1343 assignNew(mce,ty,
1344 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1345 assignNew(mce,ty, binop(opADD, a_max, b_max))
1346 )
1347 )
1348 )
1349 );
1350}
1351
1352
1353/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001354/*--- Helpers for dealing with vector primops. ---*/
1355/*------------------------------------------------------------*/
1356
1357/* Vector pessimisation -- pessimise within each lane individually. */
1358
1359static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1360{
1361 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1362}
1363
1364static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1365{
1366 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1367}
1368
1369static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1370{
1371 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1372}
1373
1374static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1375{
1376 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1377}
1378
1379
1380/* Here's a simple scheme capable of handling ops derived from SSE1
1381 code and while only generating ops that can be efficiently
1382 implemented in SSE1. */
1383
1384/* All-lanes versions are straightforward:
1385
sewardjf0c1c582005-02-07 23:47:38 +00001386 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj69f9e3e2004-12-30 02:05:34 +00001387
1388 unary32Fx4(x,y) ==> PCast32x4(x#)
1389
1390 Lowest-lane-only versions are more complex:
1391
sewardjf0c1c582005-02-07 23:47:38 +00001392 binary32F0x4(x,y) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001393 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001394 PCast32(V128to32(UifUV128(x#,y#)))
sewardj69f9e3e2004-12-30 02:05:34 +00001395 )
1396
1397 This is perhaps not so obvious. In particular, it's faster to
sewardjf0c1c582005-02-07 23:47:38 +00001398 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj69f9e3e2004-12-30 02:05:34 +00001399 obvious scheme of taking the bottom 32 bits of each operand
1400 and doing a 32-bit UifU. Basically since UifU is fast and
1401 chopping lanes off vector values is slow.
1402
1403 Finally:
1404
sewardjf0c1c582005-02-07 23:47:38 +00001405 unary32F0x4(x) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001406 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001407 PCast32(V128to32(x#))
sewardj69f9e3e2004-12-30 02:05:34 +00001408 )
1409
1410 Where:
1411
1412 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1413 PCast32x4(v#) = CmpNEZ32x4(v#)
1414*/
1415
1416static
1417IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1418{
1419 IRAtom* at;
1420 tl_assert(isShadowAtom(mce, vatomX));
1421 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001422 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001423 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1424 return at;
1425}
1426
1427static
1428IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1429{
1430 IRAtom* at;
1431 tl_assert(isShadowAtom(mce, vatomX));
1432 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1433 return at;
1434}
1435
1436static
1437IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1438{
1439 IRAtom* at;
1440 tl_assert(isShadowAtom(mce, vatomX));
1441 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001442 at = mkUifUV128(mce, vatomX, vatomY);
1443 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001444 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001445 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001446 return at;
1447}
1448
1449static
1450IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1451{
1452 IRAtom* at;
1453 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001454 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001455 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001456 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001457 return at;
1458}
1459
1460/* --- ... and ... 64Fx2 versions of the same ... --- */
1461
1462static
1463IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1464{
1465 IRAtom* at;
1466 tl_assert(isShadowAtom(mce, vatomX));
1467 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001468 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001469 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1470 return at;
1471}
1472
1473static
1474IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1475{
1476 IRAtom* at;
1477 tl_assert(isShadowAtom(mce, vatomX));
1478 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1479 return at;
1480}
1481
1482static
1483IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1484{
1485 IRAtom* at;
1486 tl_assert(isShadowAtom(mce, vatomX));
1487 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001488 at = mkUifUV128(mce, vatomX, vatomY);
1489 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001490 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001491 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001492 return at;
1493}
1494
1495static
1496IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1497{
1498 IRAtom* at;
1499 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001500 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001501 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001502 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001503 return at;
1504}
1505
1506/* --- --- Vector saturated narrowing --- --- */
1507
1508/* This is quite subtle. What to do is simple:
1509
1510 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1511
1512 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1513
1514 Why this is right is not so simple. Consider a lane in the args,
1515 vatom1 or 2, doesn't matter.
1516
1517 After the PCast, that lane is all 0s (defined) or all
1518 1s(undefined).
1519
1520 Both signed and unsigned saturating narrowing of all 0s produces
1521 all 0s, which is what we want.
1522
1523 The all-1s case is more complex. Unsigned narrowing interprets an
1524 all-1s input as the largest unsigned integer, and so produces all
1525 1s as a result since that is the largest unsigned value at the
1526 smaller width.
1527
1528 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1529 to -1, so we still wind up with all 1s at the smaller width.
1530
1531 So: In short, pessimise the args, then apply the original narrowing
1532 op.
1533*/
1534static
sewardjf0c1c582005-02-07 23:47:38 +00001535IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardj69f9e3e2004-12-30 02:05:34 +00001536 IRAtom* vatom1, IRAtom* vatom2)
1537{
1538 IRAtom *at1, *at2, *at3;
1539 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1540 switch (narrow_op) {
sewardj5f438dd2011-06-16 11:36:23 +00001541 case Iop_QNarrowBin32Sto16Sx8: pcast = mkPCast32x4; break;
1542 case Iop_QNarrowBin16Sto8Sx16: pcast = mkPCast16x8; break;
1543 case Iop_QNarrowBin16Sto8Ux16: pcast = mkPCast16x8; break;
sewardjf0c1c582005-02-07 23:47:38 +00001544 default: VG_(tool_panic)("vectorNarrowV128");
sewardj69f9e3e2004-12-30 02:05:34 +00001545 }
1546 tl_assert(isShadowAtom(mce,vatom1));
1547 tl_assert(isShadowAtom(mce,vatom2));
1548 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1549 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1550 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1551 return at3;
1552}
1553
1554
1555/* --- --- Vector integer arithmetic --- --- */
1556
1557/* Simple ... UifU the args and per-lane pessimise the results. */
1558static
1559IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1560{
1561 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001562 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001563 at = mkPCast8x16(mce, at);
1564 return at;
1565}
1566
1567static
1568IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1569{
1570 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001571 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001572 at = mkPCast16x8(mce, at);
1573 return at;
1574}
1575
1576static
1577IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1578{
1579 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001580 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001581 at = mkPCast32x4(mce, at);
1582 return at;
1583}
1584
1585static
1586IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1587{
1588 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001589 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001590 at = mkPCast64x2(mce, at);
1591 return at;
1592}
1593
1594
1595/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001596/*--- Generate shadow values from all kinds of IRExprs. ---*/
1597/*------------------------------------------------------------*/
1598
1599static
1600IRAtom* expr2vbits_Binop ( MCEnv* mce,
1601 IROp op,
1602 IRAtom* atom1, IRAtom* atom2 )
1603{
1604 IRType and_or_ty;
1605 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1606 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1607 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1608
1609 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1610 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1611
sewardj69f9e3e2004-12-30 02:05:34 +00001612 tl_assert(isOriginalAtom(mce,atom1));
1613 tl_assert(isOriginalAtom(mce,atom2));
1614 tl_assert(isShadowAtom(mce,vatom1));
1615 tl_assert(isShadowAtom(mce,vatom2));
1616 tl_assert(sameKindedAtoms(atom1,vatom1));
1617 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001618 switch (op) {
1619
sewardjf0c1c582005-02-07 23:47:38 +00001620 /* V128-bit SIMD (SSE2-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001621
1622 case Iop_ShrN16x8:
1623 case Iop_ShrN32x4:
1624 case Iop_ShrN64x2:
1625 case Iop_SarN16x8:
1626 case Iop_SarN32x4:
1627 case Iop_ShlN16x8:
1628 case Iop_ShlN32x4:
1629 case Iop_ShlN64x2:
1630 /* Same scheme as with all other shifts. */
1631 complainIfUndefined(mce, atom2);
1632 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1633
1634 case Iop_QSub8Ux16:
1635 case Iop_QSub8Sx16:
1636 case Iop_Sub8x16:
1637 case Iop_Min8Ux16:
1638 case Iop_Max8Ux16:
1639 case Iop_CmpGT8Sx16:
1640 case Iop_CmpEQ8x16:
1641 case Iop_Avg8Ux16:
1642 case Iop_QAdd8Ux16:
1643 case Iop_QAdd8Sx16:
1644 case Iop_Add8x16:
1645 return binary8Ix16(mce, vatom1, vatom2);
1646
1647 case Iop_QSub16Ux8:
1648 case Iop_QSub16Sx8:
1649 case Iop_Sub16x8:
1650 case Iop_Mul16x8:
1651 case Iop_MulHi16Sx8:
1652 case Iop_MulHi16Ux8:
1653 case Iop_Min16Sx8:
1654 case Iop_Max16Sx8:
1655 case Iop_CmpGT16Sx8:
1656 case Iop_CmpEQ16x8:
1657 case Iop_Avg16Ux8:
1658 case Iop_QAdd16Ux8:
1659 case Iop_QAdd16Sx8:
1660 case Iop_Add16x8:
1661 return binary16Ix8(mce, vatom1, vatom2);
1662
1663 case Iop_Sub32x4:
sewardj2fdd4162010-08-22 12:59:02 +00001664 case Iop_QSub32Sx4:
1665 case Iop_QSub32Ux4:
sewardj69f9e3e2004-12-30 02:05:34 +00001666 case Iop_CmpGT32Sx4:
1667 case Iop_CmpEQ32x4:
1668 case Iop_Add32x4:
sewardj2fdd4162010-08-22 12:59:02 +00001669 case Iop_QAdd32Ux4:
1670 case Iop_QAdd32Sx4:
sewardj69f9e3e2004-12-30 02:05:34 +00001671 return binary32Ix4(mce, vatom1, vatom2);
1672
1673 case Iop_Sub64x2:
sewardj2fdd4162010-08-22 12:59:02 +00001674 case Iop_QSub64Ux2:
1675 case Iop_QSub64Sx2:
sewardj69f9e3e2004-12-30 02:05:34 +00001676 case Iop_Add64x2:
sewardj2fdd4162010-08-22 12:59:02 +00001677 case Iop_QAdd64Ux2:
1678 case Iop_QAdd64Sx2:
sewardj69f9e3e2004-12-30 02:05:34 +00001679 return binary64Ix2(mce, vatom1, vatom2);
1680
sewardj5f438dd2011-06-16 11:36:23 +00001681 case Iop_QNarrowBin32Sto16Sx8:
1682 case Iop_QNarrowBin16Sto8Sx16:
1683 case Iop_QNarrowBin16Sto8Ux16:
sewardjf0c1c582005-02-07 23:47:38 +00001684 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001685
1686 case Iop_Sub64Fx2:
1687 case Iop_Mul64Fx2:
1688 case Iop_Min64Fx2:
1689 case Iop_Max64Fx2:
1690 case Iop_Div64Fx2:
1691 case Iop_CmpLT64Fx2:
1692 case Iop_CmpLE64Fx2:
1693 case Iop_CmpEQ64Fx2:
1694 case Iop_Add64Fx2:
1695 return binary64Fx2(mce, vatom1, vatom2);
1696
1697 case Iop_Sub64F0x2:
1698 case Iop_Mul64F0x2:
1699 case Iop_Min64F0x2:
1700 case Iop_Max64F0x2:
1701 case Iop_Div64F0x2:
1702 case Iop_CmpLT64F0x2:
1703 case Iop_CmpLE64F0x2:
1704 case Iop_CmpEQ64F0x2:
1705 case Iop_Add64F0x2:
1706 return binary64F0x2(mce, vatom1, vatom2);
1707
sewardjf0c1c582005-02-07 23:47:38 +00001708 /* V128-bit SIMD (SSE1-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001709
1710 case Iop_Sub32Fx4:
1711 case Iop_Mul32Fx4:
1712 case Iop_Min32Fx4:
1713 case Iop_Max32Fx4:
1714 case Iop_Div32Fx4:
1715 case Iop_CmpLT32Fx4:
1716 case Iop_CmpLE32Fx4:
1717 case Iop_CmpEQ32Fx4:
1718 case Iop_Add32Fx4:
1719 return binary32Fx4(mce, vatom1, vatom2);
1720
1721 case Iop_Sub32F0x4:
1722 case Iop_Mul32F0x4:
1723 case Iop_Min32F0x4:
1724 case Iop_Max32F0x4:
1725 case Iop_Div32F0x4:
1726 case Iop_CmpLT32F0x4:
1727 case Iop_CmpLE32F0x4:
1728 case Iop_CmpEQ32F0x4:
1729 case Iop_Add32F0x4:
1730 return binary32F0x4(mce, vatom1, vatom2);
1731
sewardjf0c1c582005-02-07 23:47:38 +00001732 /* V128-bit data-steering */
1733 case Iop_SetV128lo32:
1734 case Iop_SetV128lo64:
1735 case Iop_64HLtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001736 case Iop_InterleaveLO64x2:
1737 case Iop_InterleaveLO32x4:
1738 case Iop_InterleaveLO16x8:
1739 case Iop_InterleaveLO8x16:
1740 case Iop_InterleaveHI64x2:
1741 case Iop_InterleaveHI32x4:
1742 case Iop_InterleaveHI16x8:
1743 case Iop_InterleaveHI8x16:
1744 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1745
1746 /* Scalar floating point */
1747
sewardj478646f2008-05-01 20:13:04 +00001748 // case Iop_RoundF64:
sewardj1e3830f2011-03-14 11:27:26 +00001749 case Iop_F64toI64S:
1750 case Iop_I64StoF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001751 /* First arg is I32 (rounding mode), second is F64 or I64
1752 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001753 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1754
1755 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1756 /* Takes two F64 args. */
sewardj1e3830f2011-03-14 11:27:26 +00001757 case Iop_F64toI32S:
sewardj69f9e3e2004-12-30 02:05:34 +00001758 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001759 /* First arg is I32 (rounding mode), second is F64 (data). */
1760 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1761
sewardj1e3830f2011-03-14 11:27:26 +00001762 case Iop_F64toI16S:
sewardjde8a5ae2004-11-06 14:20:54 +00001763 /* First arg is I32 (rounding mode), second is F64 (data). */
1764 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1765
sewardj3598ef92004-11-11 02:13:30 +00001766 case Iop_ScaleF64:
1767 case Iop_Yl2xF64:
1768 case Iop_Yl2xp1F64:
1769 case Iop_PRemF64:
1770 case Iop_AtanF64:
1771 case Iop_AddF64:
1772 case Iop_DivF64:
1773 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001774 case Iop_MulF64:
1775 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1776
sewardj3598ef92004-11-11 02:13:30 +00001777 case Iop_CmpF64:
1778 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1779
sewardjde8a5ae2004-11-06 14:20:54 +00001780 /* non-FP after here */
1781
1782 case Iop_DivModU64to32:
1783 case Iop_DivModS64to32:
1784 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1785
sewardj3598ef92004-11-11 02:13:30 +00001786 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001787 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001788 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001789 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001790
1791 case Iop_MullS32:
1792 case Iop_MullU32: {
1793 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1794 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1795 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1796 }
1797
sewardj3598ef92004-11-11 02:13:30 +00001798 case Iop_MullS16:
1799 case Iop_MullU16: {
1800 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1801 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1802 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1803 }
1804
1805 case Iop_MullS8:
1806 case Iop_MullU8: {
1807 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1808 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1809 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1810 }
1811
sewardjde8a5ae2004-11-06 14:20:54 +00001812 case Iop_Add32:
1813# if 0
1814 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1815# endif
1816 case Iop_Sub32:
1817 case Iop_Mul32:
1818 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1819
sewardj3598ef92004-11-11 02:13:30 +00001820 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001821 case Iop_Add16:
1822 case Iop_Sub16:
1823 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1824
1825 case Iop_Sub8:
1826 case Iop_Add8:
1827 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1828
1829 case Iop_CmpLE32S: case Iop_CmpLE32U:
1830 case Iop_CmpLT32U: case Iop_CmpLT32S:
1831 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001832 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001833
sewardj3598ef92004-11-11 02:13:30 +00001834 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001835 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001836
1837 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001838 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001839
1840 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1841 /* Complain if the shift amount is undefined. Then simply
1842 shift the first arg's V bits by the real shift amount. */
1843 complainIfUndefined(mce, atom2);
1844 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1845
sewardj69f9e3e2004-12-30 02:05:34 +00001846 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001847 /* Same scheme as with 32-bit shifts. */
1848 complainIfUndefined(mce, atom2);
1849 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1850
sewardj3598ef92004-11-11 02:13:30 +00001851 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001852 /* Same scheme as with 32-bit shifts. */
1853 complainIfUndefined(mce, atom2);
1854 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1855
1856 case Iop_Shl64: case Iop_Shr64:
1857 /* Same scheme as with 32-bit shifts. */
1858 complainIfUndefined(mce, atom2);
1859 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1860
sewardjf0c1c582005-02-07 23:47:38 +00001861 case Iop_AndV128:
1862 uifu = mkUifUV128; difd = mkDifDV128;
1863 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001864 case Iop_And64:
1865 uifu = mkUifU64; difd = mkDifD64;
1866 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001867 case Iop_And32:
1868 uifu = mkUifU32; difd = mkDifD32;
1869 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001870 case Iop_And16:
1871 uifu = mkUifU16; difd = mkDifD16;
1872 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001873 case Iop_And8:
1874 uifu = mkUifU8; difd = mkDifD8;
1875 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1876
sewardjf0c1c582005-02-07 23:47:38 +00001877 case Iop_OrV128:
1878 uifu = mkUifUV128; difd = mkDifDV128;
1879 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001880 case Iop_Or64:
1881 uifu = mkUifU64; difd = mkDifD64;
1882 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001883 case Iop_Or32:
1884 uifu = mkUifU32; difd = mkDifD32;
1885 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1886 case Iop_Or16:
1887 uifu = mkUifU16; difd = mkDifD16;
1888 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1889 case Iop_Or8:
1890 uifu = mkUifU8; difd = mkDifD8;
1891 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1892
1893 do_And_Or:
1894 return
1895 assignNew(
1896 mce,
1897 and_or_ty,
1898 difd(mce, uifu(mce, vatom1, vatom2),
1899 difd(mce, improve(mce, atom1, vatom1),
1900 improve(mce, atom2, vatom2) ) ) );
1901
1902 case Iop_Xor8:
1903 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001904 case Iop_Xor16:
1905 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001906 case Iop_Xor32:
1907 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001908 case Iop_Xor64:
1909 return mkUifU64(mce, vatom1, vatom2);
sewardjf0c1c582005-02-07 23:47:38 +00001910 case Iop_XorV128:
1911 return mkUifUV128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001912
1913 default:
1914 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001915 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001916 }
1917}
1918
1919
1920static
1921IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1922{
1923 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001924 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001925 switch (op) {
1926
sewardj69f9e3e2004-12-30 02:05:34 +00001927 case Iop_Sqrt64Fx2:
1928 return unary64Fx2(mce, vatom);
1929
1930 case Iop_Sqrt64F0x2:
1931 return unary64F0x2(mce, vatom);
1932
1933 case Iop_Sqrt32Fx4:
1934 case Iop_RSqrt32Fx4:
1935 case Iop_Recip32Fx4:
1936 return unary32Fx4(mce, vatom);
1937
1938 case Iop_Sqrt32F0x4:
1939 case Iop_RSqrt32F0x4:
1940 case Iop_Recip32F0x4:
1941 return unary32F0x4(mce, vatom);
1942
sewardjf0c1c582005-02-07 23:47:38 +00001943 case Iop_32UtoV128:
1944 case Iop_64UtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001945 return assignNew(mce, Ity_V128, unop(op, vatom));
1946
sewardjde8a5ae2004-11-06 14:20:54 +00001947 case Iop_F32toF64:
sewardj1e3830f2011-03-14 11:27:26 +00001948 case Iop_I32StoF64:
sewardj3598ef92004-11-11 02:13:30 +00001949 case Iop_NegF64:
1950 case Iop_SinF64:
1951 case Iop_CosF64:
1952 case Iop_TanF64:
1953 case Iop_SqrtF64:
1954 case Iop_AbsF64:
1955 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001956 return mkPCastTo(mce, Ity_I64, vatom);
1957
sewardj3598ef92004-11-11 02:13:30 +00001958 case Iop_Clz32:
1959 case Iop_Ctz32:
1960 return mkPCastTo(mce, Ity_I32, vatom);
1961
1962 case Iop_32Sto64:
1963 case Iop_32Uto64:
sewardjf0c1c582005-02-07 23:47:38 +00001964 case Iop_V128to64:
1965 case Iop_V128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001966 return assignNew(mce, Ity_I64, unop(op, vatom));
1967
sewardjde8a5ae2004-11-06 14:20:54 +00001968 case Iop_64to32:
1969 case Iop_64HIto32:
1970 case Iop_1Uto32:
1971 case Iop_8Uto32:
1972 case Iop_16Uto32:
1973 case Iop_16Sto32:
1974 case Iop_8Sto32:
1975 return assignNew(mce, Ity_I32, unop(op, vatom));
1976
1977 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001978 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001979 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001980 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001981 return assignNew(mce, Ity_I16, unop(op, vatom));
1982
1983 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001984 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001985 case Iop_32to8:
1986 return assignNew(mce, Ity_I8, unop(op, vatom));
1987
1988 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001989 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001990
sewardj3598ef92004-11-11 02:13:30 +00001991 case Iop_ReinterpF64asI64:
1992 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001993 case Iop_ReinterpI32asF32:
sewardjf0c1c582005-02-07 23:47:38 +00001994 case Iop_NotV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001995 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00001996 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001997 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001998 case Iop_Not8:
1999 case Iop_Not1:
2000 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00002001
sewardjde8a5ae2004-11-06 14:20:54 +00002002 default:
2003 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00002004 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00002005 }
2006}
2007
2008
sewardj69f9e3e2004-12-30 02:05:34 +00002009/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00002010static
sewardj69f9e3e2004-12-30 02:05:34 +00002011IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00002012{
2013 void* helper;
sewardjde8c9872005-03-25 13:48:55 +00002014 HChar* hname;
sewardjde8a5ae2004-11-06 14:20:54 +00002015 IRDirty* di;
2016 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00002017 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00002018
sewardj69f9e3e2004-12-30 02:05:34 +00002019 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00002020
2021 /* First, emit a definedness test for the address. This also sets
2022 the address (shadow) to 'defined' following the test. */
2023 complainIfUndefined( mce, addr );
2024
2025 /* Now cook up a call to the relevant helper function, to read the
2026 data V bits from shadow memory. */
2027 ty = shadowType(ty);
2028 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00002029 case Ity_I64: helper = &MC_(helperc_LOADV8);
2030 hname = "MC_(helperc_LOADV8)";
2031 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002032 case Ity_I32: helper = &MC_(helperc_LOADV4);
2033 hname = "MC_(helperc_LOADV4)";
2034 break;
2035 case Ity_I16: helper = &MC_(helperc_LOADV2);
2036 hname = "MC_(helperc_LOADV2)";
2037 break;
2038 case Ity_I8: helper = &MC_(helperc_LOADV1);
2039 hname = "MC_(helperc_LOADV1)";
2040 break;
2041 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00002042 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00002043 }
2044
sewardj3598ef92004-11-11 02:13:30 +00002045 /* Generate the actual address into addrAct. */
2046 if (bias == 0) {
2047 addrAct = addr;
2048 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002049 IROp mkAdd;
2050 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00002051 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00002052 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2053 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2054 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00002055 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2056 }
2057
sewardjde8a5ae2004-11-06 14:20:54 +00002058 /* We need to have a place to park the V bits we're just about to
2059 read. */
2060 datavbits = newIRTemp(mce->bb->tyenv, ty);
2061 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00002062 1/*regparms*/, hname, helper,
2063 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00002064 setHelperAnns( mce, di );
2065 stmt( mce->bb, IRStmt_Dirty(di) );
2066
2067 return mkexpr(datavbits);
2068}
2069
2070
2071static
sewardj69f9e3e2004-12-30 02:05:34 +00002072IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
2073{
2074 IRAtom *v64hi, *v64lo;
2075 switch (shadowType(ty)) {
2076 case Ity_I8:
2077 case Ity_I16:
2078 case Ity_I32:
2079 case Ity_I64:
2080 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
2081 case Ity_V128:
2082 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
2083 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
2084 return assignNew( mce,
2085 Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +00002086 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj69f9e3e2004-12-30 02:05:34 +00002087 default:
2088 VG_(tool_panic)("expr2vbits_LDle");
2089 }
2090}
2091
2092
2093static
sewardjde8a5ae2004-11-06 14:20:54 +00002094IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00002095 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00002096{
2097 IRAtom *vbitsC, *vbits0, *vbitsX;
2098 IRType ty;
2099 /* Given Mux0X(cond,expr0,exprX), generate
2100 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2101 That is, steer the V bits like the originals, but trash the
2102 result if the steering value is undefined. This gives
2103 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00002104 tl_assert(isOriginalAtom(mce, cond));
2105 tl_assert(isOriginalAtom(mce, expr0));
2106 tl_assert(isOriginalAtom(mce, exprX));
sewardjde8a5ae2004-11-06 14:20:54 +00002107
2108 vbitsC = expr2vbits(mce, cond);
2109 vbits0 = expr2vbits(mce, expr0);
2110 vbitsX = expr2vbits(mce, exprX);
2111 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2112
2113 return
2114 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2115 mkPCastTo(mce, ty, vbitsC) );
2116}
2117
2118/* --------- This is the main expression-handling function. --------- */
2119
2120static
2121IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2122{
2123 switch (e->tag) {
2124
2125 case Iex_Get:
2126 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2127
2128 case Iex_GetI:
2129 return shadow_GETI( mce, e->Iex.GetI.descr,
2130 e->Iex.GetI.ix, e->Iex.GetI.bias );
2131
sewardj478646f2008-05-01 20:13:04 +00002132 case Iex_RdTmp:
2133 return IRExpr_RdTmp( findShadowTmp(mce, e->Iex.RdTmp.tmp) );
sewardjde8a5ae2004-11-06 14:20:54 +00002134
2135 case Iex_Const:
2136 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2137
2138 case Iex_Binop:
2139 return expr2vbits_Binop(
2140 mce,
2141 e->Iex.Binop.op,
2142 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2143 );
2144
2145 case Iex_Unop:
2146 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2147
sewardj478646f2008-05-01 20:13:04 +00002148 case Iex_Load:
2149 return expr2vbits_LDle( mce, e->Iex.Load.ty,
2150 e->Iex.Load.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002151
2152 case Iex_CCall:
2153 return mkLazyN( mce, e->Iex.CCall.args,
2154 e->Iex.CCall.retty,
2155 e->Iex.CCall.cee );
2156
2157 case Iex_Mux0X:
2158 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2159 e->Iex.Mux0X.exprX);
2160
2161 default:
2162 VG_(printf)("\n");
2163 ppIRExpr(e);
2164 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002165 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002166 }
2167}
2168
2169/*------------------------------------------------------------*/
2170/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2171/*------------------------------------------------------------*/
2172
2173/* Widen a value to the host word size. */
2174
2175static
2176IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2177{
sewardj69f9e3e2004-12-30 02:05:34 +00002178 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002179
sewardj8fc93742004-11-22 11:29:33 +00002180 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002181 tl_assert(isShadowAtom(mce,vatom));
2182
2183 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2184 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002185
sewardjde8a5ae2004-11-06 14:20:54 +00002186 if (tyH == Ity_I32) {
2187 switch (ty) {
2188 case Ity_I32: return vatom;
2189 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2190 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2191 default: goto unhandled;
2192 }
2193 } else {
2194 goto unhandled;
2195 }
2196 unhandled:
2197 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002198 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002199}
2200
2201
sewardj3598ef92004-11-11 02:13:30 +00002202/* Generate a shadow store. addr is always the original address atom.
2203 You can pass in either originals or V-bits for the data atom, but
2204 obviously not both. */
2205
sewardjde8a5ae2004-11-06 14:20:54 +00002206static
sewardj3598ef92004-11-11 02:13:30 +00002207void do_shadow_STle ( MCEnv* mce,
2208 IRAtom* addr, UInt bias,
2209 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002210{
sewardj69f9e3e2004-12-30 02:05:34 +00002211 IROp mkAdd;
2212 IRType ty, tyAddr;
2213 IRDirty *di, *diLo64, *diHi64;
2214 IRAtom *addrAct, *addrLo64, *addrHi64;
2215 IRAtom *vdataLo64, *vdataHi64;
2216 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002217 void* helper = NULL;
sewardj478646f2008-05-01 20:13:04 +00002218 HChar* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002219
2220 tyAddr = mce->hWordTy;
2221 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2222 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2223
2224 di = diLo64 = diHi64 = NULL;
2225 eBias = eBias0 = eBias8 = NULL;
2226 addrAct = addrLo64 = addrHi64 = NULL;
2227 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002228
sewardj3598ef92004-11-11 02:13:30 +00002229 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002230 tl_assert(!vdata);
2231 tl_assert(isOriginalAtom(mce, data));
2232 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002233 vdata = expr2vbits( mce, data );
2234 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002235 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002236 }
sewardjde8a5ae2004-11-06 14:20:54 +00002237
sewardj69f9e3e2004-12-30 02:05:34 +00002238 tl_assert(isOriginalAtom(mce,addr));
2239 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002240
2241 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002242
2243 /* First, emit a definedness test for the address. This also sets
2244 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002245 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002246
sewardj69f9e3e2004-12-30 02:05:34 +00002247 /* Now decide which helper function to call to write the data V
2248 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002249 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002250 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002251 case Ity_I64: helper = &MC_(helperc_STOREV8);
2252 hname = "MC_(helperc_STOREV8)";
2253 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002254 case Ity_I32: helper = &MC_(helperc_STOREV4);
2255 hname = "MC_(helperc_STOREV4)";
2256 break;
2257 case Ity_I16: helper = &MC_(helperc_STOREV2);
2258 hname = "MC_(helperc_STOREV2)";
2259 break;
2260 case Ity_I8: helper = &MC_(helperc_STOREV1);
2261 hname = "MC_(helperc_STOREV1)";
2262 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002263 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002264 }
2265
sewardj69f9e3e2004-12-30 02:05:34 +00002266 if (ty == Ity_V128) {
2267
sewardjf0c1c582005-02-07 23:47:38 +00002268 /* V128-bit case */
sewardj69f9e3e2004-12-30 02:05:34 +00002269 /* See comment in next clause re 64-bit regparms */
2270 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2271 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
sewardjf0c1c582005-02-07 23:47:38 +00002272 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002273 diLo64 = unsafeIRDirty_0_N(
2274 1/*regparms*/, hname, helper,
2275 mkIRExprVec_2( addrLo64, vdataLo64 ));
2276
2277 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2278 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
sewardjf0c1c582005-02-07 23:47:38 +00002279 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002280 diHi64 = unsafeIRDirty_0_N(
2281 1/*regparms*/, hname, helper,
2282 mkIRExprVec_2( addrHi64, vdataHi64 ));
2283
2284 setHelperAnns( mce, diLo64 );
2285 setHelperAnns( mce, diHi64 );
2286 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2287 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2288
sewardj3598ef92004-11-11 02:13:30 +00002289 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002290
2291 /* 8/16/32/64-bit cases */
2292 /* Generate the actual address into addrAct. */
2293 if (bias == 0) {
2294 addrAct = addr;
2295 } else {
2296 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2297 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2298 }
2299
2300 if (ty == Ity_I64) {
2301 /* We can't do this with regparm 2 on 32-bit platforms, since
2302 the back ends aren't clever enough to handle 64-bit
2303 regparm args. Therefore be different. */
2304 di = unsafeIRDirty_0_N(
2305 1/*regparms*/, hname, helper,
2306 mkIRExprVec_2( addrAct, vdata ));
2307 } else {
2308 di = unsafeIRDirty_0_N(
2309 2/*regparms*/, hname, helper,
2310 mkIRExprVec_2( addrAct,
2311 zwidenToHostWord( mce, vdata )));
2312 }
2313 setHelperAnns( mce, di );
2314 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002315 }
2316
sewardjde8a5ae2004-11-06 14:20:54 +00002317}
2318
2319
sewardj3598ef92004-11-11 02:13:30 +00002320/* Do lazy pessimistic propagation through a dirty helper call, by
2321 looking at the annotations on it. This is the most complex part of
2322 Memcheck. */
2323
2324static IRType szToITy ( Int n )
2325{
2326 switch (n) {
2327 case 1: return Ity_I8;
2328 case 2: return Ity_I16;
2329 case 4: return Ity_I32;
2330 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002331 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002332 }
2333}
2334
2335static
2336void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2337{
sewardj69f9e3e2004-12-30 02:05:34 +00002338 Int i, n, offset, toDo, gSz, gOff;
2339 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002340 IRType tyAddr, tySrc, tyDst;
2341 IRTemp dst;
2342
2343 /* First check the guard. */
2344 complainIfUndefined(mce, d->guard);
2345
2346 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002347 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002348
2349 /* Inputs: unmasked args */
2350 for (i = 0; d->args[i]; i++) {
2351 if (d->cee->mcx_mask & (1<<i)) {
2352 /* ignore this arg */
2353 } else {
2354 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2355 curr = mkUifU32(mce, here, curr);
2356 }
2357 }
2358
2359 /* Inputs: guest state that we read. */
2360 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002361 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002362 if (d->fxState[i].fx == Ifx_Write)
2363 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002364
2365 /* Ignore any sections marked as 'always defined'. */
2366 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2367 if (0)
2368 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2369 d->fxState[i].offset, d->fxState[i].size );
2370 continue;
2371 }
2372
sewardj3598ef92004-11-11 02:13:30 +00002373 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002374 consider it. If larger than 8 bytes, deal with it in 8-byte
2375 chunks. */
2376 gSz = d->fxState[i].size;
2377 gOff = d->fxState[i].offset;
2378 tl_assert(gSz > 0);
2379 while (True) {
2380 if (gSz == 0) break;
2381 n = gSz <= 8 ? gSz : 8;
2382 /* update 'curr' with UifU of the state slice
2383 gOff .. gOff+n-1 */
2384 tySrc = szToITy( n );
2385 src = assignNew( mce, tySrc,
2386 shadow_GET(mce, gOff, tySrc ) );
2387 here = mkPCastTo( mce, Ity_I32, src );
2388 curr = mkUifU32(mce, here, curr);
2389 gSz -= n;
2390 gOff += n;
2391 }
2392
sewardj3598ef92004-11-11 02:13:30 +00002393 }
2394
2395 /* Inputs: memory. First set up some info needed regardless of
2396 whether we're doing reads or writes. */
2397 tyAddr = Ity_INVALID;
2398
2399 if (d->mFx != Ifx_None) {
2400 /* Because we may do multiple shadow loads/stores from the same
2401 base address, it's best to do a single test of its
2402 definedness right now. Post-instrumentation optimisation
2403 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002404 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002405 complainIfUndefined(mce, d->mAddr);
2406
2407 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002408 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2409 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002410 }
2411
2412 /* Deal with memory inputs (reads or modifies) */
2413 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2414 offset = 0;
2415 toDo = d->mSize;
2416 /* chew off 32-bit chunks */
2417 while (toDo >= 4) {
2418 here = mkPCastTo(
2419 mce, Ity_I32,
2420 expr2vbits_LDle ( mce, Ity_I32,
2421 d->mAddr, d->mSize - toDo )
2422 );
2423 curr = mkUifU32(mce, here, curr);
2424 toDo -= 4;
2425 }
2426 /* chew off 16-bit chunks */
2427 while (toDo >= 2) {
2428 here = mkPCastTo(
2429 mce, Ity_I32,
2430 expr2vbits_LDle ( mce, Ity_I16,
2431 d->mAddr, d->mSize - toDo )
2432 );
2433 curr = mkUifU32(mce, here, curr);
2434 toDo -= 2;
2435 }
sewardj69f9e3e2004-12-30 02:05:34 +00002436 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002437 }
2438
2439 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2440 all the inputs to the helper. Now we need to re-distribute the
2441 results to all destinations. */
2442
2443 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002444 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002445 dst = findShadowTmp(mce, d->tmp);
2446 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2447 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2448 }
2449
2450 /* Outputs: guest state that we write or modify. */
2451 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002452 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002453 if (d->fxState[i].fx == Ifx_Read)
2454 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002455 /* Ignore any sections marked as 'always defined'. */
2456 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2457 continue;
2458 /* This state element is written or modified. So we need to
2459 consider it. If larger than 8 bytes, deal with it in 8-byte
2460 chunks. */
2461 gSz = d->fxState[i].size;
2462 gOff = d->fxState[i].offset;
2463 tl_assert(gSz > 0);
2464 while (True) {
2465 if (gSz == 0) break;
2466 n = gSz <= 8 ? gSz : 8;
2467 /* Write suitably-casted 'curr' to the state slice
2468 gOff .. gOff+n-1 */
2469 tyDst = szToITy( n );
2470 do_shadow_PUT( mce, gOff,
2471 NULL, /* original atom */
2472 mkPCastTo( mce, tyDst, curr ) );
2473 gSz -= n;
2474 gOff += n;
2475 }
sewardj3598ef92004-11-11 02:13:30 +00002476 }
2477
2478 /* Outputs: memory that we write or modify. */
2479 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2480 offset = 0;
2481 toDo = d->mSize;
2482 /* chew off 32-bit chunks */
2483 while (toDo >= 4) {
2484 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2485 NULL, /* original data */
2486 mkPCastTo( mce, Ity_I32, curr ) );
2487 toDo -= 4;
2488 }
2489 /* chew off 16-bit chunks */
2490 while (toDo >= 2) {
2491 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2492 NULL, /* original data */
2493 mkPCastTo( mce, Ity_I16, curr ) );
2494 toDo -= 2;
2495 }
sewardj69f9e3e2004-12-30 02:05:34 +00002496 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002497 }
2498
2499}
2500
2501
sewardjde8a5ae2004-11-06 14:20:54 +00002502/*------------------------------------------------------------*/
2503/*--- Memcheck main ---*/
2504/*------------------------------------------------------------*/
2505
sewardj3598ef92004-11-11 02:13:30 +00002506static Bool isBogusAtom ( IRAtom* at )
2507{
2508 ULong n = 0;
2509 IRConst* con;
sewardj496a58d2005-03-20 18:44:44 +00002510 tl_assert(isIRAtom(at));
sewardj478646f2008-05-01 20:13:04 +00002511 if (at->tag == Iex_RdTmp)
sewardj3598ef92004-11-11 02:13:30 +00002512 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002513 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002514 con = at->Iex.Const.con;
2515 switch (con->tag) {
2516 case Ico_U8: n = (ULong)con->Ico.U8; break;
2517 case Ico_U16: n = (ULong)con->Ico.U16; break;
2518 case Ico_U32: n = (ULong)con->Ico.U32; break;
2519 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002520 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002521 }
2522 /* VG_(printf)("%llx\n", n); */
2523 return (n == 0xFEFEFEFF
2524 || n == 0x80808080
2525 || n == 0x1010101
2526 || n == 1010100);
2527}
2528
sewardj5f438dd2011-06-16 11:36:23 +00002529__attribute__((unused))
sewardj3598ef92004-11-11 02:13:30 +00002530static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2531{
2532 Int i;
2533 IRExpr* e;
2534 switch (st->tag) {
sewardj478646f2008-05-01 20:13:04 +00002535 case Ist_WrTmp:
2536 e = st->Ist.WrTmp.data;
sewardj3598ef92004-11-11 02:13:30 +00002537 switch (e->tag) {
2538 case Iex_Get:
sewardj478646f2008-05-01 20:13:04 +00002539 case Iex_RdTmp:
sewardj3598ef92004-11-11 02:13:30 +00002540 return False;
2541 case Iex_Unop:
2542 return isBogusAtom(e->Iex.Unop.arg);
2543 case Iex_Binop:
2544 return isBogusAtom(e->Iex.Binop.arg1)
2545 || isBogusAtom(e->Iex.Binop.arg2);
2546 case Iex_Mux0X:
2547 return isBogusAtom(e->Iex.Mux0X.cond)
2548 || isBogusAtom(e->Iex.Mux0X.expr0)
2549 || isBogusAtom(e->Iex.Mux0X.exprX);
sewardj478646f2008-05-01 20:13:04 +00002550 case Iex_Load:
2551 return isBogusAtom(e->Iex.Load.addr);
sewardj3598ef92004-11-11 02:13:30 +00002552 case Iex_CCall:
2553 for (i = 0; e->Iex.CCall.args[i]; i++)
2554 if (isBogusAtom(e->Iex.CCall.args[i]))
2555 return True;
2556 return False;
2557 default:
2558 goto unhandled;
2559 }
2560 case Ist_Put:
2561 return isBogusAtom(st->Ist.Put.data);
sewardj478646f2008-05-01 20:13:04 +00002562 case Ist_Store:
2563 return isBogusAtom(st->Ist.Store.addr)
2564 || isBogusAtom(st->Ist.Store.data);
sewardj3598ef92004-11-11 02:13:30 +00002565 case Ist_Exit:
sewardj1ea1b612005-03-26 13:02:20 +00002566 return isBogusAtom(st->Ist.Exit.guard);
sewardj3598ef92004-11-11 02:13:30 +00002567 default:
2568 unhandled:
2569 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002570 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002571 }
2572}
sewardj3598ef92004-11-11 02:13:30 +00002573
sewardj478646f2008-05-01 20:13:04 +00002574IRSB* mc_instrument ( void* closureV,
2575 IRSB* bb_in, VexGuestLayout* layout,
2576 VexGuestExtents* vge,
sewardj1ea1b612005-03-26 13:02:20 +00002577 IRType gWordTy, IRType hWordTy )
sewardjde8a5ae2004-11-06 14:20:54 +00002578{
sewardj3598ef92004-11-11 02:13:30 +00002579 Bool verboze = False; //True;
2580
2581 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002582
2583 Int i, j, first_stmt;
2584 IRStmt* st;
2585 MCEnv mce;
2586
2587 /* Set up BB */
sewardjf6c8ebf2007-02-06 01:52:52 +00002588 IRSB* bb = emptyIRSB();
sewardj478646f2008-05-01 20:13:04 +00002589 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
2590 bb->next = deepCopyIRExpr(bb_in->next);
sewardjde8a5ae2004-11-06 14:20:54 +00002591 bb->jumpkind = bb_in->jumpkind;
2592
2593 /* Set up the running environment. Only .bb is modified as we go
2594 along. */
2595 mce.bb = bb;
2596 mce.layout = layout;
2597 mce.n_originalTmps = bb->tyenv->types_used;
2598 mce.hWordTy = hWordTy;
2599 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2600 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002601 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002602
2603 /* Iterate over the stmts. */
2604
2605 for (i = 0; i < bb_in->stmts_used; i++) {
2606 st = bb_in->stmts[i];
2607 if (!st) continue;
2608
sewardj69f9e3e2004-12-30 02:05:34 +00002609 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002610
2611 /*
2612 if (!hasBogusLiterals) {
2613 hasBogusLiterals = checkForBogusLiterals(st);
2614 if (hasBogusLiterals) {
2615 VG_(printf)("bogus: ");
2616 ppIRStmt(st);
2617 VG_(printf)("\n");
2618 }
2619 }
2620 */
sewardjde8a5ae2004-11-06 14:20:54 +00002621 first_stmt = bb->stmts_used;
2622
2623 if (verboze) {
2624 ppIRStmt(st);
2625 VG_(printf)("\n\n");
2626 }
2627
2628 switch (st->tag) {
2629
sewardj478646f2008-05-01 20:13:04 +00002630 case Ist_WrTmp:
2631 assign( bb, findShadowTmp(&mce, st->Ist.WrTmp.tmp),
2632 expr2vbits( &mce, st->Ist.WrTmp.data) );
sewardjde8a5ae2004-11-06 14:20:54 +00002633 break;
2634
2635 case Ist_Put:
2636 do_shadow_PUT( &mce,
2637 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002638 st->Ist.Put.data,
2639 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002640 break;
2641
2642 case Ist_PutI:
2643 do_shadow_PUTI( &mce,
florian4180af32012-12-24 00:25:34 +00002644 st->Ist.PutI.details->descr,
2645 st->Ist.PutI.details->ix,
2646 st->Ist.PutI.details->bias,
2647 st->Ist.PutI.details->data );
sewardjde8a5ae2004-11-06 14:20:54 +00002648 break;
2649
sewardj478646f2008-05-01 20:13:04 +00002650 case Ist_Store:
2651 do_shadow_STle( &mce, st->Ist.Store.addr, 0/* addr bias */,
2652 st->Ist.Store.data,
sewardj3598ef92004-11-11 02:13:30 +00002653 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002654 break;
2655
2656 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002657 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002658 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002659 break;
2660
2661 case Ist_Dirty:
2662 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002663 break;
2664
sewardj1ea1b612005-03-26 13:02:20 +00002665 case Ist_IMark:
2666 case Ist_NoOp:
2667 break;
2668
sewardjde8a5ae2004-11-06 14:20:54 +00002669 default:
2670 VG_(printf)("\n");
2671 ppIRStmt(st);
2672 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002673 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002674
2675 } /* switch (st->tag) */
2676
2677 if (verboze) {
2678 for (j = first_stmt; j < bb->stmts_used; j++) {
2679 VG_(printf)(" ");
2680 ppIRStmt(bb->stmts[j]);
2681 VG_(printf)("\n");
2682 }
2683 VG_(printf)("\n");
2684 }
2685
sewardjf6c8ebf2007-02-06 01:52:52 +00002686 addStmtToIRSB(bb, st);
sewardjde8a5ae2004-11-06 14:20:54 +00002687
2688 }
2689
2690 /* Now we need to complain if the jump target is undefined. */
2691 first_stmt = bb->stmts_used;
2692
2693 if (verboze) {
2694 VG_(printf)("bb->next = ");
2695 ppIRExpr(bb->next);
2696 VG_(printf)("\n\n");
2697 }
2698
2699 complainIfUndefined( &mce, bb->next );
2700
2701 if (verboze) {
2702 for (j = first_stmt; j < bb->stmts_used; j++) {
2703 VG_(printf)(" ");
2704 ppIRStmt(bb->stmts[j]);
2705 VG_(printf)("\n");
2706 }
2707 VG_(printf)("\n");
2708 }
2709
2710 return bb;
2711}
cerionaee45242005-03-17 14:03:36 +00002712#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002713
2714/*--------------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00002715/*--- end test_main.c ---*/
sewardjde8a5ae2004-11-06 14:20:54 +00002716/*--------------------------------------------------------------------*/