blob: b036acd38e0d6410c66e0fb916afabb953cc695b [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
10 Copyright (C) 2004-2010 OpenWorks LLP
11 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 */
sewardjf6c8ebf2007-02-06 01:52:52 +000079static 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
sewardjc716aea2006-01-17 01:48:46 +000087static Bool chase_into_not_ok ( void* opaque, Addr64 dst ) { return False; }
sewardj9b1004e2004-10-30 22:25:40 +000088
sewardjced9fe52004-07-07 11:55:36 +000089int main ( int argc, char** argv )
sewardjce605f92004-07-05 14:39:15 +000090{
sewardjced9fe52004-07-07 11:55:36 +000091 FILE* f;
92 Int i;
sewardj4459baa2004-09-10 20:00:46 +000093 UInt u, sum;
sewardjced9fe52004-07-07 11:55:36 +000094 Addr32 orig_addr;
sewardjabe017e2004-10-29 23:42:36 +000095 Int bb_number, n_bbs_done = 0;
sewardj72c72812005-01-19 11:49:45 +000096 Int orig_nbytes, trans_used;
sewardjd887b862005-01-17 18:34:34 +000097 VexTranslateResult tres;
sewardjb5bf2e02004-10-25 13:06:17 +000098 VexControl vcon;
sewardj72c72812005-01-19 11:49:45 +000099 VexGuestExtents vge;
sewardj9e6491a2005-07-02 19:24:10 +0000100 VexArchInfo vai_x86, vai_amd64, vai_ppc32;
sewardjdd40fdf2006-12-24 02:20:24 +0000101 VexAbiInfo vbi;
sewardj17c7f952005-12-15 14:02:34 +0000102 VexTranslateArgs vta;
sewardjced9fe52004-07-07 11:55:36 +0000103
104 if (argc != 2) {
105 fprintf(stderr, "usage: vex file.org\n");
106 exit(1);
107 }
108 f = fopen(argv[1], "r");
109 if (!f) {
110 fprintf(stderr, "can't open `%s'\n", argv[1]);
111 exit(1);
112 }
113
sewardjb5bf2e02004-10-25 13:06:17 +0000114 /* Run with default params. However, we can't allow bb chasing
115 since that causes the front end to get segfaults when it tries
sewardj5bd4d162004-11-10 13:02:48 +0000116 to read code outside the initial BB we hand it. So when calling
117 LibVEX_Translate, send in a chase-into predicate that always
118 returns False. */
sewardjb5bf2e02004-10-25 13:06:17 +0000119 LibVEX_default_VexControl ( &vcon );
sewardjb4952402004-10-26 13:24:50 +0000120 vcon.iropt_level = 2;
sewardjc279b3f2005-03-16 18:10:45 +0000121 vcon.guest_max_insns = 50;
sewardjb5bf2e02004-10-25 13:06:17 +0000122
sewardjced9fe52004-07-07 11:55:36 +0000123 LibVEX_Init ( &failure_exit, &log_bytes,
sewardj1f40a0a2004-07-21 12:28:07 +0000124 1, /* debug_paranoia */
sewardjabe017e2004-10-29 23:42:36 +0000125 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +0000126 &vcon );
sewardjced9fe52004-07-07 11:55:36 +0000127
sewardjea64e142004-07-22 16:47:21 +0000128
sewardjced9fe52004-07-07 11:55:36 +0000129 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +0000130
sewardjced9fe52004-07-07 11:55:36 +0000131 fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +0000132 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +0000133 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +0000134
135 if (n_bbs_done == TEST_N_BBS) break;
136 n_bbs_done++;
137
sewardjced9fe52004-07-07 11:55:36 +0000138 /* first line is: . bb-number bb-addr n-bytes */
139 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
140 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000141 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000142 assert(orig_nbytes >= 1);
143 assert(!feof(f));
144 fgets(linebuf, N_LINEBUF,f);
145 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000146
sewardjced9fe52004-07-07 11:55:36 +0000147 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000148 if (verbose)
sewardj07a54cc2005-02-04 21:18:55 +0000149 printf("============ Basic Block %d, Done %d, "
sewardj4459baa2004-09-10 20:00:46 +0000150 "Start %x, nbytes %2d ============",
sewardj07a54cc2005-02-04 21:18:55 +0000151 bb_number, n_bbs_done-1, orig_addr, orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000152
sewardjced9fe52004-07-07 11:55:36 +0000153 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
154 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000155 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
156 origbuf[i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000157 }
158
sewardj5117ce12006-01-27 21:20:15 +0000159 /* FIXME: put sensible values into the .hwcaps fields */
sewardj9e6491a2005-07-02 19:24:10 +0000160 LibVEX_default_VexArchInfo(&vai_x86);
sewardjc4356f02007-11-09 21:15:04 +0000161 vai_x86.hwcaps = VEX_HWCAPS_X86_SSE1
162 | VEX_HWCAPS_X86_SSE2 | VEX_HWCAPS_X86_SSE3;
sewardj9e6491a2005-07-02 19:24:10 +0000163
164 LibVEX_default_VexArchInfo(&vai_amd64);
sewardj5117ce12006-01-27 21:20:15 +0000165 vai_amd64.hwcaps = 0;
sewardj9e6491a2005-07-02 19:24:10 +0000166
167 LibVEX_default_VexArchInfo(&vai_ppc32);
sewardj5117ce12006-01-27 21:20:15 +0000168 vai_ppc32.hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000169 vai_ppc32.ppc_cache_line_szB = 128;
sewardj02ef7162005-06-30 12:50:50 +0000170
sewardjdd40fdf2006-12-24 02:20:24 +0000171 LibVEX_default_VexAbiInfo(&vbi);
sewardjaca070a2006-10-17 00:28:22 +0000172
sewardj17c7f952005-12-15 14:02:34 +0000173 /* ----- Set up args for LibVEX_Translate ----- */
sewardjc4356f02007-11-09 21:15:04 +0000174#if 0 /* ppc32 -> ppc32 */
sewardj17c7f952005-12-15 14:02:34 +0000175 vta.arch_guest = VexArchPPC32;
176 vta.archinfo_guest = vai_ppc32;
177 vta.arch_host = VexArchPPC32;
178 vta.archinfo_host = vai_ppc32;
sewardj07a54cc2005-02-04 21:18:55 +0000179#endif
sewardjc279b3f2005-03-16 18:10:45 +0000180#if 0 /* amd64 -> amd64 */
sewardj17c7f952005-12-15 14:02:34 +0000181 vta.arch_guest = VexArchAMD64;
182 vta.archinfo_guest = vai_amd64;
183 vta.arch_host = VexArchAMD64;
184 vta.archinfo_host = vai_amd64;
sewardj07a54cc2005-02-04 21:18:55 +0000185#endif
sewardjc4356f02007-11-09 21:15:04 +0000186#if 1 /* x86 -> x86 */
sewardj17c7f952005-12-15 14:02:34 +0000187 vta.arch_guest = VexArchX86;
188 vta.archinfo_guest = vai_x86;
189 vta.arch_host = VexArchX86;
190 vta.archinfo_host = vai_x86;
sewardjc279b3f2005-03-16 18:10:45 +0000191#endif
sewardjdd40fdf2006-12-24 02:20:24 +0000192 vta.abiinfo_both = vbi;
sewardj17c7f952005-12-15 14:02:34 +0000193 vta.guest_bytes = origbuf;
194 vta.guest_bytes_addr = (Addr64)orig_addr;
sewardjc716aea2006-01-17 01:48:46 +0000195 vta.callback_opaque = NULL;
sewardj17c7f952005-12-15 14:02:34 +0000196 vta.chase_into_ok = chase_into_not_ok;
197 vta.guest_extents = &vge;
198 vta.host_bytes = transbuf;
199 vta.host_bytes_size = N_TRANSBUF;
200 vta.host_bytes_used = &trans_used;
sewardj478646f2008-05-01 20:13:04 +0000201#if 0 /* no instrumentation */
sewardj17c7f952005-12-15 14:02:34 +0000202 vta.instrument1 = NULL;
203 vta.instrument2 = NULL;
sewardj9e7448b2004-11-18 13:44:15 +0000204#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000205#if 0 /* addrcheck */
sewardj17c7f952005-12-15 14:02:34 +0000206 vta.instrument1 = ac_instrument;
207 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000208#endif
sewardj478646f2008-05-01 20:13:04 +0000209#if 1 /* memcheck */
sewardj17c7f952005-12-15 14:02:34 +0000210 vta.instrument1 = mc_instrument;
211 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000212#endif
sewardj17c7f952005-12-15 14:02:34 +0000213 vta.do_self_check = False;
sewardjc716aea2006-01-17 01:48:46 +0000214 vta.preamble_function = NULL;
sewardj17c7f952005-12-15 14:02:34 +0000215 vta.traceflags = TEST_FLAGS;
216#if 1 /* x86, amd64 hosts */
217 vta.dispatch = (void*)0x12345678;
218#else /* ppc32, ppc64 hosts */
219 vta.dispatch = NULL;
220#endif
221
sewardjc4356f02007-11-09 21:15:04 +0000222 vta.finaltidy = NULL;
223
sewardj17c7f952005-12-15 14:02:34 +0000224 for (i = 0; i < TEST_N_ITERS; i++)
225 tres = LibVEX_Translate ( &vta );
sewardjabe017e2004-10-29 23:42:36 +0000226
sewardjd887b862005-01-17 18:34:34 +0000227 if (tres != VexTransOK)
sewardj4459baa2004-09-10 20:00:46 +0000228 printf("\ntres = %d\n", (Int)tres);
sewardjd887b862005-01-17 18:34:34 +0000229 assert(tres == VexTransOK);
sewardj72c72812005-01-19 11:49:45 +0000230 assert(vge.n_used == 1);
231 assert((UInt)(vge.len[0]) == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000232
sewardj4459baa2004-09-10 20:00:46 +0000233 sum = 0;
234 for (i = 0; i < trans_used; i++)
235 sum += (UInt)transbuf[i];
sewardjde8c9872005-03-25 13:48:55 +0000236 printf ( " %6.2f ... %u\n",
237 (double)trans_used / (double)vge.len[0], sum );
sewardjced9fe52004-07-07 11:55:36 +0000238 }
239
240 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000241 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000242 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000243
sewardjce605f92004-07-05 14:39:15 +0000244 return 0;
245}
sewardj9b1004e2004-10-30 22:25:40 +0000246
247//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000248//////////////////////////////////////////////////////////////////////
249//////////////////////////////////////////////////////////////////////
250//////////////////////////////////////////////////////////////////////
251//////////////////////////////////////////////////////////////////////
252//////////////////////////////////////////////////////////////////////
253//////////////////////////////////////////////////////////////////////
254//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000255
sewardj1ea1b612005-03-26 13:02:20 +0000256#if 0 /* UNUSED */
257
sewardj9b1004e2004-10-30 22:25:40 +0000258static
sewardjde8a5ae2004-11-06 14:20:54 +0000259__attribute((noreturn))
sewardjde8c9872005-03-25 13:48:55 +0000260void panic ( HChar* s )
sewardj9b1004e2004-10-30 22:25:40 +0000261{
262 printf("\npanic: %s\n", s);
263 failure_exit();
264}
265
266static
sewardjf6c8ebf2007-02-06 01:52:52 +0000267IRSB* ac_instrument (IRSB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000268{
269/* Use this rather than eg. -1 because it's a UInt. */
270#define INVALID_DATA_SIZE 999999
271
272 Int i;
273 Int sz;
274 IRCallee* helper;
275 IRStmt* st;
276 IRExpr* data;
277 IRExpr* addr;
278 Bool needSz;
279
280 /* Set up BB */
sewardjf6c8ebf2007-02-06 01:52:52 +0000281 IRSB* bb = emptyIRSB();
sewardj9b1004e2004-10-30 22:25:40 +0000282 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
283 bb->next = dopyIRExpr(bb_in->next);
284 bb->jumpkind = bb_in->jumpkind;
285
286 /* No loads to consider in ->next. */
sewardj496a58d2005-03-20 18:44:44 +0000287 assert(isIRAtom(bb_in->next));
sewardj9b1004e2004-10-30 22:25:40 +0000288
289 for (i = 0; i < bb_in->stmts_used; i++) {
290 st = bb_in->stmts[i];
291 if (!st) continue;
292
293 switch (st->tag) {
294
295 case Ist_Tmp:
296 data = st->Ist.Tmp.data;
297 if (data->tag == Iex_LDle) {
298 addr = data->Iex.LDle.addr;
299 sz = sizeofIRType(data->Iex.LDle.ty);
300 needSz = False;
301 switch (sz) {
302 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000303 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000304 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000305 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000306 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000307 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000308 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000309 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000310 needSz = True; break;
311 }
312 if (needSz) {
sewardjf6c8ebf2007-02-06 01:52:52 +0000313 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000314 bb,
315 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000316 unsafeIRDirty_0_N( helper->regparms,
317 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000318 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
319 ));
320 } else {
sewardjf6c8ebf2007-02-06 01:52:52 +0000321 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000322 bb,
323 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000324 unsafeIRDirty_0_N( helper->regparms,
325 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000326 mkIRExprVec_1(addr) )
327 ));
328 }
329 }
330 break;
331
332 case Ist_STle:
333 data = st->Ist.STle.data;
334 addr = st->Ist.STle.addr;
sewardj496a58d2005-03-20 18:44:44 +0000335 assert(isIRAtom(data));
336 assert(isIRAtom(addr));
sewardj9b1004e2004-10-30 22:25:40 +0000337 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
338 needSz = False;
339 switch (sz) {
340 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000341 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000342 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000343 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000344 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000345 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000346 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000347 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000348 needSz = True; break;
349 }
350 if (needSz) {
sewardjf6c8ebf2007-02-06 01:52:52 +0000351 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000352 bb,
353 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000354 unsafeIRDirty_0_N( helper->regparms,
355 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000356 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
357 ));
358 } else {
sewardjf6c8ebf2007-02-06 01:52:52 +0000359 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000360 bb,
361 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000362 unsafeIRDirty_0_N( helper->regparms,
363 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000364 mkIRExprVec_1(addr) )
365 ));
366 }
367 break;
368
369 case Ist_Put:
sewardj496a58d2005-03-20 18:44:44 +0000370 assert(isIRAtom(st->Ist.Put.data));
sewardj9b1004e2004-10-30 22:25:40 +0000371 break;
372
373 case Ist_PutI:
sewardj496a58d2005-03-20 18:44:44 +0000374 assert(isIRAtom(st->Ist.PutI.ix));
375 assert(isIRAtom(st->Ist.PutI.data));
sewardj9b1004e2004-10-30 22:25:40 +0000376 break;
377
378 case Ist_Exit:
sewardj496a58d2005-03-20 18:44:44 +0000379 assert(isIRAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000380 break;
381
382 case Ist_Dirty:
383 /* If the call doesn't interact with memory, we ain't
384 interested. */
385 if (st->Ist.Dirty.details->mFx == Ifx_None)
386 break;
387 goto unhandled;
388
389 default:
390 unhandled:
391 printf("\n");
392 ppIRStmt(st);
393 printf("\n");
394 panic("addrcheck: unhandled IRStmt");
395 }
396
sewardjf6c8ebf2007-02-06 01:52:52 +0000397 addStmtToIRSB( bb, dopyIRStmt(st));
sewardj9b1004e2004-10-30 22:25:40 +0000398 }
399
400 return bb;
401}
cerionaee45242005-03-17 14:03:36 +0000402#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +0000403
404//////////////////////////////////////////////////////////////////////
405//////////////////////////////////////////////////////////////////////
406//////////////////////////////////////////////////////////////////////
407//////////////////////////////////////////////////////////////////////
408//////////////////////////////////////////////////////////////////////
409//////////////////////////////////////////////////////////////////////
410//////////////////////////////////////////////////////////////////////
411//////////////////////////////////////////////////////////////////////
412
sewardj478646f2008-05-01 20:13:04 +0000413#if 1 /* UNUSED */
414
415static
416__attribute((noreturn))
417void panic ( HChar* s )
418{
419 printf("\npanic: %s\n", s);
420 failure_exit();
421}
sewardj1ea1b612005-03-26 13:02:20 +0000422
sewardj69f9e3e2004-12-30 02:05:34 +0000423#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000424#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000425#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000426#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000427#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000428
cerionaee45242005-03-17 14:03:36 +0000429
sewardjde8c9872005-03-25 13:48:55 +0000430static void MC_helperc_complain_undef ( void );
431static void MC_helperc_LOADV8 ( void );
432static void MC_helperc_LOADV4 ( void );
433static void MC_helperc_LOADV2 ( void );
434static void MC_helperc_LOADV1 ( void );
sewardj1ea1b612005-03-26 13:02:20 +0000435static void MC_helperc_STOREV8( void );
436static void MC_helperc_STOREV4( void );
437static void MC_helperc_STOREV2( void );
438static void MC_helperc_STOREV1( void );
sewardjde8c9872005-03-25 13:48:55 +0000439static void MC_helperc_value_check0_fail( void );
440static void MC_helperc_value_check1_fail( void );
441static void MC_helperc_value_check4_fail( void );
442
443static 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 ) { }
sewardj3598ef92004-11-11 02:13:30 +0000455
456
sewardj3598ef92004-11-11 02:13:30 +0000457/*--------------------------------------------------------------------*/
458/*--- Instrument IR to perform memory checking operations. ---*/
459/*--- mc_translate.c ---*/
460/*--------------------------------------------------------------------*/
461
462/*
463 This file is part of MemCheck, a heavyweight Valgrind tool for
464 detecting memory errors.
465
sewardj752f9062010-05-03 21:38:49 +0000466 Copyright (C) 2000-2010 Julian Seward
sewardj3598ef92004-11-11 02:13:30 +0000467 jseward@acm.org
468
469 This program is free software; you can redistribute it and/or
470 modify it under the terms of the GNU General Public License as
471 published by the Free Software Foundation; either version 2 of the
472 License, or (at your option) any later version.
473
474 This program is distributed in the hope that it will be useful, but
475 WITHOUT ANY WARRANTY; without even the implied warranty of
476 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
477 General Public License for more details.
478
479 You should have received a copy of the GNU General Public License
480 along with this program; if not, write to the Free Software
481 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
482 02111-1307, USA.
483
484 The GNU General Public License is contained in the file COPYING.
485*/
486
487//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000488
489
490/*------------------------------------------------------------*/
491/*--- Forward decls ---*/
492/*------------------------------------------------------------*/
493
494struct _MCEnv;
495
496static IRType shadowType ( IRType ty );
497static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
498
499
500/*------------------------------------------------------------*/
501/*--- Memcheck running state, and tmp management. ---*/
502/*------------------------------------------------------------*/
503
504/* Carries around state during memcheck instrumentation. */
505typedef
506 struct _MCEnv {
507 /* MODIFIED: the bb being constructed. IRStmts are added. */
sewardjf6c8ebf2007-02-06 01:52:52 +0000508 IRSB* bb;
sewardjde8a5ae2004-11-06 14:20:54 +0000509
510 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
511 original temps to their current their current shadow temp.
512 Initially all entries are IRTemp_INVALID. Entries are added
513 lazily since many original temps are not used due to
514 optimisation prior to instrumentation. Note that floating
515 point original tmps are shadowed by integer tmps of the same
516 size, and Bit-typed original tmps are shadowed by the type
517 Ity_I8. See comment below. */
518 IRTemp* tmpMap;
519 Int n_originalTmps; /* for range checking */
520
521 /* READONLY: the guest layout. This indicates which parts of
522 the guest state should be regarded as 'always defined'. */
523 VexGuestLayout* layout;
524 /* READONLY: the host word type. Needed for constructing
525 arguments of type 'HWord' to be passed to helper functions.
526 Ity_I32 or Ity_I64 only. */
527 IRType hWordTy;
528 }
529 MCEnv;
530
531/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
532 demand), as they are encountered. This is for two reasons.
533
534 (1) (less important reason): Many original tmps are unused due to
535 initial IR optimisation, and we do not want to spaces in tables
536 tracking them.
537
538 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
539 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000540 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000541 It is necessary to support making multiple assignments to a shadow
542 -- specifically, after testing a shadow for definedness, it needs
543 to be made defined. But IR's SSA property disallows this.
544
545 (2) (more important reason): Therefore, when a shadow needs to get
546 a new value, a new temporary is created, the value is assigned to
547 that, and the tmpMap is updated to reflect the new binding.
548
549 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000550 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000551 there's a read-before-write error in the original tmps. The IR
552 sanity checker should catch all such anomalies, however.
553*/
554
555/* Find the tmp currently shadowing the given original tmp. If none
556 so far exists, allocate one. */
557static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
558{
sewardj69f9e3e2004-12-30 02:05:34 +0000559 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000560 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000561 mce->tmpMap[orig]
562 = newIRTemp(mce->bb->tyenv,
563 shadowType(mce->bb->tyenv->types[orig]));
564 }
565 return mce->tmpMap[orig];
566}
567
568/* Allocate a new shadow for the given original tmp. This means any
569 previous shadow is abandoned. This is needed because it is
570 necessary to give a new value to a shadow once it has been tested
571 for undefinedness, but unfortunately IR's SSA property disallows
572 this. Instead we must abandon the old shadow, allocate a new one
573 and use that instead. */
574static void newShadowTmp ( MCEnv* mce, IRTemp orig )
575{
sewardj69f9e3e2004-12-30 02:05:34 +0000576 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000577 mce->tmpMap[orig]
578 = newIRTemp(mce->bb->tyenv,
579 shadowType(mce->bb->tyenv->types[orig]));
580}
581
582
583/*------------------------------------------------------------*/
584/*--- IRAtoms -- a subset of IRExprs ---*/
585/*------------------------------------------------------------*/
586
587/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj496a58d2005-03-20 18:44:44 +0000588 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardjde8a5ae2004-11-06 14:20:54 +0000589 input, most of this code deals in atoms. Usefully, a value atom
590 always has a V-value which is also an atom: constants are shadowed
591 by constants, and temps are shadowed by the corresponding shadow
592 temporary. */
593
594typedef IRExpr IRAtom;
595
596/* (used for sanity checks only): is this an atom which looks
597 like it's from original code? */
598static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
599{
600 if (a1->tag == Iex_Const)
601 return True;
sewardj478646f2008-05-01 20:13:04 +0000602 if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < mce->n_originalTmps)
sewardjde8a5ae2004-11-06 14:20:54 +0000603 return True;
604 return False;
605}
606
607/* (used for sanity checks only): is this an atom which looks
608 like it's from shadow code? */
609static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
610{
611 if (a1->tag == Iex_Const)
612 return True;
sewardj478646f2008-05-01 20:13:04 +0000613 if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= mce->n_originalTmps)
sewardjde8a5ae2004-11-06 14:20:54 +0000614 return True;
615 return False;
616}
617
618/* (used for sanity checks only): check that both args are atoms and
619 are identically-kinded. */
620static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
621{
sewardj478646f2008-05-01 20:13:04 +0000622 if (a1->tag == Iex_RdTmp && a1->tag == Iex_RdTmp)
sewardjde8a5ae2004-11-06 14:20:54 +0000623 return True;
624 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
625 return True;
626 return False;
627}
628
629
630/*------------------------------------------------------------*/
631/*--- Type management ---*/
632/*------------------------------------------------------------*/
633
634/* Shadow state is always accessed using integer types. This returns
635 an integer type with the same size (as per sizeofIRType) as the
636 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000637 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000638
639static IRType shadowType ( IRType ty )
640{
641 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000642 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000643 case Ity_I8:
644 case Ity_I16:
645 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000646 case Ity_I64: return ty;
647 case Ity_F32: return Ity_I32;
648 case Ity_F64: return Ity_I64;
649 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000650 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000651 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000652 }
653}
654
655/* Produce a 'defined' value of the given shadow type. Should only be
656 supplied shadow types (Bit/I8/I16/I32/UI64). */
657static IRExpr* definedOfType ( IRType ty ) {
658 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000659 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
660 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
661 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
662 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
663 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
664 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
665 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000666 }
667}
668
669
670/*------------------------------------------------------------*/
671/*--- Constructing IR fragments ---*/
672/*------------------------------------------------------------*/
673
674/* assign value to tmp */
675#define assign(_bb,_tmp,_expr) \
sewardj478646f2008-05-01 20:13:04 +0000676 addStmtToIRSB((_bb), IRStmt_WrTmp((_tmp),(_expr)))
sewardjde8a5ae2004-11-06 14:20:54 +0000677
678/* add stmt to a bb */
679#define stmt(_bb,_stmt) \
sewardjf6c8ebf2007-02-06 01:52:52 +0000680 addStmtToIRSB((_bb), (_stmt))
sewardjde8a5ae2004-11-06 14:20:54 +0000681
682/* build various kinds of expressions */
683#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
684#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
685#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
686#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
687#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
688#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000689#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardj478646f2008-05-01 20:13:04 +0000690#define mkexpr(_tmp) IRExpr_RdTmp((_tmp))
sewardjde8a5ae2004-11-06 14:20:54 +0000691
692/* bind the given expression to a new temporary, and return the
693 temporary. This effectively converts an arbitrary expression into
694 an atom. */
695static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
696 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
697 assign(mce->bb, t, e);
698 return mkexpr(t);
699}
700
701
702/*------------------------------------------------------------*/
703/*--- Constructing definedness primitive ops ---*/
704/*------------------------------------------------------------*/
705
706/* --------- Defined-if-either-defined --------- */
707
708static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000709 tl_assert(isShadowAtom(mce,a1));
710 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000711 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
712}
713
714static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000715 tl_assert(isShadowAtom(mce,a1));
716 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000717 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
718}
719
720static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000721 tl_assert(isShadowAtom(mce,a1));
722 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000723 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
724}
725
sewardj69f9e3e2004-12-30 02:05:34 +0000726static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
727 tl_assert(isShadowAtom(mce,a1));
728 tl_assert(isShadowAtom(mce,a2));
729 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
730}
731
sewardjf0c1c582005-02-07 23:47:38 +0000732static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000733 tl_assert(isShadowAtom(mce,a1));
734 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000735 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000736}
737
sewardjde8a5ae2004-11-06 14:20:54 +0000738/* --------- Undefined-if-either-undefined --------- */
739
740static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000741 tl_assert(isShadowAtom(mce,a1));
742 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000743 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
744}
745
746static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000747 tl_assert(isShadowAtom(mce,a1));
748 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000749 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
750}
751
752static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000753 tl_assert(isShadowAtom(mce,a1));
754 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000755 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
756}
757
758static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000759 tl_assert(isShadowAtom(mce,a1));
760 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000761 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
762}
763
sewardjf0c1c582005-02-07 23:47:38 +0000764static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000765 tl_assert(isShadowAtom(mce,a1));
766 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000767 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000768}
769
770static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000771 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000772 case Ity_I8: return mkUifU8(mce, a1, a2);
773 case Ity_I16: return mkUifU16(mce, a1, a2);
774 case Ity_I32: return mkUifU32(mce, a1, a2);
775 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardjf0c1c582005-02-07 23:47:38 +0000776 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000777 default:
778 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000779 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000780 }
781}
782
783/* --------- The Left-family of operations. --------- */
784
785static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000786 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000787 /* It's safe to duplicate a1 since it's only an atom */
788 return assignNew(mce, Ity_I8,
789 binop(Iop_Or8, a1,
790 assignNew(mce, Ity_I8,
791 /* unop(Iop_Neg8, a1)))); */
792 binop(Iop_Sub8, mkU8(0), a1) )));
793}
794
795static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000796 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000797 /* It's safe to duplicate a1 since it's only an atom */
798 return assignNew(mce, Ity_I16,
799 binop(Iop_Or16, a1,
800 assignNew(mce, Ity_I16,
801 /* unop(Iop_Neg16, a1)))); */
802 binop(Iop_Sub16, mkU16(0), a1) )));
803}
804
805static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000806 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000807 /* It's safe to duplicate a1 since it's only an atom */
808 return assignNew(mce, Ity_I32,
809 binop(Iop_Or32, a1,
810 assignNew(mce, Ity_I32,
811 /* unop(Iop_Neg32, a1)))); */
812 binop(Iop_Sub32, mkU32(0), a1) )));
813}
814
815/* --------- 'Improvement' functions for AND/OR. --------- */
816
817/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
818 defined (0); all other -> undefined (1).
819*/
820static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
821{
sewardj69f9e3e2004-12-30 02:05:34 +0000822 tl_assert(isOriginalAtom(mce, data));
823 tl_assert(isShadowAtom(mce, vbits));
824 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000825 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
826}
827
sewardj3598ef92004-11-11 02:13:30 +0000828static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
829{
sewardj69f9e3e2004-12-30 02:05:34 +0000830 tl_assert(isOriginalAtom(mce, data));
831 tl_assert(isShadowAtom(mce, vbits));
832 tl_assert(sameKindedAtoms(data, vbits));
sewardj3598ef92004-11-11 02:13:30 +0000833 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
834}
835
sewardjde8a5ae2004-11-06 14:20:54 +0000836static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
837{
sewardj69f9e3e2004-12-30 02:05:34 +0000838 tl_assert(isOriginalAtom(mce, data));
839 tl_assert(isShadowAtom(mce, vbits));
840 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000841 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
842}
843
sewardj69f9e3e2004-12-30 02:05:34 +0000844static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
845{
846 tl_assert(isOriginalAtom(mce, data));
847 tl_assert(isShadowAtom(mce, vbits));
848 tl_assert(sameKindedAtoms(data, vbits));
849 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
850}
851
sewardjf0c1c582005-02-07 23:47:38 +0000852static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000853{
854 tl_assert(isOriginalAtom(mce, data));
855 tl_assert(isShadowAtom(mce, vbits));
856 tl_assert(sameKindedAtoms(data, vbits));
sewardjf0c1c582005-02-07 23:47:38 +0000857 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj69f9e3e2004-12-30 02:05:34 +0000858}
859
sewardjde8a5ae2004-11-06 14:20:54 +0000860/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
861 defined (0); all other -> undefined (1).
862*/
863static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
864{
sewardj69f9e3e2004-12-30 02:05:34 +0000865 tl_assert(isOriginalAtom(mce, data));
866 tl_assert(isShadowAtom(mce, vbits));
867 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000868 return assignNew(
869 mce, Ity_I8,
870 binop(Iop_Or8,
871 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
872 vbits) );
873}
874
875static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
876{
sewardj69f9e3e2004-12-30 02:05:34 +0000877 tl_assert(isOriginalAtom(mce, data));
878 tl_assert(isShadowAtom(mce, vbits));
879 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000880 return assignNew(
881 mce, Ity_I16,
882 binop(Iop_Or16,
883 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
884 vbits) );
885}
886
887static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
888{
sewardj69f9e3e2004-12-30 02:05:34 +0000889 tl_assert(isOriginalAtom(mce, data));
890 tl_assert(isShadowAtom(mce, vbits));
891 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000892 return assignNew(
893 mce, Ity_I32,
894 binop(Iop_Or32,
895 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
896 vbits) );
897}
898
sewardj69f9e3e2004-12-30 02:05:34 +0000899static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
900{
901 tl_assert(isOriginalAtom(mce, data));
902 tl_assert(isShadowAtom(mce, vbits));
903 tl_assert(sameKindedAtoms(data, vbits));
904 return assignNew(
905 mce, Ity_I64,
906 binop(Iop_Or64,
907 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
908 vbits) );
909}
910
sewardjf0c1c582005-02-07 23:47:38 +0000911static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000912{
913 tl_assert(isOriginalAtom(mce, data));
914 tl_assert(isShadowAtom(mce, vbits));
915 tl_assert(sameKindedAtoms(data, vbits));
916 return assignNew(
917 mce, Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +0000918 binop(Iop_OrV128,
919 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj69f9e3e2004-12-30 02:05:34 +0000920 vbits) );
921}
922
sewardjde8a5ae2004-11-06 14:20:54 +0000923/* --------- Pessimising casts. --------- */
924
925static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
926{
sewardj8fc93742004-11-22 11:29:33 +0000927 IRType ty;
928 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000929 /* Note, dst_ty is a shadow type, not an original type. */
930 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000931 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000932 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
933 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000934 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000935 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000936 tmp1 = vbits;
937 break;
938 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000939 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000940 break;
941 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000942 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000943 break;
944 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000945 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000946 break;
947 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000948 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000949 break;
950 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000951 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000952 }
sewardj69f9e3e2004-12-30 02:05:34 +0000953 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000954 /* Now widen up to the dst type. */
955 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000956 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000957 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000958 case Ity_I8:
959 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000960 case Ity_I16:
961 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
962 case Ity_I32:
963 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
964 case Ity_I64:
965 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000966 case Ity_V128:
967 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardjf0c1c582005-02-07 23:47:38 +0000968 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000969 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000970 default:
971 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000972 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +0000973 }
974}
975
976
977/*------------------------------------------------------------*/
978/*--- Emit a test and complaint if something is undefined. ---*/
979/*------------------------------------------------------------*/
980
981/* Set the annotations on a dirty helper to indicate that the stack
982 pointer and instruction pointers might be read. This is the
983 behaviour of all 'emit-a-complaint' style functions we might
984 call. */
985
986static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
987 di->nFxState = 2;
988 di->fxState[0].fx = Ifx_Read;
989 di->fxState[0].offset = mce->layout->offset_SP;
990 di->fxState[0].size = mce->layout->sizeof_SP;
991 di->fxState[1].fx = Ifx_Read;
992 di->fxState[1].offset = mce->layout->offset_IP;
993 di->fxState[1].size = mce->layout->sizeof_IP;
994}
995
996
997/* Check the supplied **original** atom for undefinedness, and emit a
998 complaint if so. Once that happens, mark it as defined. This is
999 possible because the atom is either a tmp or literal. If it's a
1000 tmp, it will be shadowed by a tmp, and so we can set the shadow to
1001 be defined. In fact as mentioned above, we will have to allocate a
1002 new tmp to carry the new 'defined' shadow value, and update the
1003 original->tmp mapping accordingly; we cannot simply assign a new
1004 value to an existing shadow tmp as this breaks SSAness -- resulting
1005 in the post-instrumentation sanity checker spluttering in disapproval.
1006*/
1007static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
1008{
sewardj8fc93742004-11-22 11:29:33 +00001009 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001010 IRType ty;
1011 Int sz;
sewardj8fc93742004-11-22 11:29:33 +00001012 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +00001013 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +00001014
sewardjde8a5ae2004-11-06 14:20:54 +00001015 /* Since the original expression is atomic, there's no duplicated
1016 work generated by making multiple V-expressions for it. So we
1017 don't really care about the possibility that someone else may
1018 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +00001019 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +00001020 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001021 tl_assert(isShadowAtom(mce, vatom));
1022 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001023
sewardj8fc93742004-11-22 11:29:33 +00001024 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +00001025
1026 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +00001027 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +00001028
sewardj8fc93742004-11-22 11:29:33 +00001029 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +00001030 /* cond will be 0 if all defined, and 1 if any not defined. */
1031
sewardj3598ef92004-11-11 02:13:30 +00001032 switch (sz) {
1033 case 0:
1034 di = unsafeIRDirty_0_N( 0/*regparms*/,
1035 "MC_(helperc_value_check0_fail)",
1036 &MC_(helperc_value_check0_fail),
1037 mkIRExprVec_0()
1038 );
1039 break;
1040 case 1:
1041 di = unsafeIRDirty_0_N( 0/*regparms*/,
1042 "MC_(helperc_value_check1_fail)",
1043 &MC_(helperc_value_check1_fail),
1044 mkIRExprVec_0()
1045 );
1046 break;
1047 case 4:
1048 di = unsafeIRDirty_0_N( 0/*regparms*/,
1049 "MC_(helperc_value_check4_fail)",
1050 &MC_(helperc_value_check4_fail),
1051 mkIRExprVec_0()
1052 );
1053 break;
1054 default:
1055 di = unsafeIRDirty_0_N( 1/*regparms*/,
1056 "MC_(helperc_complain_undef)",
1057 &MC_(helperc_complain_undef),
1058 mkIRExprVec_1( mkIRExpr_HWord( sz ))
1059 );
1060 break;
1061 }
sewardjde8a5ae2004-11-06 14:20:54 +00001062 di->guard = cond;
1063 setHelperAnns( mce, di );
1064 stmt( mce->bb, IRStmt_Dirty(di));
1065
1066 /* Set the shadow tmp to be defined. First, update the
1067 orig->shadow tmp mapping to reflect the fact that this shadow is
1068 getting a new value. */
sewardj496a58d2005-03-20 18:44:44 +00001069 tl_assert(isIRAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001070 /* sameKindedAtoms ... */
sewardj478646f2008-05-01 20:13:04 +00001071 if (vatom->tag == Iex_RdTmp) {
1072 tl_assert(atom->tag == Iex_RdTmp);
1073 newShadowTmp(mce, atom->Iex.RdTmp.tmp);
1074 assign(mce->bb, findShadowTmp(mce, atom->Iex.RdTmp.tmp),
sewardjde8a5ae2004-11-06 14:20:54 +00001075 definedOfType(ty));
1076 }
1077}
1078
1079
1080/*------------------------------------------------------------*/
1081/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
1082/*------------------------------------------------------------*/
1083
1084/* Examine the always-defined sections declared in layout to see if
1085 the (offset,size) section is within one. Note, is is an error to
1086 partially fall into such a region: (offset,size) should either be
1087 completely in such a region or completely not-in such a region.
1088*/
1089static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1090{
1091 Int minoffD, maxoffD, i;
1092 Int minoff = offset;
1093 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001094 tl_assert((minoff & ~0xFFFF) == 0);
1095 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001096
1097 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1098 minoffD = mce->layout->alwaysDefd[i].offset;
1099 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001100 tl_assert((minoffD & ~0xFFFF) == 0);
1101 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001102
1103 if (maxoff < minoffD || maxoffD < minoff)
1104 continue; /* no overlap */
1105 if (minoff >= minoffD && maxoff <= maxoffD)
1106 return True; /* completely contained in an always-defd section */
1107
sewardj69f9e3e2004-12-30 02:05:34 +00001108 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001109 }
1110 return False; /* could not find any containing section */
1111}
1112
1113
1114/* Generate into bb suitable actions to shadow this Put. If the state
1115 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001116 supplied V bits to the shadow state. We can pass in either an
1117 original atom or a V-atom, but not both. In the former case the
1118 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001119*/
1120static
sewardj3598ef92004-11-11 02:13:30 +00001121void do_shadow_PUT ( MCEnv* mce, Int offset,
1122 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001123{
sewardj8fc93742004-11-22 11:29:33 +00001124 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001125 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001126 tl_assert(!vatom);
1127 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001128 vatom = expr2vbits( mce, atom );
1129 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001130 tl_assert(vatom);
1131 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001132 }
1133
sewardj8fc93742004-11-22 11:29:33 +00001134 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001135 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001136 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1137 /* later: no ... */
1138 /* emit code to emit a complaint if any of the vbits are 1. */
1139 /* complainIfUndefined(mce, atom); */
1140 } else {
1141 /* Do a plain shadow Put. */
1142 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1143 }
1144}
1145
1146
1147/* Return an expression which contains the V bits corresponding to the
1148 given GETI (passed in in pieces).
1149*/
1150static
1151void do_shadow_PUTI ( MCEnv* mce,
sewardj478646f2008-05-01 20:13:04 +00001152 IRRegArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
sewardjde8a5ae2004-11-06 14:20:54 +00001153{
sewardj8fc93742004-11-22 11:29:33 +00001154 IRAtom* vatom;
1155 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001156 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001157
sewardj69f9e3e2004-12-30 02:05:34 +00001158 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001159 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001160 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001161 ty = descr->elemTy;
1162 tyS = shadowType(ty);
1163 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001164 tl_assert(ty != Ity_I1);
1165 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001166 complainIfUndefined(mce,ix);
1167 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1168 /* later: no ... */
1169 /* emit code to emit a complaint if any of the vbits are 1. */
1170 /* complainIfUndefined(mce, atom); */
1171 } else {
1172 /* Do a cloned version of the Put that refers to the shadow
1173 area. */
sewardj478646f2008-05-01 20:13:04 +00001174 IRRegArray* new_descr
1175 = mkIRRegArray( descr->base + mce->layout->total_sizeB,
sewardjde8a5ae2004-11-06 14:20:54 +00001176 tyS, descr->nElems);
1177 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1178 }
1179}
1180
1181
1182/* Return an expression which contains the V bits corresponding to the
1183 given GET (passed in in pieces).
1184*/
1185static
1186IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1187{
1188 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001189 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001190 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1191 /* Always defined, return all zeroes of the relevant type */
1192 return definedOfType(tyS);
1193 } else {
1194 /* return a cloned version of the Get that refers to the shadow
1195 area. */
1196 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1197 }
1198}
1199
1200
1201/* Return an expression which contains the V bits corresponding to the
1202 given GETI (passed in in pieces).
1203*/
1204static
sewardj478646f2008-05-01 20:13:04 +00001205IRExpr* shadow_GETI ( MCEnv* mce, IRRegArray* descr, IRAtom* ix, Int bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001206{
1207 IRType ty = descr->elemTy;
1208 IRType tyS = shadowType(ty);
1209 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001210 tl_assert(ty != Ity_I1);
1211 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001212 complainIfUndefined(mce,ix);
1213 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1214 /* Always defined, return all zeroes of the relevant type */
1215 return definedOfType(tyS);
1216 } else {
1217 /* return a cloned version of the Get that refers to the shadow
1218 area. */
sewardj478646f2008-05-01 20:13:04 +00001219 IRRegArray* new_descr
1220 = mkIRRegArray( descr->base + mce->layout->total_sizeB,
sewardjde8a5ae2004-11-06 14:20:54 +00001221 tyS, descr->nElems);
1222 return IRExpr_GetI( new_descr, ix, bias );
1223 }
1224}
1225
1226
1227/*------------------------------------------------------------*/
1228/*--- Generating approximations for unknown operations, ---*/
1229/*--- using lazy-propagate semantics ---*/
1230/*------------------------------------------------------------*/
1231
1232/* Lazy propagation of undefinedness from two values, resulting in the
1233 specified shadow type.
1234*/
1235static
1236IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1237{
1238 /* force everything via 32-bit intermediaries. */
1239 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001240 tl_assert(isShadowAtom(mce,va1));
1241 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001242 at = mkPCastTo(mce, Ity_I32, va1);
1243 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1244 at = mkPCastTo(mce, finalVty, at);
1245 return at;
1246}
1247
1248
1249/* Do the lazy propagation game from a null-terminated vector of
1250 atoms. This is presumably the arguments to a helper call, so the
1251 IRCallee info is also supplied in order that we can know which
1252 arguments should be ignored (via the .mcx_mask field).
1253*/
1254static
1255IRAtom* mkLazyN ( MCEnv* mce,
1256 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1257{
1258 Int i;
1259 IRAtom* here;
1260 IRAtom* curr = definedOfType(Ity_I32);
1261 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001262 tl_assert(i < 32);
1263 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001264 /* Only take notice of this arg if the callee's mc-exclusion
1265 mask does not say it is to be excluded. */
1266 if (cee->mcx_mask & (1<<i)) {
1267 /* the arg is to be excluded from definedness checking. Do
1268 nothing. */
1269 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1270 } else {
1271 /* calculate the arg's definedness, and pessimistically merge
1272 it in. */
1273 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1274 curr = mkUifU32(mce, here, curr);
1275 }
1276 }
1277 return mkPCastTo(mce, finalVtype, curr );
1278}
1279
1280
1281/*------------------------------------------------------------*/
1282/*--- Generating expensive sequences for exact carry-chain ---*/
1283/*--- propagation in add/sub and related operations. ---*/
1284/*------------------------------------------------------------*/
1285
1286static
1287IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1288 IRAtom* aa, IRAtom* bb )
1289{
sewardj69f9e3e2004-12-30 02:05:34 +00001290 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001291 IRType ty;
1292 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001293
sewardj69f9e3e2004-12-30 02:05:34 +00001294 tl_assert(isShadowAtom(mce,qaa));
1295 tl_assert(isShadowAtom(mce,qbb));
1296 tl_assert(isOriginalAtom(mce,aa));
1297 tl_assert(isOriginalAtom(mce,bb));
1298 tl_assert(sameKindedAtoms(qaa,aa));
1299 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001300
sewardj8fc93742004-11-22 11:29:33 +00001301 ty = Ity_I32;
1302 opAND = Iop_And32;
1303 opOR = Iop_Or32;
1304 opXOR = Iop_Xor32;
1305 opNOT = Iop_Not32;
1306 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001307
1308 // a_min = aa & ~qaa
1309 a_min = assignNew(mce,ty,
1310 binop(opAND, aa,
1311 assignNew(mce,ty, unop(opNOT, qaa))));
1312
1313 // b_min = bb & ~qbb
1314 b_min = assignNew(mce,ty,
1315 binop(opAND, bb,
1316 assignNew(mce,ty, unop(opNOT, qbb))));
1317
1318 // a_max = aa | qaa
1319 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1320
1321 // b_max = bb | qbb
1322 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1323
1324 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1325 return
1326 assignNew(mce,ty,
1327 binop( opOR,
1328 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1329 assignNew(mce,ty,
1330 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1331 assignNew(mce,ty, binop(opADD, a_max, b_max))
1332 )
1333 )
1334 )
1335 );
1336}
1337
1338
1339/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001340/*--- Helpers for dealing with vector primops. ---*/
1341/*------------------------------------------------------------*/
1342
1343/* Vector pessimisation -- pessimise within each lane individually. */
1344
1345static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1346{
1347 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1348}
1349
1350static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1351{
1352 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1353}
1354
1355static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1356{
1357 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1358}
1359
1360static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1361{
1362 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1363}
1364
1365
1366/* Here's a simple scheme capable of handling ops derived from SSE1
1367 code and while only generating ops that can be efficiently
1368 implemented in SSE1. */
1369
1370/* All-lanes versions are straightforward:
1371
sewardjf0c1c582005-02-07 23:47:38 +00001372 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj69f9e3e2004-12-30 02:05:34 +00001373
1374 unary32Fx4(x,y) ==> PCast32x4(x#)
1375
1376 Lowest-lane-only versions are more complex:
1377
sewardjf0c1c582005-02-07 23:47:38 +00001378 binary32F0x4(x,y) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001379 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001380 PCast32(V128to32(UifUV128(x#,y#)))
sewardj69f9e3e2004-12-30 02:05:34 +00001381 )
1382
1383 This is perhaps not so obvious. In particular, it's faster to
sewardjf0c1c582005-02-07 23:47:38 +00001384 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj69f9e3e2004-12-30 02:05:34 +00001385 obvious scheme of taking the bottom 32 bits of each operand
1386 and doing a 32-bit UifU. Basically since UifU is fast and
1387 chopping lanes off vector values is slow.
1388
1389 Finally:
1390
sewardjf0c1c582005-02-07 23:47:38 +00001391 unary32F0x4(x) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001392 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001393 PCast32(V128to32(x#))
sewardj69f9e3e2004-12-30 02:05:34 +00001394 )
1395
1396 Where:
1397
1398 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1399 PCast32x4(v#) = CmpNEZ32x4(v#)
1400*/
1401
1402static
1403IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1404{
1405 IRAtom* at;
1406 tl_assert(isShadowAtom(mce, vatomX));
1407 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001408 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001409 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1410 return at;
1411}
1412
1413static
1414IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1415{
1416 IRAtom* at;
1417 tl_assert(isShadowAtom(mce, vatomX));
1418 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1419 return at;
1420}
1421
1422static
1423IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1424{
1425 IRAtom* at;
1426 tl_assert(isShadowAtom(mce, vatomX));
1427 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001428 at = mkUifUV128(mce, vatomX, vatomY);
1429 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001430 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001431 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001432 return at;
1433}
1434
1435static
1436IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1437{
1438 IRAtom* at;
1439 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001440 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001441 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001442 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001443 return at;
1444}
1445
1446/* --- ... and ... 64Fx2 versions of the same ... --- */
1447
1448static
1449IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1450{
1451 IRAtom* at;
1452 tl_assert(isShadowAtom(mce, vatomX));
1453 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001454 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001455 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1456 return at;
1457}
1458
1459static
1460IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1461{
1462 IRAtom* at;
1463 tl_assert(isShadowAtom(mce, vatomX));
1464 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1465 return at;
1466}
1467
1468static
1469IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1470{
1471 IRAtom* at;
1472 tl_assert(isShadowAtom(mce, vatomX));
1473 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001474 at = mkUifUV128(mce, vatomX, vatomY);
1475 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001476 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001477 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001478 return at;
1479}
1480
1481static
1482IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1483{
1484 IRAtom* at;
1485 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001486 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001487 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001488 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001489 return at;
1490}
1491
1492/* --- --- Vector saturated narrowing --- --- */
1493
1494/* This is quite subtle. What to do is simple:
1495
1496 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1497
1498 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1499
1500 Why this is right is not so simple. Consider a lane in the args,
1501 vatom1 or 2, doesn't matter.
1502
1503 After the PCast, that lane is all 0s (defined) or all
1504 1s(undefined).
1505
1506 Both signed and unsigned saturating narrowing of all 0s produces
1507 all 0s, which is what we want.
1508
1509 The all-1s case is more complex. Unsigned narrowing interprets an
1510 all-1s input as the largest unsigned integer, and so produces all
1511 1s as a result since that is the largest unsigned value at the
1512 smaller width.
1513
1514 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1515 to -1, so we still wind up with all 1s at the smaller width.
1516
1517 So: In short, pessimise the args, then apply the original narrowing
1518 op.
1519*/
1520static
sewardjf0c1c582005-02-07 23:47:38 +00001521IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardj69f9e3e2004-12-30 02:05:34 +00001522 IRAtom* vatom1, IRAtom* vatom2)
1523{
1524 IRAtom *at1, *at2, *at3;
1525 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1526 switch (narrow_op) {
1527 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1528 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1529 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardjf0c1c582005-02-07 23:47:38 +00001530 default: VG_(tool_panic)("vectorNarrowV128");
sewardj69f9e3e2004-12-30 02:05:34 +00001531 }
1532 tl_assert(isShadowAtom(mce,vatom1));
1533 tl_assert(isShadowAtom(mce,vatom2));
1534 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1535 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1536 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1537 return at3;
1538}
1539
1540
1541/* --- --- Vector integer arithmetic --- --- */
1542
1543/* Simple ... UifU the args and per-lane pessimise the results. */
1544static
1545IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1546{
1547 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001548 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001549 at = mkPCast8x16(mce, at);
1550 return at;
1551}
1552
1553static
1554IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1555{
1556 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001557 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001558 at = mkPCast16x8(mce, at);
1559 return at;
1560}
1561
1562static
1563IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1564{
1565 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001566 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001567 at = mkPCast32x4(mce, at);
1568 return at;
1569}
1570
1571static
1572IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1573{
1574 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001575 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001576 at = mkPCast64x2(mce, at);
1577 return at;
1578}
1579
1580
1581/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001582/*--- Generate shadow values from all kinds of IRExprs. ---*/
1583/*------------------------------------------------------------*/
1584
1585static
1586IRAtom* expr2vbits_Binop ( MCEnv* mce,
1587 IROp op,
1588 IRAtom* atom1, IRAtom* atom2 )
1589{
1590 IRType and_or_ty;
1591 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1592 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1593 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1594
1595 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1596 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1597
sewardj69f9e3e2004-12-30 02:05:34 +00001598 tl_assert(isOriginalAtom(mce,atom1));
1599 tl_assert(isOriginalAtom(mce,atom2));
1600 tl_assert(isShadowAtom(mce,vatom1));
1601 tl_assert(isShadowAtom(mce,vatom2));
1602 tl_assert(sameKindedAtoms(atom1,vatom1));
1603 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001604 switch (op) {
1605
sewardjf0c1c582005-02-07 23:47:38 +00001606 /* V128-bit SIMD (SSE2-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001607
1608 case Iop_ShrN16x8:
1609 case Iop_ShrN32x4:
1610 case Iop_ShrN64x2:
1611 case Iop_SarN16x8:
1612 case Iop_SarN32x4:
1613 case Iop_ShlN16x8:
1614 case Iop_ShlN32x4:
1615 case Iop_ShlN64x2:
1616 /* Same scheme as with all other shifts. */
1617 complainIfUndefined(mce, atom2);
1618 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1619
1620 case Iop_QSub8Ux16:
1621 case Iop_QSub8Sx16:
1622 case Iop_Sub8x16:
1623 case Iop_Min8Ux16:
1624 case Iop_Max8Ux16:
1625 case Iop_CmpGT8Sx16:
1626 case Iop_CmpEQ8x16:
1627 case Iop_Avg8Ux16:
1628 case Iop_QAdd8Ux16:
1629 case Iop_QAdd8Sx16:
1630 case Iop_Add8x16:
1631 return binary8Ix16(mce, vatom1, vatom2);
1632
1633 case Iop_QSub16Ux8:
1634 case Iop_QSub16Sx8:
1635 case Iop_Sub16x8:
1636 case Iop_Mul16x8:
1637 case Iop_MulHi16Sx8:
1638 case Iop_MulHi16Ux8:
1639 case Iop_Min16Sx8:
1640 case Iop_Max16Sx8:
1641 case Iop_CmpGT16Sx8:
1642 case Iop_CmpEQ16x8:
1643 case Iop_Avg16Ux8:
1644 case Iop_QAdd16Ux8:
1645 case Iop_QAdd16Sx8:
1646 case Iop_Add16x8:
1647 return binary16Ix8(mce, vatom1, vatom2);
1648
1649 case Iop_Sub32x4:
sewardj2fdd4162010-08-22 12:59:02 +00001650 case Iop_QSub32Sx4:
1651 case Iop_QSub32Ux4:
sewardj69f9e3e2004-12-30 02:05:34 +00001652 case Iop_CmpGT32Sx4:
1653 case Iop_CmpEQ32x4:
1654 case Iop_Add32x4:
sewardj2fdd4162010-08-22 12:59:02 +00001655 case Iop_QAdd32Ux4:
1656 case Iop_QAdd32Sx4:
sewardj69f9e3e2004-12-30 02:05:34 +00001657 return binary32Ix4(mce, vatom1, vatom2);
1658
1659 case Iop_Sub64x2:
sewardj2fdd4162010-08-22 12:59:02 +00001660 case Iop_QSub64Ux2:
1661 case Iop_QSub64Sx2:
sewardj69f9e3e2004-12-30 02:05:34 +00001662 case Iop_Add64x2:
sewardj2fdd4162010-08-22 12:59:02 +00001663 case Iop_QAdd64Ux2:
1664 case Iop_QAdd64Sx2:
sewardj69f9e3e2004-12-30 02:05:34 +00001665 return binary64Ix2(mce, vatom1, vatom2);
1666
1667 case Iop_QNarrow32Sx4:
1668 case Iop_QNarrow16Sx8:
1669 case Iop_QNarrow16Ux8:
sewardjf0c1c582005-02-07 23:47:38 +00001670 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001671
1672 case Iop_Sub64Fx2:
1673 case Iop_Mul64Fx2:
1674 case Iop_Min64Fx2:
1675 case Iop_Max64Fx2:
1676 case Iop_Div64Fx2:
1677 case Iop_CmpLT64Fx2:
1678 case Iop_CmpLE64Fx2:
1679 case Iop_CmpEQ64Fx2:
1680 case Iop_Add64Fx2:
1681 return binary64Fx2(mce, vatom1, vatom2);
1682
1683 case Iop_Sub64F0x2:
1684 case Iop_Mul64F0x2:
1685 case Iop_Min64F0x2:
1686 case Iop_Max64F0x2:
1687 case Iop_Div64F0x2:
1688 case Iop_CmpLT64F0x2:
1689 case Iop_CmpLE64F0x2:
1690 case Iop_CmpEQ64F0x2:
1691 case Iop_Add64F0x2:
1692 return binary64F0x2(mce, vatom1, vatom2);
1693
sewardjf0c1c582005-02-07 23:47:38 +00001694 /* V128-bit SIMD (SSE1-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001695
1696 case Iop_Sub32Fx4:
1697 case Iop_Mul32Fx4:
1698 case Iop_Min32Fx4:
1699 case Iop_Max32Fx4:
1700 case Iop_Div32Fx4:
1701 case Iop_CmpLT32Fx4:
1702 case Iop_CmpLE32Fx4:
1703 case Iop_CmpEQ32Fx4:
1704 case Iop_Add32Fx4:
1705 return binary32Fx4(mce, vatom1, vatom2);
1706
1707 case Iop_Sub32F0x4:
1708 case Iop_Mul32F0x4:
1709 case Iop_Min32F0x4:
1710 case Iop_Max32F0x4:
1711 case Iop_Div32F0x4:
1712 case Iop_CmpLT32F0x4:
1713 case Iop_CmpLE32F0x4:
1714 case Iop_CmpEQ32F0x4:
1715 case Iop_Add32F0x4:
1716 return binary32F0x4(mce, vatom1, vatom2);
1717
sewardjf0c1c582005-02-07 23:47:38 +00001718 /* V128-bit data-steering */
1719 case Iop_SetV128lo32:
1720 case Iop_SetV128lo64:
1721 case Iop_64HLtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001722 case Iop_InterleaveLO64x2:
1723 case Iop_InterleaveLO32x4:
1724 case Iop_InterleaveLO16x8:
1725 case Iop_InterleaveLO8x16:
1726 case Iop_InterleaveHI64x2:
1727 case Iop_InterleaveHI32x4:
1728 case Iop_InterleaveHI16x8:
1729 case Iop_InterleaveHI8x16:
1730 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1731
1732 /* Scalar floating point */
1733
sewardj478646f2008-05-01 20:13:04 +00001734 // case Iop_RoundF64:
sewardj1e3830f2011-03-14 11:27:26 +00001735 case Iop_F64toI64S:
1736 case Iop_I64StoF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001737 /* First arg is I32 (rounding mode), second is F64 or I64
1738 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001739 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1740
1741 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1742 /* Takes two F64 args. */
sewardj1e3830f2011-03-14 11:27:26 +00001743 case Iop_F64toI32S:
sewardj69f9e3e2004-12-30 02:05:34 +00001744 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001745 /* First arg is I32 (rounding mode), second is F64 (data). */
1746 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1747
sewardj1e3830f2011-03-14 11:27:26 +00001748 case Iop_F64toI16S:
sewardjde8a5ae2004-11-06 14:20:54 +00001749 /* First arg is I32 (rounding mode), second is F64 (data). */
1750 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1751
sewardj3598ef92004-11-11 02:13:30 +00001752 case Iop_ScaleF64:
1753 case Iop_Yl2xF64:
1754 case Iop_Yl2xp1F64:
1755 case Iop_PRemF64:
1756 case Iop_AtanF64:
1757 case Iop_AddF64:
1758 case Iop_DivF64:
1759 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001760 case Iop_MulF64:
1761 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1762
sewardj3598ef92004-11-11 02:13:30 +00001763 case Iop_CmpF64:
1764 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1765
sewardjde8a5ae2004-11-06 14:20:54 +00001766 /* non-FP after here */
1767
1768 case Iop_DivModU64to32:
1769 case Iop_DivModS64to32:
1770 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1771
sewardj3598ef92004-11-11 02:13:30 +00001772 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001773 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001774 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001775 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001776
1777 case Iop_MullS32:
1778 case Iop_MullU32: {
1779 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1780 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1781 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1782 }
1783
sewardj3598ef92004-11-11 02:13:30 +00001784 case Iop_MullS16:
1785 case Iop_MullU16: {
1786 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1787 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1788 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1789 }
1790
1791 case Iop_MullS8:
1792 case Iop_MullU8: {
1793 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1794 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1795 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1796 }
1797
sewardjde8a5ae2004-11-06 14:20:54 +00001798 case Iop_Add32:
1799# if 0
1800 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1801# endif
1802 case Iop_Sub32:
1803 case Iop_Mul32:
1804 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1805
sewardj3598ef92004-11-11 02:13:30 +00001806 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001807 case Iop_Add16:
1808 case Iop_Sub16:
1809 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1810
1811 case Iop_Sub8:
1812 case Iop_Add8:
1813 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1814
1815 case Iop_CmpLE32S: case Iop_CmpLE32U:
1816 case Iop_CmpLT32U: case Iop_CmpLT32S:
1817 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001818 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001819
sewardj3598ef92004-11-11 02:13:30 +00001820 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001821 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001822
1823 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001824 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001825
1826 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1827 /* Complain if the shift amount is undefined. Then simply
1828 shift the first arg's V bits by the real shift amount. */
1829 complainIfUndefined(mce, atom2);
1830 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1831
sewardj69f9e3e2004-12-30 02:05:34 +00001832 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001833 /* Same scheme as with 32-bit shifts. */
1834 complainIfUndefined(mce, atom2);
1835 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1836
sewardj3598ef92004-11-11 02:13:30 +00001837 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001838 /* Same scheme as with 32-bit shifts. */
1839 complainIfUndefined(mce, atom2);
1840 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1841
1842 case Iop_Shl64: case Iop_Shr64:
1843 /* Same scheme as with 32-bit shifts. */
1844 complainIfUndefined(mce, atom2);
1845 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1846
sewardjf0c1c582005-02-07 23:47:38 +00001847 case Iop_AndV128:
1848 uifu = mkUifUV128; difd = mkDifDV128;
1849 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001850 case Iop_And64:
1851 uifu = mkUifU64; difd = mkDifD64;
1852 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001853 case Iop_And32:
1854 uifu = mkUifU32; difd = mkDifD32;
1855 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001856 case Iop_And16:
1857 uifu = mkUifU16; difd = mkDifD16;
1858 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001859 case Iop_And8:
1860 uifu = mkUifU8; difd = mkDifD8;
1861 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1862
sewardjf0c1c582005-02-07 23:47:38 +00001863 case Iop_OrV128:
1864 uifu = mkUifUV128; difd = mkDifDV128;
1865 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001866 case Iop_Or64:
1867 uifu = mkUifU64; difd = mkDifD64;
1868 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001869 case Iop_Or32:
1870 uifu = mkUifU32; difd = mkDifD32;
1871 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1872 case Iop_Or16:
1873 uifu = mkUifU16; difd = mkDifD16;
1874 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1875 case Iop_Or8:
1876 uifu = mkUifU8; difd = mkDifD8;
1877 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1878
1879 do_And_Or:
1880 return
1881 assignNew(
1882 mce,
1883 and_or_ty,
1884 difd(mce, uifu(mce, vatom1, vatom2),
1885 difd(mce, improve(mce, atom1, vatom1),
1886 improve(mce, atom2, vatom2) ) ) );
1887
1888 case Iop_Xor8:
1889 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001890 case Iop_Xor16:
1891 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001892 case Iop_Xor32:
1893 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001894 case Iop_Xor64:
1895 return mkUifU64(mce, vatom1, vatom2);
sewardjf0c1c582005-02-07 23:47:38 +00001896 case Iop_XorV128:
1897 return mkUifUV128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001898
1899 default:
1900 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001901 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001902 }
1903}
1904
1905
1906static
1907IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1908{
1909 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001910 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001911 switch (op) {
1912
sewardj69f9e3e2004-12-30 02:05:34 +00001913 case Iop_Sqrt64Fx2:
1914 return unary64Fx2(mce, vatom);
1915
1916 case Iop_Sqrt64F0x2:
1917 return unary64F0x2(mce, vatom);
1918
1919 case Iop_Sqrt32Fx4:
1920 case Iop_RSqrt32Fx4:
1921 case Iop_Recip32Fx4:
1922 return unary32Fx4(mce, vatom);
1923
1924 case Iop_Sqrt32F0x4:
1925 case Iop_RSqrt32F0x4:
1926 case Iop_Recip32F0x4:
1927 return unary32F0x4(mce, vatom);
1928
sewardjf0c1c582005-02-07 23:47:38 +00001929 case Iop_32UtoV128:
1930 case Iop_64UtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001931 return assignNew(mce, Ity_V128, unop(op, vatom));
1932
sewardjde8a5ae2004-11-06 14:20:54 +00001933 case Iop_F32toF64:
sewardj1e3830f2011-03-14 11:27:26 +00001934 case Iop_I32StoF64:
sewardj3598ef92004-11-11 02:13:30 +00001935 case Iop_NegF64:
1936 case Iop_SinF64:
1937 case Iop_CosF64:
1938 case Iop_TanF64:
1939 case Iop_SqrtF64:
1940 case Iop_AbsF64:
1941 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001942 return mkPCastTo(mce, Ity_I64, vatom);
1943
sewardj3598ef92004-11-11 02:13:30 +00001944 case Iop_Clz32:
1945 case Iop_Ctz32:
1946 return mkPCastTo(mce, Ity_I32, vatom);
1947
1948 case Iop_32Sto64:
1949 case Iop_32Uto64:
sewardjf0c1c582005-02-07 23:47:38 +00001950 case Iop_V128to64:
1951 case Iop_V128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001952 return assignNew(mce, Ity_I64, unop(op, vatom));
1953
sewardjde8a5ae2004-11-06 14:20:54 +00001954 case Iop_64to32:
1955 case Iop_64HIto32:
1956 case Iop_1Uto32:
1957 case Iop_8Uto32:
1958 case Iop_16Uto32:
1959 case Iop_16Sto32:
1960 case Iop_8Sto32:
1961 return assignNew(mce, Ity_I32, unop(op, vatom));
1962
1963 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001964 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001965 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001966 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001967 return assignNew(mce, Ity_I16, unop(op, vatom));
1968
1969 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001970 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001971 case Iop_32to8:
1972 return assignNew(mce, Ity_I8, unop(op, vatom));
1973
1974 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001975 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001976
sewardj3598ef92004-11-11 02:13:30 +00001977 case Iop_ReinterpF64asI64:
1978 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001979 case Iop_ReinterpI32asF32:
sewardjf0c1c582005-02-07 23:47:38 +00001980 case Iop_NotV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001981 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00001982 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001983 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001984 case Iop_Not8:
1985 case Iop_Not1:
1986 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001987
sewardjde8a5ae2004-11-06 14:20:54 +00001988 default:
1989 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001990 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00001991 }
1992}
1993
1994
sewardj69f9e3e2004-12-30 02:05:34 +00001995/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00001996static
sewardj69f9e3e2004-12-30 02:05:34 +00001997IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001998{
1999 void* helper;
sewardjde8c9872005-03-25 13:48:55 +00002000 HChar* hname;
sewardjde8a5ae2004-11-06 14:20:54 +00002001 IRDirty* di;
2002 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00002003 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00002004
sewardj69f9e3e2004-12-30 02:05:34 +00002005 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00002006
2007 /* First, emit a definedness test for the address. This also sets
2008 the address (shadow) to 'defined' following the test. */
2009 complainIfUndefined( mce, addr );
2010
2011 /* Now cook up a call to the relevant helper function, to read the
2012 data V bits from shadow memory. */
2013 ty = shadowType(ty);
2014 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00002015 case Ity_I64: helper = &MC_(helperc_LOADV8);
2016 hname = "MC_(helperc_LOADV8)";
2017 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002018 case Ity_I32: helper = &MC_(helperc_LOADV4);
2019 hname = "MC_(helperc_LOADV4)";
2020 break;
2021 case Ity_I16: helper = &MC_(helperc_LOADV2);
2022 hname = "MC_(helperc_LOADV2)";
2023 break;
2024 case Ity_I8: helper = &MC_(helperc_LOADV1);
2025 hname = "MC_(helperc_LOADV1)";
2026 break;
2027 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00002028 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00002029 }
2030
sewardj3598ef92004-11-11 02:13:30 +00002031 /* Generate the actual address into addrAct. */
2032 if (bias == 0) {
2033 addrAct = addr;
2034 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002035 IROp mkAdd;
2036 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00002037 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00002038 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2039 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2040 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00002041 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2042 }
2043
sewardjde8a5ae2004-11-06 14:20:54 +00002044 /* We need to have a place to park the V bits we're just about to
2045 read. */
2046 datavbits = newIRTemp(mce->bb->tyenv, ty);
2047 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00002048 1/*regparms*/, hname, helper,
2049 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00002050 setHelperAnns( mce, di );
2051 stmt( mce->bb, IRStmt_Dirty(di) );
2052
2053 return mkexpr(datavbits);
2054}
2055
2056
2057static
sewardj69f9e3e2004-12-30 02:05:34 +00002058IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
2059{
2060 IRAtom *v64hi, *v64lo;
2061 switch (shadowType(ty)) {
2062 case Ity_I8:
2063 case Ity_I16:
2064 case Ity_I32:
2065 case Ity_I64:
2066 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
2067 case Ity_V128:
2068 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
2069 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
2070 return assignNew( mce,
2071 Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +00002072 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj69f9e3e2004-12-30 02:05:34 +00002073 default:
2074 VG_(tool_panic)("expr2vbits_LDle");
2075 }
2076}
2077
2078
2079static
sewardjde8a5ae2004-11-06 14:20:54 +00002080IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00002081 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00002082{
2083 IRAtom *vbitsC, *vbits0, *vbitsX;
2084 IRType ty;
2085 /* Given Mux0X(cond,expr0,exprX), generate
2086 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2087 That is, steer the V bits like the originals, but trash the
2088 result if the steering value is undefined. This gives
2089 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00002090 tl_assert(isOriginalAtom(mce, cond));
2091 tl_assert(isOriginalAtom(mce, expr0));
2092 tl_assert(isOriginalAtom(mce, exprX));
sewardjde8a5ae2004-11-06 14:20:54 +00002093
2094 vbitsC = expr2vbits(mce, cond);
2095 vbits0 = expr2vbits(mce, expr0);
2096 vbitsX = expr2vbits(mce, exprX);
2097 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2098
2099 return
2100 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2101 mkPCastTo(mce, ty, vbitsC) );
2102}
2103
2104/* --------- This is the main expression-handling function. --------- */
2105
2106static
2107IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2108{
2109 switch (e->tag) {
2110
2111 case Iex_Get:
2112 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2113
2114 case Iex_GetI:
2115 return shadow_GETI( mce, e->Iex.GetI.descr,
2116 e->Iex.GetI.ix, e->Iex.GetI.bias );
2117
sewardj478646f2008-05-01 20:13:04 +00002118 case Iex_RdTmp:
2119 return IRExpr_RdTmp( findShadowTmp(mce, e->Iex.RdTmp.tmp) );
sewardjde8a5ae2004-11-06 14:20:54 +00002120
2121 case Iex_Const:
2122 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2123
2124 case Iex_Binop:
2125 return expr2vbits_Binop(
2126 mce,
2127 e->Iex.Binop.op,
2128 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2129 );
2130
2131 case Iex_Unop:
2132 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2133
sewardj478646f2008-05-01 20:13:04 +00002134 case Iex_Load:
2135 return expr2vbits_LDle( mce, e->Iex.Load.ty,
2136 e->Iex.Load.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002137
2138 case Iex_CCall:
2139 return mkLazyN( mce, e->Iex.CCall.args,
2140 e->Iex.CCall.retty,
2141 e->Iex.CCall.cee );
2142
2143 case Iex_Mux0X:
2144 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2145 e->Iex.Mux0X.exprX);
2146
2147 default:
2148 VG_(printf)("\n");
2149 ppIRExpr(e);
2150 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002151 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002152 }
2153}
2154
2155/*------------------------------------------------------------*/
2156/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2157/*------------------------------------------------------------*/
2158
2159/* Widen a value to the host word size. */
2160
2161static
2162IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2163{
sewardj69f9e3e2004-12-30 02:05:34 +00002164 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002165
sewardj8fc93742004-11-22 11:29:33 +00002166 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002167 tl_assert(isShadowAtom(mce,vatom));
2168
2169 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2170 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002171
sewardjde8a5ae2004-11-06 14:20:54 +00002172 if (tyH == Ity_I32) {
2173 switch (ty) {
2174 case Ity_I32: return vatom;
2175 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2176 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2177 default: goto unhandled;
2178 }
2179 } else {
2180 goto unhandled;
2181 }
2182 unhandled:
2183 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002184 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002185}
2186
2187
sewardj3598ef92004-11-11 02:13:30 +00002188/* Generate a shadow store. addr is always the original address atom.
2189 You can pass in either originals or V-bits for the data atom, but
2190 obviously not both. */
2191
sewardjde8a5ae2004-11-06 14:20:54 +00002192static
sewardj3598ef92004-11-11 02:13:30 +00002193void do_shadow_STle ( MCEnv* mce,
2194 IRAtom* addr, UInt bias,
2195 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002196{
sewardj69f9e3e2004-12-30 02:05:34 +00002197 IROp mkAdd;
2198 IRType ty, tyAddr;
2199 IRDirty *di, *diLo64, *diHi64;
2200 IRAtom *addrAct, *addrLo64, *addrHi64;
2201 IRAtom *vdataLo64, *vdataHi64;
2202 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002203 void* helper = NULL;
sewardj478646f2008-05-01 20:13:04 +00002204 HChar* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002205
2206 tyAddr = mce->hWordTy;
2207 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2208 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2209
2210 di = diLo64 = diHi64 = NULL;
2211 eBias = eBias0 = eBias8 = NULL;
2212 addrAct = addrLo64 = addrHi64 = NULL;
2213 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002214
sewardj3598ef92004-11-11 02:13:30 +00002215 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002216 tl_assert(!vdata);
2217 tl_assert(isOriginalAtom(mce, data));
2218 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002219 vdata = expr2vbits( mce, data );
2220 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002221 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002222 }
sewardjde8a5ae2004-11-06 14:20:54 +00002223
sewardj69f9e3e2004-12-30 02:05:34 +00002224 tl_assert(isOriginalAtom(mce,addr));
2225 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002226
2227 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002228
2229 /* First, emit a definedness test for the address. This also sets
2230 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002231 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002232
sewardj69f9e3e2004-12-30 02:05:34 +00002233 /* Now decide which helper function to call to write the data V
2234 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002235 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002236 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002237 case Ity_I64: helper = &MC_(helperc_STOREV8);
2238 hname = "MC_(helperc_STOREV8)";
2239 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002240 case Ity_I32: helper = &MC_(helperc_STOREV4);
2241 hname = "MC_(helperc_STOREV4)";
2242 break;
2243 case Ity_I16: helper = &MC_(helperc_STOREV2);
2244 hname = "MC_(helperc_STOREV2)";
2245 break;
2246 case Ity_I8: helper = &MC_(helperc_STOREV1);
2247 hname = "MC_(helperc_STOREV1)";
2248 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002249 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002250 }
2251
sewardj69f9e3e2004-12-30 02:05:34 +00002252 if (ty == Ity_V128) {
2253
sewardjf0c1c582005-02-07 23:47:38 +00002254 /* V128-bit case */
sewardj69f9e3e2004-12-30 02:05:34 +00002255 /* See comment in next clause re 64-bit regparms */
2256 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2257 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
sewardjf0c1c582005-02-07 23:47:38 +00002258 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002259 diLo64 = unsafeIRDirty_0_N(
2260 1/*regparms*/, hname, helper,
2261 mkIRExprVec_2( addrLo64, vdataLo64 ));
2262
2263 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2264 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
sewardjf0c1c582005-02-07 23:47:38 +00002265 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002266 diHi64 = unsafeIRDirty_0_N(
2267 1/*regparms*/, hname, helper,
2268 mkIRExprVec_2( addrHi64, vdataHi64 ));
2269
2270 setHelperAnns( mce, diLo64 );
2271 setHelperAnns( mce, diHi64 );
2272 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2273 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2274
sewardj3598ef92004-11-11 02:13:30 +00002275 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002276
2277 /* 8/16/32/64-bit cases */
2278 /* Generate the actual address into addrAct. */
2279 if (bias == 0) {
2280 addrAct = addr;
2281 } else {
2282 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2283 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2284 }
2285
2286 if (ty == Ity_I64) {
2287 /* We can't do this with regparm 2 on 32-bit platforms, since
2288 the back ends aren't clever enough to handle 64-bit
2289 regparm args. Therefore be different. */
2290 di = unsafeIRDirty_0_N(
2291 1/*regparms*/, hname, helper,
2292 mkIRExprVec_2( addrAct, vdata ));
2293 } else {
2294 di = unsafeIRDirty_0_N(
2295 2/*regparms*/, hname, helper,
2296 mkIRExprVec_2( addrAct,
2297 zwidenToHostWord( mce, vdata )));
2298 }
2299 setHelperAnns( mce, di );
2300 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002301 }
2302
sewardjde8a5ae2004-11-06 14:20:54 +00002303}
2304
2305
sewardj3598ef92004-11-11 02:13:30 +00002306/* Do lazy pessimistic propagation through a dirty helper call, by
2307 looking at the annotations on it. This is the most complex part of
2308 Memcheck. */
2309
2310static IRType szToITy ( Int n )
2311{
2312 switch (n) {
2313 case 1: return Ity_I8;
2314 case 2: return Ity_I16;
2315 case 4: return Ity_I32;
2316 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002317 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002318 }
2319}
2320
2321static
2322void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2323{
sewardj69f9e3e2004-12-30 02:05:34 +00002324 Int i, n, offset, toDo, gSz, gOff;
2325 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002326 IRType tyAddr, tySrc, tyDst;
2327 IRTemp dst;
2328
2329 /* First check the guard. */
2330 complainIfUndefined(mce, d->guard);
2331
2332 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002333 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002334
2335 /* Inputs: unmasked args */
2336 for (i = 0; d->args[i]; i++) {
2337 if (d->cee->mcx_mask & (1<<i)) {
2338 /* ignore this arg */
2339 } else {
2340 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2341 curr = mkUifU32(mce, here, curr);
2342 }
2343 }
2344
2345 /* Inputs: guest state that we read. */
2346 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002347 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002348 if (d->fxState[i].fx == Ifx_Write)
2349 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002350
2351 /* Ignore any sections marked as 'always defined'. */
2352 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2353 if (0)
2354 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2355 d->fxState[i].offset, d->fxState[i].size );
2356 continue;
2357 }
2358
sewardj3598ef92004-11-11 02:13:30 +00002359 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002360 consider it. If larger than 8 bytes, deal with it in 8-byte
2361 chunks. */
2362 gSz = d->fxState[i].size;
2363 gOff = d->fxState[i].offset;
2364 tl_assert(gSz > 0);
2365 while (True) {
2366 if (gSz == 0) break;
2367 n = gSz <= 8 ? gSz : 8;
2368 /* update 'curr' with UifU of the state slice
2369 gOff .. gOff+n-1 */
2370 tySrc = szToITy( n );
2371 src = assignNew( mce, tySrc,
2372 shadow_GET(mce, gOff, tySrc ) );
2373 here = mkPCastTo( mce, Ity_I32, src );
2374 curr = mkUifU32(mce, here, curr);
2375 gSz -= n;
2376 gOff += n;
2377 }
2378
sewardj3598ef92004-11-11 02:13:30 +00002379 }
2380
2381 /* Inputs: memory. First set up some info needed regardless of
2382 whether we're doing reads or writes. */
2383 tyAddr = Ity_INVALID;
2384
2385 if (d->mFx != Ifx_None) {
2386 /* Because we may do multiple shadow loads/stores from the same
2387 base address, it's best to do a single test of its
2388 definedness right now. Post-instrumentation optimisation
2389 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002390 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002391 complainIfUndefined(mce, d->mAddr);
2392
2393 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002394 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2395 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002396 }
2397
2398 /* Deal with memory inputs (reads or modifies) */
2399 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2400 offset = 0;
2401 toDo = d->mSize;
2402 /* chew off 32-bit chunks */
2403 while (toDo >= 4) {
2404 here = mkPCastTo(
2405 mce, Ity_I32,
2406 expr2vbits_LDle ( mce, Ity_I32,
2407 d->mAddr, d->mSize - toDo )
2408 );
2409 curr = mkUifU32(mce, here, curr);
2410 toDo -= 4;
2411 }
2412 /* chew off 16-bit chunks */
2413 while (toDo >= 2) {
2414 here = mkPCastTo(
2415 mce, Ity_I32,
2416 expr2vbits_LDle ( mce, Ity_I16,
2417 d->mAddr, d->mSize - toDo )
2418 );
2419 curr = mkUifU32(mce, here, curr);
2420 toDo -= 2;
2421 }
sewardj69f9e3e2004-12-30 02:05:34 +00002422 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002423 }
2424
2425 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2426 all the inputs to the helper. Now we need to re-distribute the
2427 results to all destinations. */
2428
2429 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002430 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002431 dst = findShadowTmp(mce, d->tmp);
2432 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2433 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2434 }
2435
2436 /* Outputs: guest state that we write or modify. */
2437 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002438 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002439 if (d->fxState[i].fx == Ifx_Read)
2440 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002441 /* Ignore any sections marked as 'always defined'. */
2442 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2443 continue;
2444 /* This state element is written or modified. So we need to
2445 consider it. If larger than 8 bytes, deal with it in 8-byte
2446 chunks. */
2447 gSz = d->fxState[i].size;
2448 gOff = d->fxState[i].offset;
2449 tl_assert(gSz > 0);
2450 while (True) {
2451 if (gSz == 0) break;
2452 n = gSz <= 8 ? gSz : 8;
2453 /* Write suitably-casted 'curr' to the state slice
2454 gOff .. gOff+n-1 */
2455 tyDst = szToITy( n );
2456 do_shadow_PUT( mce, gOff,
2457 NULL, /* original atom */
2458 mkPCastTo( mce, tyDst, curr ) );
2459 gSz -= n;
2460 gOff += n;
2461 }
sewardj3598ef92004-11-11 02:13:30 +00002462 }
2463
2464 /* Outputs: memory that we write or modify. */
2465 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2466 offset = 0;
2467 toDo = d->mSize;
2468 /* chew off 32-bit chunks */
2469 while (toDo >= 4) {
2470 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2471 NULL, /* original data */
2472 mkPCastTo( mce, Ity_I32, curr ) );
2473 toDo -= 4;
2474 }
2475 /* chew off 16-bit chunks */
2476 while (toDo >= 2) {
2477 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2478 NULL, /* original data */
2479 mkPCastTo( mce, Ity_I16, curr ) );
2480 toDo -= 2;
2481 }
sewardj69f9e3e2004-12-30 02:05:34 +00002482 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002483 }
2484
2485}
2486
2487
sewardjde8a5ae2004-11-06 14:20:54 +00002488/*------------------------------------------------------------*/
2489/*--- Memcheck main ---*/
2490/*------------------------------------------------------------*/
2491
sewardj3598ef92004-11-11 02:13:30 +00002492static Bool isBogusAtom ( IRAtom* at )
2493{
2494 ULong n = 0;
2495 IRConst* con;
sewardj496a58d2005-03-20 18:44:44 +00002496 tl_assert(isIRAtom(at));
sewardj478646f2008-05-01 20:13:04 +00002497 if (at->tag == Iex_RdTmp)
sewardj3598ef92004-11-11 02:13:30 +00002498 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002499 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002500 con = at->Iex.Const.con;
2501 switch (con->tag) {
2502 case Ico_U8: n = (ULong)con->Ico.U8; break;
2503 case Ico_U16: n = (ULong)con->Ico.U16; break;
2504 case Ico_U32: n = (ULong)con->Ico.U32; break;
2505 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002506 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002507 }
2508 /* VG_(printf)("%llx\n", n); */
2509 return (n == 0xFEFEFEFF
2510 || n == 0x80808080
2511 || n == 0x1010101
2512 || n == 1010100);
2513}
2514
2515static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2516{
2517 Int i;
2518 IRExpr* e;
2519 switch (st->tag) {
sewardj478646f2008-05-01 20:13:04 +00002520 case Ist_WrTmp:
2521 e = st->Ist.WrTmp.data;
sewardj3598ef92004-11-11 02:13:30 +00002522 switch (e->tag) {
2523 case Iex_Get:
sewardj478646f2008-05-01 20:13:04 +00002524 case Iex_RdTmp:
sewardj3598ef92004-11-11 02:13:30 +00002525 return False;
2526 case Iex_Unop:
2527 return isBogusAtom(e->Iex.Unop.arg);
2528 case Iex_Binop:
2529 return isBogusAtom(e->Iex.Binop.arg1)
2530 || isBogusAtom(e->Iex.Binop.arg2);
2531 case Iex_Mux0X:
2532 return isBogusAtom(e->Iex.Mux0X.cond)
2533 || isBogusAtom(e->Iex.Mux0X.expr0)
2534 || isBogusAtom(e->Iex.Mux0X.exprX);
sewardj478646f2008-05-01 20:13:04 +00002535 case Iex_Load:
2536 return isBogusAtom(e->Iex.Load.addr);
sewardj3598ef92004-11-11 02:13:30 +00002537 case Iex_CCall:
2538 for (i = 0; e->Iex.CCall.args[i]; i++)
2539 if (isBogusAtom(e->Iex.CCall.args[i]))
2540 return True;
2541 return False;
2542 default:
2543 goto unhandled;
2544 }
2545 case Ist_Put:
2546 return isBogusAtom(st->Ist.Put.data);
sewardj478646f2008-05-01 20:13:04 +00002547 case Ist_Store:
2548 return isBogusAtom(st->Ist.Store.addr)
2549 || isBogusAtom(st->Ist.Store.data);
sewardj3598ef92004-11-11 02:13:30 +00002550 case Ist_Exit:
sewardj1ea1b612005-03-26 13:02:20 +00002551 return isBogusAtom(st->Ist.Exit.guard);
sewardj3598ef92004-11-11 02:13:30 +00002552 default:
2553 unhandled:
2554 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002555 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002556 }
2557}
sewardj3598ef92004-11-11 02:13:30 +00002558
sewardj478646f2008-05-01 20:13:04 +00002559IRSB* mc_instrument ( void* closureV,
2560 IRSB* bb_in, VexGuestLayout* layout,
2561 VexGuestExtents* vge,
sewardj1ea1b612005-03-26 13:02:20 +00002562 IRType gWordTy, IRType hWordTy )
sewardjde8a5ae2004-11-06 14:20:54 +00002563{
sewardj3598ef92004-11-11 02:13:30 +00002564 Bool verboze = False; //True;
2565
2566 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002567
2568 Int i, j, first_stmt;
2569 IRStmt* st;
2570 MCEnv mce;
2571
2572 /* Set up BB */
sewardjf6c8ebf2007-02-06 01:52:52 +00002573 IRSB* bb = emptyIRSB();
sewardj478646f2008-05-01 20:13:04 +00002574 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
2575 bb->next = deepCopyIRExpr(bb_in->next);
sewardjde8a5ae2004-11-06 14:20:54 +00002576 bb->jumpkind = bb_in->jumpkind;
2577
2578 /* Set up the running environment. Only .bb is modified as we go
2579 along. */
2580 mce.bb = bb;
2581 mce.layout = layout;
2582 mce.n_originalTmps = bb->tyenv->types_used;
2583 mce.hWordTy = hWordTy;
2584 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2585 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002586 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002587
2588 /* Iterate over the stmts. */
2589
2590 for (i = 0; i < bb_in->stmts_used; i++) {
2591 st = bb_in->stmts[i];
2592 if (!st) continue;
2593
sewardj69f9e3e2004-12-30 02:05:34 +00002594 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002595
2596 /*
2597 if (!hasBogusLiterals) {
2598 hasBogusLiterals = checkForBogusLiterals(st);
2599 if (hasBogusLiterals) {
2600 VG_(printf)("bogus: ");
2601 ppIRStmt(st);
2602 VG_(printf)("\n");
2603 }
2604 }
2605 */
sewardjde8a5ae2004-11-06 14:20:54 +00002606 first_stmt = bb->stmts_used;
2607
2608 if (verboze) {
2609 ppIRStmt(st);
2610 VG_(printf)("\n\n");
2611 }
2612
2613 switch (st->tag) {
2614
sewardj478646f2008-05-01 20:13:04 +00002615 case Ist_WrTmp:
2616 assign( bb, findShadowTmp(&mce, st->Ist.WrTmp.tmp),
2617 expr2vbits( &mce, st->Ist.WrTmp.data) );
sewardjde8a5ae2004-11-06 14:20:54 +00002618 break;
2619
2620 case Ist_Put:
2621 do_shadow_PUT( &mce,
2622 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002623 st->Ist.Put.data,
2624 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002625 break;
2626
2627 case Ist_PutI:
2628 do_shadow_PUTI( &mce,
2629 st->Ist.PutI.descr,
2630 st->Ist.PutI.ix,
2631 st->Ist.PutI.bias,
2632 st->Ist.PutI.data );
2633 break;
2634
sewardj478646f2008-05-01 20:13:04 +00002635 case Ist_Store:
2636 do_shadow_STle( &mce, st->Ist.Store.addr, 0/* addr bias */,
2637 st->Ist.Store.data,
sewardj3598ef92004-11-11 02:13:30 +00002638 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002639 break;
2640
2641 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002642 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002643 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002644 break;
2645
2646 case Ist_Dirty:
2647 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002648 break;
2649
sewardj1ea1b612005-03-26 13:02:20 +00002650 case Ist_IMark:
2651 case Ist_NoOp:
2652 break;
2653
sewardjde8a5ae2004-11-06 14:20:54 +00002654 default:
2655 VG_(printf)("\n");
2656 ppIRStmt(st);
2657 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002658 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002659
2660 } /* switch (st->tag) */
2661
2662 if (verboze) {
2663 for (j = first_stmt; j < bb->stmts_used; j++) {
2664 VG_(printf)(" ");
2665 ppIRStmt(bb->stmts[j]);
2666 VG_(printf)("\n");
2667 }
2668 VG_(printf)("\n");
2669 }
2670
sewardjf6c8ebf2007-02-06 01:52:52 +00002671 addStmtToIRSB(bb, st);
sewardjde8a5ae2004-11-06 14:20:54 +00002672
2673 }
2674
2675 /* Now we need to complain if the jump target is undefined. */
2676 first_stmt = bb->stmts_used;
2677
2678 if (verboze) {
2679 VG_(printf)("bb->next = ");
2680 ppIRExpr(bb->next);
2681 VG_(printf)("\n\n");
2682 }
2683
2684 complainIfUndefined( &mce, bb->next );
2685
2686 if (verboze) {
2687 for (j = first_stmt; j < bb->stmts_used; j++) {
2688 VG_(printf)(" ");
2689 ppIRStmt(bb->stmts[j]);
2690 VG_(printf)("\n");
2691 }
2692 VG_(printf)("\n");
2693 }
2694
2695 return bb;
2696}
cerionaee45242005-03-17 14:03:36 +00002697#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002698
2699/*--------------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00002700/*--- end test_main.c ---*/
sewardjde8a5ae2004-11-06 14:20:54 +00002701/*--------------------------------------------------------------------*/