blob: dad12702b64673deaba0bf44ec3e0a84983148dc [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:
1650 case Iop_CmpGT32Sx4:
1651 case Iop_CmpEQ32x4:
1652 case Iop_Add32x4:
1653 return binary32Ix4(mce, vatom1, vatom2);
1654
1655 case Iop_Sub64x2:
1656 case Iop_Add64x2:
1657 return binary64Ix2(mce, vatom1, vatom2);
1658
1659 case Iop_QNarrow32Sx4:
1660 case Iop_QNarrow16Sx8:
1661 case Iop_QNarrow16Ux8:
sewardjf0c1c582005-02-07 23:47:38 +00001662 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001663
1664 case Iop_Sub64Fx2:
1665 case Iop_Mul64Fx2:
1666 case Iop_Min64Fx2:
1667 case Iop_Max64Fx2:
1668 case Iop_Div64Fx2:
1669 case Iop_CmpLT64Fx2:
1670 case Iop_CmpLE64Fx2:
1671 case Iop_CmpEQ64Fx2:
1672 case Iop_Add64Fx2:
1673 return binary64Fx2(mce, vatom1, vatom2);
1674
1675 case Iop_Sub64F0x2:
1676 case Iop_Mul64F0x2:
1677 case Iop_Min64F0x2:
1678 case Iop_Max64F0x2:
1679 case Iop_Div64F0x2:
1680 case Iop_CmpLT64F0x2:
1681 case Iop_CmpLE64F0x2:
1682 case Iop_CmpEQ64F0x2:
1683 case Iop_Add64F0x2:
1684 return binary64F0x2(mce, vatom1, vatom2);
1685
sewardjf0c1c582005-02-07 23:47:38 +00001686 /* V128-bit SIMD (SSE1-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001687
1688 case Iop_Sub32Fx4:
1689 case Iop_Mul32Fx4:
1690 case Iop_Min32Fx4:
1691 case Iop_Max32Fx4:
1692 case Iop_Div32Fx4:
1693 case Iop_CmpLT32Fx4:
1694 case Iop_CmpLE32Fx4:
1695 case Iop_CmpEQ32Fx4:
1696 case Iop_Add32Fx4:
1697 return binary32Fx4(mce, vatom1, vatom2);
1698
1699 case Iop_Sub32F0x4:
1700 case Iop_Mul32F0x4:
1701 case Iop_Min32F0x4:
1702 case Iop_Max32F0x4:
1703 case Iop_Div32F0x4:
1704 case Iop_CmpLT32F0x4:
1705 case Iop_CmpLE32F0x4:
1706 case Iop_CmpEQ32F0x4:
1707 case Iop_Add32F0x4:
1708 return binary32F0x4(mce, vatom1, vatom2);
1709
sewardjf0c1c582005-02-07 23:47:38 +00001710 /* V128-bit data-steering */
1711 case Iop_SetV128lo32:
1712 case Iop_SetV128lo64:
1713 case Iop_64HLtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001714 case Iop_InterleaveLO64x2:
1715 case Iop_InterleaveLO32x4:
1716 case Iop_InterleaveLO16x8:
1717 case Iop_InterleaveLO8x16:
1718 case Iop_InterleaveHI64x2:
1719 case Iop_InterleaveHI32x4:
1720 case Iop_InterleaveHI16x8:
1721 case Iop_InterleaveHI8x16:
1722 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1723
1724 /* Scalar floating point */
1725
sewardj478646f2008-05-01 20:13:04 +00001726 // case Iop_RoundF64:
sewardj3598ef92004-11-11 02:13:30 +00001727 case Iop_F64toI64:
sewardj69f9e3e2004-12-30 02:05:34 +00001728 case Iop_I64toF64:
1729 /* First arg is I32 (rounding mode), second is F64 or I64
1730 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001731 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1732
1733 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1734 /* Takes two F64 args. */
sewardjde8a5ae2004-11-06 14:20:54 +00001735 case Iop_F64toI32:
sewardj69f9e3e2004-12-30 02:05:34 +00001736 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001737 /* First arg is I32 (rounding mode), second is F64 (data). */
1738 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1739
1740 case Iop_F64toI16:
1741 /* First arg is I32 (rounding mode), second is F64 (data). */
1742 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1743
sewardj3598ef92004-11-11 02:13:30 +00001744 case Iop_ScaleF64:
1745 case Iop_Yl2xF64:
1746 case Iop_Yl2xp1F64:
1747 case Iop_PRemF64:
1748 case Iop_AtanF64:
1749 case Iop_AddF64:
1750 case Iop_DivF64:
1751 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001752 case Iop_MulF64:
1753 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1754
sewardj3598ef92004-11-11 02:13:30 +00001755 case Iop_CmpF64:
1756 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1757
sewardjde8a5ae2004-11-06 14:20:54 +00001758 /* non-FP after here */
1759
1760 case Iop_DivModU64to32:
1761 case Iop_DivModS64to32:
1762 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1763
sewardj3598ef92004-11-11 02:13:30 +00001764 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001765 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001766 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001767 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001768
1769 case Iop_MullS32:
1770 case Iop_MullU32: {
1771 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1772 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1773 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1774 }
1775
sewardj3598ef92004-11-11 02:13:30 +00001776 case Iop_MullS16:
1777 case Iop_MullU16: {
1778 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1779 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1780 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1781 }
1782
1783 case Iop_MullS8:
1784 case Iop_MullU8: {
1785 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1786 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1787 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1788 }
1789
sewardjde8a5ae2004-11-06 14:20:54 +00001790 case Iop_Add32:
1791# if 0
1792 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1793# endif
1794 case Iop_Sub32:
1795 case Iop_Mul32:
1796 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1797
sewardj3598ef92004-11-11 02:13:30 +00001798 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001799 case Iop_Add16:
1800 case Iop_Sub16:
1801 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1802
1803 case Iop_Sub8:
1804 case Iop_Add8:
1805 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1806
1807 case Iop_CmpLE32S: case Iop_CmpLE32U:
1808 case Iop_CmpLT32U: case Iop_CmpLT32S:
1809 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001810 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001811
sewardj3598ef92004-11-11 02:13:30 +00001812 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001813 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001814
1815 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001816 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001817
1818 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1819 /* Complain if the shift amount is undefined. Then simply
1820 shift the first arg's V bits by the real shift amount. */
1821 complainIfUndefined(mce, atom2);
1822 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1823
sewardj69f9e3e2004-12-30 02:05:34 +00001824 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001825 /* Same scheme as with 32-bit shifts. */
1826 complainIfUndefined(mce, atom2);
1827 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1828
sewardj3598ef92004-11-11 02:13:30 +00001829 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001830 /* Same scheme as with 32-bit shifts. */
1831 complainIfUndefined(mce, atom2);
1832 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1833
1834 case Iop_Shl64: case Iop_Shr64:
1835 /* Same scheme as with 32-bit shifts. */
1836 complainIfUndefined(mce, atom2);
1837 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1838
sewardjf0c1c582005-02-07 23:47:38 +00001839 case Iop_AndV128:
1840 uifu = mkUifUV128; difd = mkDifDV128;
1841 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001842 case Iop_And64:
1843 uifu = mkUifU64; difd = mkDifD64;
1844 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001845 case Iop_And32:
1846 uifu = mkUifU32; difd = mkDifD32;
1847 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001848 case Iop_And16:
1849 uifu = mkUifU16; difd = mkDifD16;
1850 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001851 case Iop_And8:
1852 uifu = mkUifU8; difd = mkDifD8;
1853 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1854
sewardjf0c1c582005-02-07 23:47:38 +00001855 case Iop_OrV128:
1856 uifu = mkUifUV128; difd = mkDifDV128;
1857 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001858 case Iop_Or64:
1859 uifu = mkUifU64; difd = mkDifD64;
1860 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001861 case Iop_Or32:
1862 uifu = mkUifU32; difd = mkDifD32;
1863 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1864 case Iop_Or16:
1865 uifu = mkUifU16; difd = mkDifD16;
1866 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1867 case Iop_Or8:
1868 uifu = mkUifU8; difd = mkDifD8;
1869 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1870
1871 do_And_Or:
1872 return
1873 assignNew(
1874 mce,
1875 and_or_ty,
1876 difd(mce, uifu(mce, vatom1, vatom2),
1877 difd(mce, improve(mce, atom1, vatom1),
1878 improve(mce, atom2, vatom2) ) ) );
1879
1880 case Iop_Xor8:
1881 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001882 case Iop_Xor16:
1883 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001884 case Iop_Xor32:
1885 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001886 case Iop_Xor64:
1887 return mkUifU64(mce, vatom1, vatom2);
sewardjf0c1c582005-02-07 23:47:38 +00001888 case Iop_XorV128:
1889 return mkUifUV128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001890
1891 default:
1892 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001893 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001894 }
1895}
1896
1897
1898static
1899IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1900{
1901 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001902 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001903 switch (op) {
1904
sewardj69f9e3e2004-12-30 02:05:34 +00001905 case Iop_Sqrt64Fx2:
1906 return unary64Fx2(mce, vatom);
1907
1908 case Iop_Sqrt64F0x2:
1909 return unary64F0x2(mce, vatom);
1910
1911 case Iop_Sqrt32Fx4:
1912 case Iop_RSqrt32Fx4:
1913 case Iop_Recip32Fx4:
1914 return unary32Fx4(mce, vatom);
1915
1916 case Iop_Sqrt32F0x4:
1917 case Iop_RSqrt32F0x4:
1918 case Iop_Recip32F0x4:
1919 return unary32F0x4(mce, vatom);
1920
sewardjf0c1c582005-02-07 23:47:38 +00001921 case Iop_32UtoV128:
1922 case Iop_64UtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001923 return assignNew(mce, Ity_V128, unop(op, vatom));
1924
sewardjde8a5ae2004-11-06 14:20:54 +00001925 case Iop_F32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001926 case Iop_I32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001927 case Iop_NegF64:
1928 case Iop_SinF64:
1929 case Iop_CosF64:
1930 case Iop_TanF64:
1931 case Iop_SqrtF64:
1932 case Iop_AbsF64:
1933 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001934 return mkPCastTo(mce, Ity_I64, vatom);
1935
sewardj3598ef92004-11-11 02:13:30 +00001936 case Iop_Clz32:
1937 case Iop_Ctz32:
1938 return mkPCastTo(mce, Ity_I32, vatom);
1939
1940 case Iop_32Sto64:
1941 case Iop_32Uto64:
sewardjf0c1c582005-02-07 23:47:38 +00001942 case Iop_V128to64:
1943 case Iop_V128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001944 return assignNew(mce, Ity_I64, unop(op, vatom));
1945
sewardjde8a5ae2004-11-06 14:20:54 +00001946 case Iop_64to32:
1947 case Iop_64HIto32:
1948 case Iop_1Uto32:
1949 case Iop_8Uto32:
1950 case Iop_16Uto32:
1951 case Iop_16Sto32:
1952 case Iop_8Sto32:
1953 return assignNew(mce, Ity_I32, unop(op, vatom));
1954
1955 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001956 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001957 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001958 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001959 return assignNew(mce, Ity_I16, unop(op, vatom));
1960
1961 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001962 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001963 case Iop_32to8:
1964 return assignNew(mce, Ity_I8, unop(op, vatom));
1965
1966 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001967 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001968
sewardj3598ef92004-11-11 02:13:30 +00001969 case Iop_ReinterpF64asI64:
1970 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001971 case Iop_ReinterpI32asF32:
sewardjf0c1c582005-02-07 23:47:38 +00001972 case Iop_NotV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001973 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00001974 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001975 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001976 case Iop_Not8:
1977 case Iop_Not1:
1978 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001979
sewardjde8a5ae2004-11-06 14:20:54 +00001980 default:
1981 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001982 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00001983 }
1984}
1985
1986
sewardj69f9e3e2004-12-30 02:05:34 +00001987/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00001988static
sewardj69f9e3e2004-12-30 02:05:34 +00001989IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001990{
1991 void* helper;
sewardjde8c9872005-03-25 13:48:55 +00001992 HChar* hname;
sewardjde8a5ae2004-11-06 14:20:54 +00001993 IRDirty* di;
1994 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00001995 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001996
sewardj69f9e3e2004-12-30 02:05:34 +00001997 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00001998
1999 /* First, emit a definedness test for the address. This also sets
2000 the address (shadow) to 'defined' following the test. */
2001 complainIfUndefined( mce, addr );
2002
2003 /* Now cook up a call to the relevant helper function, to read the
2004 data V bits from shadow memory. */
2005 ty = shadowType(ty);
2006 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00002007 case Ity_I64: helper = &MC_(helperc_LOADV8);
2008 hname = "MC_(helperc_LOADV8)";
2009 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002010 case Ity_I32: helper = &MC_(helperc_LOADV4);
2011 hname = "MC_(helperc_LOADV4)";
2012 break;
2013 case Ity_I16: helper = &MC_(helperc_LOADV2);
2014 hname = "MC_(helperc_LOADV2)";
2015 break;
2016 case Ity_I8: helper = &MC_(helperc_LOADV1);
2017 hname = "MC_(helperc_LOADV1)";
2018 break;
2019 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00002020 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00002021 }
2022
sewardj3598ef92004-11-11 02:13:30 +00002023 /* Generate the actual address into addrAct. */
2024 if (bias == 0) {
2025 addrAct = addr;
2026 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002027 IROp mkAdd;
2028 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00002029 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00002030 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2031 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2032 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00002033 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2034 }
2035
sewardjde8a5ae2004-11-06 14:20:54 +00002036 /* We need to have a place to park the V bits we're just about to
2037 read. */
2038 datavbits = newIRTemp(mce->bb->tyenv, ty);
2039 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00002040 1/*regparms*/, hname, helper,
2041 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00002042 setHelperAnns( mce, di );
2043 stmt( mce->bb, IRStmt_Dirty(di) );
2044
2045 return mkexpr(datavbits);
2046}
2047
2048
2049static
sewardj69f9e3e2004-12-30 02:05:34 +00002050IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
2051{
2052 IRAtom *v64hi, *v64lo;
2053 switch (shadowType(ty)) {
2054 case Ity_I8:
2055 case Ity_I16:
2056 case Ity_I32:
2057 case Ity_I64:
2058 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
2059 case Ity_V128:
2060 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
2061 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
2062 return assignNew( mce,
2063 Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +00002064 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj69f9e3e2004-12-30 02:05:34 +00002065 default:
2066 VG_(tool_panic)("expr2vbits_LDle");
2067 }
2068}
2069
2070
2071static
sewardjde8a5ae2004-11-06 14:20:54 +00002072IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00002073 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00002074{
2075 IRAtom *vbitsC, *vbits0, *vbitsX;
2076 IRType ty;
2077 /* Given Mux0X(cond,expr0,exprX), generate
2078 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2079 That is, steer the V bits like the originals, but trash the
2080 result if the steering value is undefined. This gives
2081 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00002082 tl_assert(isOriginalAtom(mce, cond));
2083 tl_assert(isOriginalAtom(mce, expr0));
2084 tl_assert(isOriginalAtom(mce, exprX));
sewardjde8a5ae2004-11-06 14:20:54 +00002085
2086 vbitsC = expr2vbits(mce, cond);
2087 vbits0 = expr2vbits(mce, expr0);
2088 vbitsX = expr2vbits(mce, exprX);
2089 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2090
2091 return
2092 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2093 mkPCastTo(mce, ty, vbitsC) );
2094}
2095
2096/* --------- This is the main expression-handling function. --------- */
2097
2098static
2099IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2100{
2101 switch (e->tag) {
2102
2103 case Iex_Get:
2104 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2105
2106 case Iex_GetI:
2107 return shadow_GETI( mce, e->Iex.GetI.descr,
2108 e->Iex.GetI.ix, e->Iex.GetI.bias );
2109
sewardj478646f2008-05-01 20:13:04 +00002110 case Iex_RdTmp:
2111 return IRExpr_RdTmp( findShadowTmp(mce, e->Iex.RdTmp.tmp) );
sewardjde8a5ae2004-11-06 14:20:54 +00002112
2113 case Iex_Const:
2114 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2115
2116 case Iex_Binop:
2117 return expr2vbits_Binop(
2118 mce,
2119 e->Iex.Binop.op,
2120 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2121 );
2122
2123 case Iex_Unop:
2124 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2125
sewardj478646f2008-05-01 20:13:04 +00002126 case Iex_Load:
2127 return expr2vbits_LDle( mce, e->Iex.Load.ty,
2128 e->Iex.Load.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002129
2130 case Iex_CCall:
2131 return mkLazyN( mce, e->Iex.CCall.args,
2132 e->Iex.CCall.retty,
2133 e->Iex.CCall.cee );
2134
2135 case Iex_Mux0X:
2136 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2137 e->Iex.Mux0X.exprX);
2138
2139 default:
2140 VG_(printf)("\n");
2141 ppIRExpr(e);
2142 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002143 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002144 }
2145}
2146
2147/*------------------------------------------------------------*/
2148/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2149/*------------------------------------------------------------*/
2150
2151/* Widen a value to the host word size. */
2152
2153static
2154IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2155{
sewardj69f9e3e2004-12-30 02:05:34 +00002156 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002157
sewardj8fc93742004-11-22 11:29:33 +00002158 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002159 tl_assert(isShadowAtom(mce,vatom));
2160
2161 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2162 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002163
sewardjde8a5ae2004-11-06 14:20:54 +00002164 if (tyH == Ity_I32) {
2165 switch (ty) {
2166 case Ity_I32: return vatom;
2167 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2168 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2169 default: goto unhandled;
2170 }
2171 } else {
2172 goto unhandled;
2173 }
2174 unhandled:
2175 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002176 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002177}
2178
2179
sewardj3598ef92004-11-11 02:13:30 +00002180/* Generate a shadow store. addr is always the original address atom.
2181 You can pass in either originals or V-bits for the data atom, but
2182 obviously not both. */
2183
sewardjde8a5ae2004-11-06 14:20:54 +00002184static
sewardj3598ef92004-11-11 02:13:30 +00002185void do_shadow_STle ( MCEnv* mce,
2186 IRAtom* addr, UInt bias,
2187 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002188{
sewardj69f9e3e2004-12-30 02:05:34 +00002189 IROp mkAdd;
2190 IRType ty, tyAddr;
2191 IRDirty *di, *diLo64, *diHi64;
2192 IRAtom *addrAct, *addrLo64, *addrHi64;
2193 IRAtom *vdataLo64, *vdataHi64;
2194 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002195 void* helper = NULL;
sewardj478646f2008-05-01 20:13:04 +00002196 HChar* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002197
2198 tyAddr = mce->hWordTy;
2199 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2200 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2201
2202 di = diLo64 = diHi64 = NULL;
2203 eBias = eBias0 = eBias8 = NULL;
2204 addrAct = addrLo64 = addrHi64 = NULL;
2205 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002206
sewardj3598ef92004-11-11 02:13:30 +00002207 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002208 tl_assert(!vdata);
2209 tl_assert(isOriginalAtom(mce, data));
2210 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002211 vdata = expr2vbits( mce, data );
2212 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002213 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002214 }
sewardjde8a5ae2004-11-06 14:20:54 +00002215
sewardj69f9e3e2004-12-30 02:05:34 +00002216 tl_assert(isOriginalAtom(mce,addr));
2217 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002218
2219 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002220
2221 /* First, emit a definedness test for the address. This also sets
2222 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002223 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002224
sewardj69f9e3e2004-12-30 02:05:34 +00002225 /* Now decide which helper function to call to write the data V
2226 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002227 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002228 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002229 case Ity_I64: helper = &MC_(helperc_STOREV8);
2230 hname = "MC_(helperc_STOREV8)";
2231 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002232 case Ity_I32: helper = &MC_(helperc_STOREV4);
2233 hname = "MC_(helperc_STOREV4)";
2234 break;
2235 case Ity_I16: helper = &MC_(helperc_STOREV2);
2236 hname = "MC_(helperc_STOREV2)";
2237 break;
2238 case Ity_I8: helper = &MC_(helperc_STOREV1);
2239 hname = "MC_(helperc_STOREV1)";
2240 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002241 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002242 }
2243
sewardj69f9e3e2004-12-30 02:05:34 +00002244 if (ty == Ity_V128) {
2245
sewardjf0c1c582005-02-07 23:47:38 +00002246 /* V128-bit case */
sewardj69f9e3e2004-12-30 02:05:34 +00002247 /* See comment in next clause re 64-bit regparms */
2248 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2249 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
sewardjf0c1c582005-02-07 23:47:38 +00002250 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002251 diLo64 = unsafeIRDirty_0_N(
2252 1/*regparms*/, hname, helper,
2253 mkIRExprVec_2( addrLo64, vdataLo64 ));
2254
2255 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2256 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
sewardjf0c1c582005-02-07 23:47:38 +00002257 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002258 diHi64 = unsafeIRDirty_0_N(
2259 1/*regparms*/, hname, helper,
2260 mkIRExprVec_2( addrHi64, vdataHi64 ));
2261
2262 setHelperAnns( mce, diLo64 );
2263 setHelperAnns( mce, diHi64 );
2264 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2265 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2266
sewardj3598ef92004-11-11 02:13:30 +00002267 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002268
2269 /* 8/16/32/64-bit cases */
2270 /* Generate the actual address into addrAct. */
2271 if (bias == 0) {
2272 addrAct = addr;
2273 } else {
2274 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2275 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2276 }
2277
2278 if (ty == Ity_I64) {
2279 /* We can't do this with regparm 2 on 32-bit platforms, since
2280 the back ends aren't clever enough to handle 64-bit
2281 regparm args. Therefore be different. */
2282 di = unsafeIRDirty_0_N(
2283 1/*regparms*/, hname, helper,
2284 mkIRExprVec_2( addrAct, vdata ));
2285 } else {
2286 di = unsafeIRDirty_0_N(
2287 2/*regparms*/, hname, helper,
2288 mkIRExprVec_2( addrAct,
2289 zwidenToHostWord( mce, vdata )));
2290 }
2291 setHelperAnns( mce, di );
2292 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002293 }
2294
sewardjde8a5ae2004-11-06 14:20:54 +00002295}
2296
2297
sewardj3598ef92004-11-11 02:13:30 +00002298/* Do lazy pessimistic propagation through a dirty helper call, by
2299 looking at the annotations on it. This is the most complex part of
2300 Memcheck. */
2301
2302static IRType szToITy ( Int n )
2303{
2304 switch (n) {
2305 case 1: return Ity_I8;
2306 case 2: return Ity_I16;
2307 case 4: return Ity_I32;
2308 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002309 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002310 }
2311}
2312
2313static
2314void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2315{
sewardj69f9e3e2004-12-30 02:05:34 +00002316 Int i, n, offset, toDo, gSz, gOff;
2317 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002318 IRType tyAddr, tySrc, tyDst;
2319 IRTemp dst;
2320
2321 /* First check the guard. */
2322 complainIfUndefined(mce, d->guard);
2323
2324 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002325 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002326
2327 /* Inputs: unmasked args */
2328 for (i = 0; d->args[i]; i++) {
2329 if (d->cee->mcx_mask & (1<<i)) {
2330 /* ignore this arg */
2331 } else {
2332 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2333 curr = mkUifU32(mce, here, curr);
2334 }
2335 }
2336
2337 /* Inputs: guest state that we read. */
2338 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002339 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002340 if (d->fxState[i].fx == Ifx_Write)
2341 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002342
2343 /* Ignore any sections marked as 'always defined'. */
2344 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2345 if (0)
2346 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2347 d->fxState[i].offset, d->fxState[i].size );
2348 continue;
2349 }
2350
sewardj3598ef92004-11-11 02:13:30 +00002351 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002352 consider it. If larger than 8 bytes, deal with it in 8-byte
2353 chunks. */
2354 gSz = d->fxState[i].size;
2355 gOff = d->fxState[i].offset;
2356 tl_assert(gSz > 0);
2357 while (True) {
2358 if (gSz == 0) break;
2359 n = gSz <= 8 ? gSz : 8;
2360 /* update 'curr' with UifU of the state slice
2361 gOff .. gOff+n-1 */
2362 tySrc = szToITy( n );
2363 src = assignNew( mce, tySrc,
2364 shadow_GET(mce, gOff, tySrc ) );
2365 here = mkPCastTo( mce, Ity_I32, src );
2366 curr = mkUifU32(mce, here, curr);
2367 gSz -= n;
2368 gOff += n;
2369 }
2370
sewardj3598ef92004-11-11 02:13:30 +00002371 }
2372
2373 /* Inputs: memory. First set up some info needed regardless of
2374 whether we're doing reads or writes. */
2375 tyAddr = Ity_INVALID;
2376
2377 if (d->mFx != Ifx_None) {
2378 /* Because we may do multiple shadow loads/stores from the same
2379 base address, it's best to do a single test of its
2380 definedness right now. Post-instrumentation optimisation
2381 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002382 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002383 complainIfUndefined(mce, d->mAddr);
2384
2385 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002386 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2387 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002388 }
2389
2390 /* Deal with memory inputs (reads or modifies) */
2391 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2392 offset = 0;
2393 toDo = d->mSize;
2394 /* chew off 32-bit chunks */
2395 while (toDo >= 4) {
2396 here = mkPCastTo(
2397 mce, Ity_I32,
2398 expr2vbits_LDle ( mce, Ity_I32,
2399 d->mAddr, d->mSize - toDo )
2400 );
2401 curr = mkUifU32(mce, here, curr);
2402 toDo -= 4;
2403 }
2404 /* chew off 16-bit chunks */
2405 while (toDo >= 2) {
2406 here = mkPCastTo(
2407 mce, Ity_I32,
2408 expr2vbits_LDle ( mce, Ity_I16,
2409 d->mAddr, d->mSize - toDo )
2410 );
2411 curr = mkUifU32(mce, here, curr);
2412 toDo -= 2;
2413 }
sewardj69f9e3e2004-12-30 02:05:34 +00002414 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002415 }
2416
2417 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2418 all the inputs to the helper. Now we need to re-distribute the
2419 results to all destinations. */
2420
2421 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002422 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002423 dst = findShadowTmp(mce, d->tmp);
2424 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2425 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2426 }
2427
2428 /* Outputs: guest state that we write or modify. */
2429 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002430 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002431 if (d->fxState[i].fx == Ifx_Read)
2432 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002433 /* Ignore any sections marked as 'always defined'. */
2434 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2435 continue;
2436 /* This state element is written or modified. So we need to
2437 consider it. If larger than 8 bytes, deal with it in 8-byte
2438 chunks. */
2439 gSz = d->fxState[i].size;
2440 gOff = d->fxState[i].offset;
2441 tl_assert(gSz > 0);
2442 while (True) {
2443 if (gSz == 0) break;
2444 n = gSz <= 8 ? gSz : 8;
2445 /* Write suitably-casted 'curr' to the state slice
2446 gOff .. gOff+n-1 */
2447 tyDst = szToITy( n );
2448 do_shadow_PUT( mce, gOff,
2449 NULL, /* original atom */
2450 mkPCastTo( mce, tyDst, curr ) );
2451 gSz -= n;
2452 gOff += n;
2453 }
sewardj3598ef92004-11-11 02:13:30 +00002454 }
2455
2456 /* Outputs: memory that we write or modify. */
2457 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2458 offset = 0;
2459 toDo = d->mSize;
2460 /* chew off 32-bit chunks */
2461 while (toDo >= 4) {
2462 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2463 NULL, /* original data */
2464 mkPCastTo( mce, Ity_I32, curr ) );
2465 toDo -= 4;
2466 }
2467 /* chew off 16-bit chunks */
2468 while (toDo >= 2) {
2469 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2470 NULL, /* original data */
2471 mkPCastTo( mce, Ity_I16, curr ) );
2472 toDo -= 2;
2473 }
sewardj69f9e3e2004-12-30 02:05:34 +00002474 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002475 }
2476
2477}
2478
2479
sewardjde8a5ae2004-11-06 14:20:54 +00002480/*------------------------------------------------------------*/
2481/*--- Memcheck main ---*/
2482/*------------------------------------------------------------*/
2483
sewardj3598ef92004-11-11 02:13:30 +00002484static Bool isBogusAtom ( IRAtom* at )
2485{
2486 ULong n = 0;
2487 IRConst* con;
sewardj496a58d2005-03-20 18:44:44 +00002488 tl_assert(isIRAtom(at));
sewardj478646f2008-05-01 20:13:04 +00002489 if (at->tag == Iex_RdTmp)
sewardj3598ef92004-11-11 02:13:30 +00002490 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002491 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002492 con = at->Iex.Const.con;
2493 switch (con->tag) {
2494 case Ico_U8: n = (ULong)con->Ico.U8; break;
2495 case Ico_U16: n = (ULong)con->Ico.U16; break;
2496 case Ico_U32: n = (ULong)con->Ico.U32; break;
2497 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002498 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002499 }
2500 /* VG_(printf)("%llx\n", n); */
2501 return (n == 0xFEFEFEFF
2502 || n == 0x80808080
2503 || n == 0x1010101
2504 || n == 1010100);
2505}
2506
2507static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2508{
2509 Int i;
2510 IRExpr* e;
2511 switch (st->tag) {
sewardj478646f2008-05-01 20:13:04 +00002512 case Ist_WrTmp:
2513 e = st->Ist.WrTmp.data;
sewardj3598ef92004-11-11 02:13:30 +00002514 switch (e->tag) {
2515 case Iex_Get:
sewardj478646f2008-05-01 20:13:04 +00002516 case Iex_RdTmp:
sewardj3598ef92004-11-11 02:13:30 +00002517 return False;
2518 case Iex_Unop:
2519 return isBogusAtom(e->Iex.Unop.arg);
2520 case Iex_Binop:
2521 return isBogusAtom(e->Iex.Binop.arg1)
2522 || isBogusAtom(e->Iex.Binop.arg2);
2523 case Iex_Mux0X:
2524 return isBogusAtom(e->Iex.Mux0X.cond)
2525 || isBogusAtom(e->Iex.Mux0X.expr0)
2526 || isBogusAtom(e->Iex.Mux0X.exprX);
sewardj478646f2008-05-01 20:13:04 +00002527 case Iex_Load:
2528 return isBogusAtom(e->Iex.Load.addr);
sewardj3598ef92004-11-11 02:13:30 +00002529 case Iex_CCall:
2530 for (i = 0; e->Iex.CCall.args[i]; i++)
2531 if (isBogusAtom(e->Iex.CCall.args[i]))
2532 return True;
2533 return False;
2534 default:
2535 goto unhandled;
2536 }
2537 case Ist_Put:
2538 return isBogusAtom(st->Ist.Put.data);
sewardj478646f2008-05-01 20:13:04 +00002539 case Ist_Store:
2540 return isBogusAtom(st->Ist.Store.addr)
2541 || isBogusAtom(st->Ist.Store.data);
sewardj3598ef92004-11-11 02:13:30 +00002542 case Ist_Exit:
sewardj1ea1b612005-03-26 13:02:20 +00002543 return isBogusAtom(st->Ist.Exit.guard);
sewardj3598ef92004-11-11 02:13:30 +00002544 default:
2545 unhandled:
2546 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002547 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002548 }
2549}
sewardj3598ef92004-11-11 02:13:30 +00002550
sewardj478646f2008-05-01 20:13:04 +00002551IRSB* mc_instrument ( void* closureV,
2552 IRSB* bb_in, VexGuestLayout* layout,
2553 VexGuestExtents* vge,
sewardj1ea1b612005-03-26 13:02:20 +00002554 IRType gWordTy, IRType hWordTy )
sewardjde8a5ae2004-11-06 14:20:54 +00002555{
sewardj3598ef92004-11-11 02:13:30 +00002556 Bool verboze = False; //True;
2557
2558 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002559
2560 Int i, j, first_stmt;
2561 IRStmt* st;
2562 MCEnv mce;
2563
2564 /* Set up BB */
sewardjf6c8ebf2007-02-06 01:52:52 +00002565 IRSB* bb = emptyIRSB();
sewardj478646f2008-05-01 20:13:04 +00002566 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
2567 bb->next = deepCopyIRExpr(bb_in->next);
sewardjde8a5ae2004-11-06 14:20:54 +00002568 bb->jumpkind = bb_in->jumpkind;
2569
2570 /* Set up the running environment. Only .bb is modified as we go
2571 along. */
2572 mce.bb = bb;
2573 mce.layout = layout;
2574 mce.n_originalTmps = bb->tyenv->types_used;
2575 mce.hWordTy = hWordTy;
2576 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2577 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002578 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002579
2580 /* Iterate over the stmts. */
2581
2582 for (i = 0; i < bb_in->stmts_used; i++) {
2583 st = bb_in->stmts[i];
2584 if (!st) continue;
2585
sewardj69f9e3e2004-12-30 02:05:34 +00002586 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002587
2588 /*
2589 if (!hasBogusLiterals) {
2590 hasBogusLiterals = checkForBogusLiterals(st);
2591 if (hasBogusLiterals) {
2592 VG_(printf)("bogus: ");
2593 ppIRStmt(st);
2594 VG_(printf)("\n");
2595 }
2596 }
2597 */
sewardjde8a5ae2004-11-06 14:20:54 +00002598 first_stmt = bb->stmts_used;
2599
2600 if (verboze) {
2601 ppIRStmt(st);
2602 VG_(printf)("\n\n");
2603 }
2604
2605 switch (st->tag) {
2606
sewardj478646f2008-05-01 20:13:04 +00002607 case Ist_WrTmp:
2608 assign( bb, findShadowTmp(&mce, st->Ist.WrTmp.tmp),
2609 expr2vbits( &mce, st->Ist.WrTmp.data) );
sewardjde8a5ae2004-11-06 14:20:54 +00002610 break;
2611
2612 case Ist_Put:
2613 do_shadow_PUT( &mce,
2614 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002615 st->Ist.Put.data,
2616 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002617 break;
2618
2619 case Ist_PutI:
2620 do_shadow_PUTI( &mce,
2621 st->Ist.PutI.descr,
2622 st->Ist.PutI.ix,
2623 st->Ist.PutI.bias,
2624 st->Ist.PutI.data );
2625 break;
2626
sewardj478646f2008-05-01 20:13:04 +00002627 case Ist_Store:
2628 do_shadow_STle( &mce, st->Ist.Store.addr, 0/* addr bias */,
2629 st->Ist.Store.data,
sewardj3598ef92004-11-11 02:13:30 +00002630 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002631 break;
2632
2633 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002634 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002635 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002636 break;
2637
2638 case Ist_Dirty:
2639 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002640 break;
2641
sewardj1ea1b612005-03-26 13:02:20 +00002642 case Ist_IMark:
2643 case Ist_NoOp:
2644 break;
2645
sewardjde8a5ae2004-11-06 14:20:54 +00002646 default:
2647 VG_(printf)("\n");
2648 ppIRStmt(st);
2649 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002650 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002651
2652 } /* switch (st->tag) */
2653
2654 if (verboze) {
2655 for (j = first_stmt; j < bb->stmts_used; j++) {
2656 VG_(printf)(" ");
2657 ppIRStmt(bb->stmts[j]);
2658 VG_(printf)("\n");
2659 }
2660 VG_(printf)("\n");
2661 }
2662
sewardjf6c8ebf2007-02-06 01:52:52 +00002663 addStmtToIRSB(bb, st);
sewardjde8a5ae2004-11-06 14:20:54 +00002664
2665 }
2666
2667 /* Now we need to complain if the jump target is undefined. */
2668 first_stmt = bb->stmts_used;
2669
2670 if (verboze) {
2671 VG_(printf)("bb->next = ");
2672 ppIRExpr(bb->next);
2673 VG_(printf)("\n\n");
2674 }
2675
2676 complainIfUndefined( &mce, bb->next );
2677
2678 if (verboze) {
2679 for (j = first_stmt; j < bb->stmts_used; j++) {
2680 VG_(printf)(" ");
2681 ppIRStmt(bb->stmts[j]);
2682 VG_(printf)("\n");
2683 }
2684 VG_(printf)("\n");
2685 }
2686
2687 return bb;
2688}
cerionaee45242005-03-17 14:03:36 +00002689#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002690
2691/*--------------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00002692/*--- end test_main.c ---*/
sewardjde8a5ae2004-11-06 14:20:54 +00002693/*--------------------------------------------------------------------*/