blob: f1336aa6326746b989462146150e4820ee057bde [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
sewardjbc161a42011-06-07 21:28:38 +000087static Bool chase_into_not_ok ( void* opaque, Addr64 dst ) {
88 return False;
89}
90static UInt needs_self_check ( void* opaque, VexGuestExtents* vge ) {
91 return 0;
92}
sewardj9b1004e2004-10-30 22:25:40 +000093
sewardjced9fe52004-07-07 11:55:36 +000094int main ( int argc, char** argv )
sewardjce605f92004-07-05 14:39:15 +000095{
sewardjced9fe52004-07-07 11:55:36 +000096 FILE* f;
97 Int i;
sewardj4459baa2004-09-10 20:00:46 +000098 UInt u, sum;
sewardjced9fe52004-07-07 11:55:36 +000099 Addr32 orig_addr;
sewardjabe017e2004-10-29 23:42:36 +0000100 Int bb_number, n_bbs_done = 0;
sewardj72c72812005-01-19 11:49:45 +0000101 Int orig_nbytes, trans_used;
sewardjd887b862005-01-17 18:34:34 +0000102 VexTranslateResult tres;
sewardjb5bf2e02004-10-25 13:06:17 +0000103 VexControl vcon;
sewardj72c72812005-01-19 11:49:45 +0000104 VexGuestExtents vge;
sewardj9e6491a2005-07-02 19:24:10 +0000105 VexArchInfo vai_x86, vai_amd64, vai_ppc32;
sewardjdd40fdf2006-12-24 02:20:24 +0000106 VexAbiInfo vbi;
sewardj17c7f952005-12-15 14:02:34 +0000107 VexTranslateArgs vta;
sewardjced9fe52004-07-07 11:55:36 +0000108
109 if (argc != 2) {
110 fprintf(stderr, "usage: vex file.org\n");
111 exit(1);
112 }
113 f = fopen(argv[1], "r");
114 if (!f) {
115 fprintf(stderr, "can't open `%s'\n", argv[1]);
116 exit(1);
117 }
118
sewardjb5bf2e02004-10-25 13:06:17 +0000119 /* Run with default params. However, we can't allow bb chasing
120 since that causes the front end to get segfaults when it tries
sewardj5bd4d162004-11-10 13:02:48 +0000121 to read code outside the initial BB we hand it. So when calling
122 LibVEX_Translate, send in a chase-into predicate that always
123 returns False. */
sewardjb5bf2e02004-10-25 13:06:17 +0000124 LibVEX_default_VexControl ( &vcon );
sewardjb4952402004-10-26 13:24:50 +0000125 vcon.iropt_level = 2;
sewardjc279b3f2005-03-16 18:10:45 +0000126 vcon.guest_max_insns = 50;
sewardjb5bf2e02004-10-25 13:06:17 +0000127
sewardjced9fe52004-07-07 11:55:36 +0000128 LibVEX_Init ( &failure_exit, &log_bytes,
sewardj1f40a0a2004-07-21 12:28:07 +0000129 1, /* debug_paranoia */
sewardjabe017e2004-10-29 23:42:36 +0000130 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +0000131 &vcon );
sewardjced9fe52004-07-07 11:55:36 +0000132
sewardjea64e142004-07-22 16:47:21 +0000133
sewardjced9fe52004-07-07 11:55:36 +0000134 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +0000135
sewardjced9fe52004-07-07 11:55:36 +0000136 fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +0000137 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +0000138 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +0000139
140 if (n_bbs_done == TEST_N_BBS) break;
141 n_bbs_done++;
142
sewardjced9fe52004-07-07 11:55:36 +0000143 /* first line is: . bb-number bb-addr n-bytes */
144 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
145 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000146 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000147 assert(orig_nbytes >= 1);
148 assert(!feof(f));
149 fgets(linebuf, N_LINEBUF,f);
150 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000151
sewardjced9fe52004-07-07 11:55:36 +0000152 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000153 if (verbose)
sewardj07a54cc2005-02-04 21:18:55 +0000154 printf("============ Basic Block %d, Done %d, "
sewardj4459baa2004-09-10 20:00:46 +0000155 "Start %x, nbytes %2d ============",
sewardj07a54cc2005-02-04 21:18:55 +0000156 bb_number, n_bbs_done-1, orig_addr, orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000157
sewardjced9fe52004-07-07 11:55:36 +0000158 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
159 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000160 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
161 origbuf[i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000162 }
163
sewardj5117ce12006-01-27 21:20:15 +0000164 /* FIXME: put sensible values into the .hwcaps fields */
sewardj9e6491a2005-07-02 19:24:10 +0000165 LibVEX_default_VexArchInfo(&vai_x86);
sewardjc4356f02007-11-09 21:15:04 +0000166 vai_x86.hwcaps = VEX_HWCAPS_X86_SSE1
167 | VEX_HWCAPS_X86_SSE2 | VEX_HWCAPS_X86_SSE3;
sewardj9e6491a2005-07-02 19:24:10 +0000168
169 LibVEX_default_VexArchInfo(&vai_amd64);
sewardj5117ce12006-01-27 21:20:15 +0000170 vai_amd64.hwcaps = 0;
sewardj9e6491a2005-07-02 19:24:10 +0000171
172 LibVEX_default_VexArchInfo(&vai_ppc32);
sewardj5117ce12006-01-27 21:20:15 +0000173 vai_ppc32.hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000174 vai_ppc32.ppc_cache_line_szB = 128;
sewardj02ef7162005-06-30 12:50:50 +0000175
sewardjdd40fdf2006-12-24 02:20:24 +0000176 LibVEX_default_VexAbiInfo(&vbi);
sewardjaca070a2006-10-17 00:28:22 +0000177
sewardj17c7f952005-12-15 14:02:34 +0000178 /* ----- Set up args for LibVEX_Translate ----- */
sewardjc4356f02007-11-09 21:15:04 +0000179#if 0 /* ppc32 -> ppc32 */
sewardj17c7f952005-12-15 14:02:34 +0000180 vta.arch_guest = VexArchPPC32;
181 vta.archinfo_guest = vai_ppc32;
182 vta.arch_host = VexArchPPC32;
183 vta.archinfo_host = vai_ppc32;
sewardj07a54cc2005-02-04 21:18:55 +0000184#endif
sewardjc279b3f2005-03-16 18:10:45 +0000185#if 0 /* amd64 -> amd64 */
sewardj17c7f952005-12-15 14:02:34 +0000186 vta.arch_guest = VexArchAMD64;
187 vta.archinfo_guest = vai_amd64;
188 vta.arch_host = VexArchAMD64;
189 vta.archinfo_host = vai_amd64;
sewardj07a54cc2005-02-04 21:18:55 +0000190#endif
sewardjc4356f02007-11-09 21:15:04 +0000191#if 1 /* x86 -> x86 */
sewardj17c7f952005-12-15 14:02:34 +0000192 vta.arch_guest = VexArchX86;
193 vta.archinfo_guest = vai_x86;
194 vta.arch_host = VexArchX86;
195 vta.archinfo_host = vai_x86;
sewardjc279b3f2005-03-16 18:10:45 +0000196#endif
sewardjdd40fdf2006-12-24 02:20:24 +0000197 vta.abiinfo_both = vbi;
sewardj17c7f952005-12-15 14:02:34 +0000198 vta.guest_bytes = origbuf;
199 vta.guest_bytes_addr = (Addr64)orig_addr;
sewardjc716aea2006-01-17 01:48:46 +0000200 vta.callback_opaque = NULL;
sewardj17c7f952005-12-15 14:02:34 +0000201 vta.chase_into_ok = chase_into_not_ok;
202 vta.guest_extents = &vge;
203 vta.host_bytes = transbuf;
204 vta.host_bytes_size = N_TRANSBUF;
205 vta.host_bytes_used = &trans_used;
sewardj478646f2008-05-01 20:13:04 +0000206#if 0 /* no instrumentation */
sewardj17c7f952005-12-15 14:02:34 +0000207 vta.instrument1 = NULL;
208 vta.instrument2 = NULL;
sewardj9e7448b2004-11-18 13:44:15 +0000209#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000210#if 0 /* addrcheck */
sewardj17c7f952005-12-15 14:02:34 +0000211 vta.instrument1 = ac_instrument;
212 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000213#endif
sewardj478646f2008-05-01 20:13:04 +0000214#if 1 /* memcheck */
sewardj17c7f952005-12-15 14:02:34 +0000215 vta.instrument1 = mc_instrument;
216 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000217#endif
sewardjbc161a42011-06-07 21:28:38 +0000218 vta.needs_self_check = needs_self_check;
sewardjc716aea2006-01-17 01:48:46 +0000219 vta.preamble_function = NULL;
sewardj17c7f952005-12-15 14:02:34 +0000220 vta.traceflags = TEST_FLAGS;
221#if 1 /* x86, amd64 hosts */
sewardjbc161a42011-06-07 21:28:38 +0000222 vta.dispatch_unassisted = (void*)0x12345678;
223 vta.dispatch_assisted = (void*)0x12345678;
sewardj17c7f952005-12-15 14:02:34 +0000224#else /* ppc32, ppc64 hosts */
225 vta.dispatch = NULL;
226#endif
227
sewardjc4356f02007-11-09 21:15:04 +0000228 vta.finaltidy = NULL;
229
sewardj17c7f952005-12-15 14:02:34 +0000230 for (i = 0; i < TEST_N_ITERS; i++)
231 tres = LibVEX_Translate ( &vta );
sewardjabe017e2004-10-29 23:42:36 +0000232
sewardjbc161a42011-06-07 21:28:38 +0000233 if (tres.status != VexTransOK)
234 printf("\ntres = %d\n", (Int)tres.status);
235 assert(tres.status == VexTransOK);
236 assert(tres.n_sc_extents == 0);
sewardj72c72812005-01-19 11:49:45 +0000237 assert(vge.n_used == 1);
238 assert((UInt)(vge.len[0]) == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000239
sewardj4459baa2004-09-10 20:00:46 +0000240 sum = 0;
241 for (i = 0; i < trans_used; i++)
242 sum += (UInt)transbuf[i];
sewardjde8c9872005-03-25 13:48:55 +0000243 printf ( " %6.2f ... %u\n",
244 (double)trans_used / (double)vge.len[0], sum );
sewardjced9fe52004-07-07 11:55:36 +0000245 }
246
247 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000248 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000249 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000250
sewardjce605f92004-07-05 14:39:15 +0000251 return 0;
252}
sewardj9b1004e2004-10-30 22:25:40 +0000253
254//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000255//////////////////////////////////////////////////////////////////////
256//////////////////////////////////////////////////////////////////////
257//////////////////////////////////////////////////////////////////////
258//////////////////////////////////////////////////////////////////////
259//////////////////////////////////////////////////////////////////////
260//////////////////////////////////////////////////////////////////////
261//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000262
sewardj1ea1b612005-03-26 13:02:20 +0000263#if 0 /* UNUSED */
264
sewardj9b1004e2004-10-30 22:25:40 +0000265static
sewardjde8a5ae2004-11-06 14:20:54 +0000266__attribute((noreturn))
sewardjde8c9872005-03-25 13:48:55 +0000267void panic ( HChar* s )
sewardj9b1004e2004-10-30 22:25:40 +0000268{
269 printf("\npanic: %s\n", s);
270 failure_exit();
271}
272
273static
sewardjf6c8ebf2007-02-06 01:52:52 +0000274IRSB* ac_instrument (IRSB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000275{
276/* Use this rather than eg. -1 because it's a UInt. */
277#define INVALID_DATA_SIZE 999999
278
279 Int i;
280 Int sz;
281 IRCallee* helper;
282 IRStmt* st;
283 IRExpr* data;
284 IRExpr* addr;
285 Bool needSz;
286
287 /* Set up BB */
sewardjf6c8ebf2007-02-06 01:52:52 +0000288 IRSB* bb = emptyIRSB();
sewardj9b1004e2004-10-30 22:25:40 +0000289 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
290 bb->next = dopyIRExpr(bb_in->next);
291 bb->jumpkind = bb_in->jumpkind;
292
293 /* No loads to consider in ->next. */
sewardj496a58d2005-03-20 18:44:44 +0000294 assert(isIRAtom(bb_in->next));
sewardj9b1004e2004-10-30 22:25:40 +0000295
296 for (i = 0; i < bb_in->stmts_used; i++) {
297 st = bb_in->stmts[i];
298 if (!st) continue;
299
300 switch (st->tag) {
301
302 case Ist_Tmp:
303 data = st->Ist.Tmp.data;
304 if (data->tag == Iex_LDle) {
305 addr = data->Iex.LDle.addr;
306 sz = sizeofIRType(data->Iex.LDle.ty);
307 needSz = False;
308 switch (sz) {
309 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000310 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000311 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000312 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000313 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000314 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000315 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000316 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000317 needSz = True; break;
318 }
319 if (needSz) {
sewardjf6c8ebf2007-02-06 01:52:52 +0000320 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000321 bb,
322 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000323 unsafeIRDirty_0_N( helper->regparms,
324 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000325 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
326 ));
327 } else {
sewardjf6c8ebf2007-02-06 01:52:52 +0000328 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000329 bb,
330 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000331 unsafeIRDirty_0_N( helper->regparms,
332 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000333 mkIRExprVec_1(addr) )
334 ));
335 }
336 }
337 break;
338
339 case Ist_STle:
340 data = st->Ist.STle.data;
341 addr = st->Ist.STle.addr;
sewardj496a58d2005-03-20 18:44:44 +0000342 assert(isIRAtom(data));
343 assert(isIRAtom(addr));
sewardj9b1004e2004-10-30 22:25:40 +0000344 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
345 needSz = False;
346 switch (sz) {
347 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000348 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000349 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000350 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000351 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000352 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000353 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000354 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000355 needSz = True; break;
356 }
357 if (needSz) {
sewardjf6c8ebf2007-02-06 01:52:52 +0000358 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000359 bb,
360 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000361 unsafeIRDirty_0_N( helper->regparms,
362 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000363 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
364 ));
365 } else {
sewardjf6c8ebf2007-02-06 01:52:52 +0000366 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000367 bb,
368 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000369 unsafeIRDirty_0_N( helper->regparms,
370 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000371 mkIRExprVec_1(addr) )
372 ));
373 }
374 break;
375
376 case Ist_Put:
sewardj496a58d2005-03-20 18:44:44 +0000377 assert(isIRAtom(st->Ist.Put.data));
sewardj9b1004e2004-10-30 22:25:40 +0000378 break;
379
380 case Ist_PutI:
sewardj496a58d2005-03-20 18:44:44 +0000381 assert(isIRAtom(st->Ist.PutI.ix));
382 assert(isIRAtom(st->Ist.PutI.data));
sewardj9b1004e2004-10-30 22:25:40 +0000383 break;
384
385 case Ist_Exit:
sewardj496a58d2005-03-20 18:44:44 +0000386 assert(isIRAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000387 break;
388
389 case Ist_Dirty:
390 /* If the call doesn't interact with memory, we ain't
391 interested. */
392 if (st->Ist.Dirty.details->mFx == Ifx_None)
393 break;
394 goto unhandled;
395
396 default:
397 unhandled:
398 printf("\n");
399 ppIRStmt(st);
400 printf("\n");
401 panic("addrcheck: unhandled IRStmt");
402 }
403
sewardjf6c8ebf2007-02-06 01:52:52 +0000404 addStmtToIRSB( bb, dopyIRStmt(st));
sewardj9b1004e2004-10-30 22:25:40 +0000405 }
406
407 return bb;
408}
cerionaee45242005-03-17 14:03:36 +0000409#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +0000410
411//////////////////////////////////////////////////////////////////////
412//////////////////////////////////////////////////////////////////////
413//////////////////////////////////////////////////////////////////////
414//////////////////////////////////////////////////////////////////////
415//////////////////////////////////////////////////////////////////////
416//////////////////////////////////////////////////////////////////////
417//////////////////////////////////////////////////////////////////////
418//////////////////////////////////////////////////////////////////////
419
sewardj478646f2008-05-01 20:13:04 +0000420#if 1 /* UNUSED */
421
422static
423__attribute((noreturn))
424void panic ( HChar* s )
425{
426 printf("\npanic: %s\n", s);
427 failure_exit();
428}
sewardj1ea1b612005-03-26 13:02:20 +0000429
sewardj69f9e3e2004-12-30 02:05:34 +0000430#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000431#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000432#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000433#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000434#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000435
cerionaee45242005-03-17 14:03:36 +0000436
sewardjde8c9872005-03-25 13:48:55 +0000437static void MC_helperc_complain_undef ( void );
438static void MC_helperc_LOADV8 ( void );
439static void MC_helperc_LOADV4 ( void );
440static void MC_helperc_LOADV2 ( void );
441static void MC_helperc_LOADV1 ( void );
sewardj1ea1b612005-03-26 13:02:20 +0000442static void MC_helperc_STOREV8( void );
443static void MC_helperc_STOREV4( void );
444static void MC_helperc_STOREV2( void );
445static void MC_helperc_STOREV1( void );
sewardjde8c9872005-03-25 13:48:55 +0000446static void MC_helperc_value_check0_fail( void );
447static void MC_helperc_value_check1_fail( void );
448static void MC_helperc_value_check4_fail( void );
449
450static void MC_helperc_complain_undef ( void ) { }
451static void MC_helperc_LOADV8 ( void ) { }
452static void MC_helperc_LOADV4 ( void ) { }
453static void MC_helperc_LOADV2 ( void ) { }
454static void MC_helperc_LOADV1 ( void ) { }
sewardj1ea1b612005-03-26 13:02:20 +0000455static void MC_helperc_STOREV8( void ) { }
456static void MC_helperc_STOREV4( void ) { }
457static void MC_helperc_STOREV2( void ) { }
458static void MC_helperc_STOREV1( void ) { }
sewardjde8c9872005-03-25 13:48:55 +0000459static void MC_helperc_value_check0_fail( void ) { }
460static void MC_helperc_value_check1_fail( void ) { }
461static void MC_helperc_value_check4_fail( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000462
463
sewardj3598ef92004-11-11 02:13:30 +0000464/*--------------------------------------------------------------------*/
465/*--- Instrument IR to perform memory checking operations. ---*/
466/*--- mc_translate.c ---*/
467/*--------------------------------------------------------------------*/
468
469/*
470 This file is part of MemCheck, a heavyweight Valgrind tool for
471 detecting memory errors.
472
sewardj752f9062010-05-03 21:38:49 +0000473 Copyright (C) 2000-2010 Julian Seward
sewardj3598ef92004-11-11 02:13:30 +0000474 jseward@acm.org
475
476 This program is free software; you can redistribute it and/or
477 modify it under the terms of the GNU General Public License as
478 published by the Free Software Foundation; either version 2 of the
479 License, or (at your option) any later version.
480
481 This program is distributed in the hope that it will be useful, but
482 WITHOUT ANY WARRANTY; without even the implied warranty of
483 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
484 General Public License for more details.
485
486 You should have received a copy of the GNU General Public License
487 along with this program; if not, write to the Free Software
488 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
489 02111-1307, USA.
490
491 The GNU General Public License is contained in the file COPYING.
492*/
493
494//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000495
496
497/*------------------------------------------------------------*/
498/*--- Forward decls ---*/
499/*------------------------------------------------------------*/
500
501struct _MCEnv;
502
503static IRType shadowType ( IRType ty );
504static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
505
506
507/*------------------------------------------------------------*/
508/*--- Memcheck running state, and tmp management. ---*/
509/*------------------------------------------------------------*/
510
511/* Carries around state during memcheck instrumentation. */
512typedef
513 struct _MCEnv {
514 /* MODIFIED: the bb being constructed. IRStmts are added. */
sewardjf6c8ebf2007-02-06 01:52:52 +0000515 IRSB* bb;
sewardjde8a5ae2004-11-06 14:20:54 +0000516
517 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
518 original temps to their current their current shadow temp.
519 Initially all entries are IRTemp_INVALID. Entries are added
520 lazily since many original temps are not used due to
521 optimisation prior to instrumentation. Note that floating
522 point original tmps are shadowed by integer tmps of the same
523 size, and Bit-typed original tmps are shadowed by the type
524 Ity_I8. See comment below. */
525 IRTemp* tmpMap;
526 Int n_originalTmps; /* for range checking */
527
528 /* READONLY: the guest layout. This indicates which parts of
529 the guest state should be regarded as 'always defined'. */
530 VexGuestLayout* layout;
531 /* READONLY: the host word type. Needed for constructing
532 arguments of type 'HWord' to be passed to helper functions.
533 Ity_I32 or Ity_I64 only. */
534 IRType hWordTy;
535 }
536 MCEnv;
537
538/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
539 demand), as they are encountered. This is for two reasons.
540
541 (1) (less important reason): Many original tmps are unused due to
542 initial IR optimisation, and we do not want to spaces in tables
543 tracking them.
544
545 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
546 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000547 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000548 It is necessary to support making multiple assignments to a shadow
549 -- specifically, after testing a shadow for definedness, it needs
550 to be made defined. But IR's SSA property disallows this.
551
552 (2) (more important reason): Therefore, when a shadow needs to get
553 a new value, a new temporary is created, the value is assigned to
554 that, and the tmpMap is updated to reflect the new binding.
555
556 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000557 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000558 there's a read-before-write error in the original tmps. The IR
559 sanity checker should catch all such anomalies, however.
560*/
561
562/* Find the tmp currently shadowing the given original tmp. If none
563 so far exists, allocate one. */
564static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
565{
sewardj69f9e3e2004-12-30 02:05:34 +0000566 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000567 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000568 mce->tmpMap[orig]
569 = newIRTemp(mce->bb->tyenv,
570 shadowType(mce->bb->tyenv->types[orig]));
571 }
572 return mce->tmpMap[orig];
573}
574
575/* Allocate a new shadow for the given original tmp. This means any
576 previous shadow is abandoned. This is needed because it is
577 necessary to give a new value to a shadow once it has been tested
578 for undefinedness, but unfortunately IR's SSA property disallows
579 this. Instead we must abandon the old shadow, allocate a new one
580 and use that instead. */
581static void newShadowTmp ( MCEnv* mce, IRTemp orig )
582{
sewardj69f9e3e2004-12-30 02:05:34 +0000583 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000584 mce->tmpMap[orig]
585 = newIRTemp(mce->bb->tyenv,
586 shadowType(mce->bb->tyenv->types[orig]));
587}
588
589
590/*------------------------------------------------------------*/
591/*--- IRAtoms -- a subset of IRExprs ---*/
592/*------------------------------------------------------------*/
593
594/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj496a58d2005-03-20 18:44:44 +0000595 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardjde8a5ae2004-11-06 14:20:54 +0000596 input, most of this code deals in atoms. Usefully, a value atom
597 always has a V-value which is also an atom: constants are shadowed
598 by constants, and temps are shadowed by the corresponding shadow
599 temporary. */
600
601typedef IRExpr IRAtom;
602
603/* (used for sanity checks only): is this an atom which looks
604 like it's from original code? */
605static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
606{
607 if (a1->tag == Iex_Const)
608 return True;
sewardj478646f2008-05-01 20:13:04 +0000609 if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < mce->n_originalTmps)
sewardjde8a5ae2004-11-06 14:20:54 +0000610 return True;
611 return False;
612}
613
614/* (used for sanity checks only): is this an atom which looks
615 like it's from shadow code? */
616static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
617{
618 if (a1->tag == Iex_Const)
619 return True;
sewardj478646f2008-05-01 20:13:04 +0000620 if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= mce->n_originalTmps)
sewardjde8a5ae2004-11-06 14:20:54 +0000621 return True;
622 return False;
623}
624
625/* (used for sanity checks only): check that both args are atoms and
626 are identically-kinded. */
627static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
628{
sewardj478646f2008-05-01 20:13:04 +0000629 if (a1->tag == Iex_RdTmp && a1->tag == Iex_RdTmp)
sewardjde8a5ae2004-11-06 14:20:54 +0000630 return True;
631 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
632 return True;
633 return False;
634}
635
636
637/*------------------------------------------------------------*/
638/*--- Type management ---*/
639/*------------------------------------------------------------*/
640
641/* Shadow state is always accessed using integer types. This returns
642 an integer type with the same size (as per sizeofIRType) as the
643 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000644 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000645
646static IRType shadowType ( IRType ty )
647{
648 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000649 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000650 case Ity_I8:
651 case Ity_I16:
652 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000653 case Ity_I64: return ty;
654 case Ity_F32: return Ity_I32;
655 case Ity_F64: return Ity_I64;
656 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000657 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000658 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000659 }
660}
661
662/* Produce a 'defined' value of the given shadow type. Should only be
663 supplied shadow types (Bit/I8/I16/I32/UI64). */
664static IRExpr* definedOfType ( IRType ty ) {
665 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000666 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
667 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
668 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
669 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
670 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
671 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
672 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000673 }
674}
675
676
677/*------------------------------------------------------------*/
678/*--- Constructing IR fragments ---*/
679/*------------------------------------------------------------*/
680
681/* assign value to tmp */
682#define assign(_bb,_tmp,_expr) \
sewardj478646f2008-05-01 20:13:04 +0000683 addStmtToIRSB((_bb), IRStmt_WrTmp((_tmp),(_expr)))
sewardjde8a5ae2004-11-06 14:20:54 +0000684
685/* add stmt to a bb */
686#define stmt(_bb,_stmt) \
sewardjf6c8ebf2007-02-06 01:52:52 +0000687 addStmtToIRSB((_bb), (_stmt))
sewardjde8a5ae2004-11-06 14:20:54 +0000688
689/* build various kinds of expressions */
690#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
691#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
692#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
693#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
694#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
695#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000696#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardj478646f2008-05-01 20:13:04 +0000697#define mkexpr(_tmp) IRExpr_RdTmp((_tmp))
sewardjde8a5ae2004-11-06 14:20:54 +0000698
699/* bind the given expression to a new temporary, and return the
700 temporary. This effectively converts an arbitrary expression into
701 an atom. */
702static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
703 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
704 assign(mce->bb, t, e);
705 return mkexpr(t);
706}
707
708
709/*------------------------------------------------------------*/
710/*--- Constructing definedness primitive ops ---*/
711/*------------------------------------------------------------*/
712
713/* --------- Defined-if-either-defined --------- */
714
715static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000716 tl_assert(isShadowAtom(mce,a1));
717 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000718 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
719}
720
721static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000722 tl_assert(isShadowAtom(mce,a1));
723 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000724 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
725}
726
727static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000728 tl_assert(isShadowAtom(mce,a1));
729 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000730 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
731}
732
sewardj69f9e3e2004-12-30 02:05:34 +0000733static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
734 tl_assert(isShadowAtom(mce,a1));
735 tl_assert(isShadowAtom(mce,a2));
736 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
737}
738
sewardjf0c1c582005-02-07 23:47:38 +0000739static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000740 tl_assert(isShadowAtom(mce,a1));
741 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000742 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000743}
744
sewardjde8a5ae2004-11-06 14:20:54 +0000745/* --------- Undefined-if-either-undefined --------- */
746
747static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000748 tl_assert(isShadowAtom(mce,a1));
749 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000750 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
751}
752
753static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000754 tl_assert(isShadowAtom(mce,a1));
755 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000756 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
757}
758
759static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000760 tl_assert(isShadowAtom(mce,a1));
761 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000762 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
763}
764
765static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000766 tl_assert(isShadowAtom(mce,a1));
767 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000768 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
769}
770
sewardjf0c1c582005-02-07 23:47:38 +0000771static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000772 tl_assert(isShadowAtom(mce,a1));
773 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000774 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000775}
776
777static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000778 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000779 case Ity_I8: return mkUifU8(mce, a1, a2);
780 case Ity_I16: return mkUifU16(mce, a1, a2);
781 case Ity_I32: return mkUifU32(mce, a1, a2);
782 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardjf0c1c582005-02-07 23:47:38 +0000783 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000784 default:
785 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000786 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000787 }
788}
789
790/* --------- The Left-family of operations. --------- */
791
792static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000793 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000794 /* It's safe to duplicate a1 since it's only an atom */
795 return assignNew(mce, Ity_I8,
796 binop(Iop_Or8, a1,
797 assignNew(mce, Ity_I8,
798 /* unop(Iop_Neg8, a1)))); */
799 binop(Iop_Sub8, mkU8(0), a1) )));
800}
801
802static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000803 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000804 /* It's safe to duplicate a1 since it's only an atom */
805 return assignNew(mce, Ity_I16,
806 binop(Iop_Or16, a1,
807 assignNew(mce, Ity_I16,
808 /* unop(Iop_Neg16, a1)))); */
809 binop(Iop_Sub16, mkU16(0), a1) )));
810}
811
812static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000813 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000814 /* It's safe to duplicate a1 since it's only an atom */
815 return assignNew(mce, Ity_I32,
816 binop(Iop_Or32, a1,
817 assignNew(mce, Ity_I32,
818 /* unop(Iop_Neg32, a1)))); */
819 binop(Iop_Sub32, mkU32(0), a1) )));
820}
821
822/* --------- 'Improvement' functions for AND/OR. --------- */
823
824/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
825 defined (0); all other -> undefined (1).
826*/
827static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
828{
sewardj69f9e3e2004-12-30 02:05:34 +0000829 tl_assert(isOriginalAtom(mce, data));
830 tl_assert(isShadowAtom(mce, vbits));
831 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000832 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
833}
834
sewardj3598ef92004-11-11 02:13:30 +0000835static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
836{
sewardj69f9e3e2004-12-30 02:05:34 +0000837 tl_assert(isOriginalAtom(mce, data));
838 tl_assert(isShadowAtom(mce, vbits));
839 tl_assert(sameKindedAtoms(data, vbits));
sewardj3598ef92004-11-11 02:13:30 +0000840 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
841}
842
sewardjde8a5ae2004-11-06 14:20:54 +0000843static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
844{
sewardj69f9e3e2004-12-30 02:05:34 +0000845 tl_assert(isOriginalAtom(mce, data));
846 tl_assert(isShadowAtom(mce, vbits));
847 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000848 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
849}
850
sewardj69f9e3e2004-12-30 02:05:34 +0000851static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
852{
853 tl_assert(isOriginalAtom(mce, data));
854 tl_assert(isShadowAtom(mce, vbits));
855 tl_assert(sameKindedAtoms(data, vbits));
856 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
857}
858
sewardjf0c1c582005-02-07 23:47:38 +0000859static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000860{
861 tl_assert(isOriginalAtom(mce, data));
862 tl_assert(isShadowAtom(mce, vbits));
863 tl_assert(sameKindedAtoms(data, vbits));
sewardjf0c1c582005-02-07 23:47:38 +0000864 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj69f9e3e2004-12-30 02:05:34 +0000865}
866
sewardjde8a5ae2004-11-06 14:20:54 +0000867/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
868 defined (0); all other -> undefined (1).
869*/
870static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
871{
sewardj69f9e3e2004-12-30 02:05:34 +0000872 tl_assert(isOriginalAtom(mce, data));
873 tl_assert(isShadowAtom(mce, vbits));
874 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000875 return assignNew(
876 mce, Ity_I8,
877 binop(Iop_Or8,
878 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
879 vbits) );
880}
881
882static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
883{
sewardj69f9e3e2004-12-30 02:05:34 +0000884 tl_assert(isOriginalAtom(mce, data));
885 tl_assert(isShadowAtom(mce, vbits));
886 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000887 return assignNew(
888 mce, Ity_I16,
889 binop(Iop_Or16,
890 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
891 vbits) );
892}
893
894static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
895{
sewardj69f9e3e2004-12-30 02:05:34 +0000896 tl_assert(isOriginalAtom(mce, data));
897 tl_assert(isShadowAtom(mce, vbits));
898 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000899 return assignNew(
900 mce, Ity_I32,
901 binop(Iop_Or32,
902 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
903 vbits) );
904}
905
sewardj69f9e3e2004-12-30 02:05:34 +0000906static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
907{
908 tl_assert(isOriginalAtom(mce, data));
909 tl_assert(isShadowAtom(mce, vbits));
910 tl_assert(sameKindedAtoms(data, vbits));
911 return assignNew(
912 mce, Ity_I64,
913 binop(Iop_Or64,
914 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
915 vbits) );
916}
917
sewardjf0c1c582005-02-07 23:47:38 +0000918static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000919{
920 tl_assert(isOriginalAtom(mce, data));
921 tl_assert(isShadowAtom(mce, vbits));
922 tl_assert(sameKindedAtoms(data, vbits));
923 return assignNew(
924 mce, Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +0000925 binop(Iop_OrV128,
926 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj69f9e3e2004-12-30 02:05:34 +0000927 vbits) );
928}
929
sewardjde8a5ae2004-11-06 14:20:54 +0000930/* --------- Pessimising casts. --------- */
931
932static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
933{
sewardj8fc93742004-11-22 11:29:33 +0000934 IRType ty;
935 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000936 /* Note, dst_ty is a shadow type, not an original type. */
937 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000938 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000939 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
940 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000941 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000942 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000943 tmp1 = vbits;
944 break;
945 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000946 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000947 break;
948 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000949 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000950 break;
951 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000952 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000953 break;
954 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000955 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000956 break;
957 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000958 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000959 }
sewardj69f9e3e2004-12-30 02:05:34 +0000960 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000961 /* Now widen up to the dst type. */
962 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000963 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000964 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000965 case Ity_I8:
966 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000967 case Ity_I16:
968 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
969 case Ity_I32:
970 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
971 case Ity_I64:
972 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000973 case Ity_V128:
974 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardjf0c1c582005-02-07 23:47:38 +0000975 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000976 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000977 default:
978 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000979 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +0000980 }
981}
982
983
984/*------------------------------------------------------------*/
985/*--- Emit a test and complaint if something is undefined. ---*/
986/*------------------------------------------------------------*/
987
988/* Set the annotations on a dirty helper to indicate that the stack
989 pointer and instruction pointers might be read. This is the
990 behaviour of all 'emit-a-complaint' style functions we might
991 call. */
992
993static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
994 di->nFxState = 2;
995 di->fxState[0].fx = Ifx_Read;
996 di->fxState[0].offset = mce->layout->offset_SP;
997 di->fxState[0].size = mce->layout->sizeof_SP;
998 di->fxState[1].fx = Ifx_Read;
999 di->fxState[1].offset = mce->layout->offset_IP;
1000 di->fxState[1].size = mce->layout->sizeof_IP;
1001}
1002
1003
1004/* Check the supplied **original** atom for undefinedness, and emit a
1005 complaint if so. Once that happens, mark it as defined. This is
1006 possible because the atom is either a tmp or literal. If it's a
1007 tmp, it will be shadowed by a tmp, and so we can set the shadow to
1008 be defined. In fact as mentioned above, we will have to allocate a
1009 new tmp to carry the new 'defined' shadow value, and update the
1010 original->tmp mapping accordingly; we cannot simply assign a new
1011 value to an existing shadow tmp as this breaks SSAness -- resulting
1012 in the post-instrumentation sanity checker spluttering in disapproval.
1013*/
1014static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
1015{
sewardj8fc93742004-11-22 11:29:33 +00001016 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001017 IRType ty;
1018 Int sz;
sewardj8fc93742004-11-22 11:29:33 +00001019 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +00001020 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +00001021
sewardjde8a5ae2004-11-06 14:20:54 +00001022 /* Since the original expression is atomic, there's no duplicated
1023 work generated by making multiple V-expressions for it. So we
1024 don't really care about the possibility that someone else may
1025 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +00001026 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +00001027 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001028 tl_assert(isShadowAtom(mce, vatom));
1029 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001030
sewardj8fc93742004-11-22 11:29:33 +00001031 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +00001032
1033 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +00001034 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +00001035
sewardj8fc93742004-11-22 11:29:33 +00001036 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +00001037 /* cond will be 0 if all defined, and 1 if any not defined. */
1038
sewardj3598ef92004-11-11 02:13:30 +00001039 switch (sz) {
1040 case 0:
1041 di = unsafeIRDirty_0_N( 0/*regparms*/,
1042 "MC_(helperc_value_check0_fail)",
1043 &MC_(helperc_value_check0_fail),
1044 mkIRExprVec_0()
1045 );
1046 break;
1047 case 1:
1048 di = unsafeIRDirty_0_N( 0/*regparms*/,
1049 "MC_(helperc_value_check1_fail)",
1050 &MC_(helperc_value_check1_fail),
1051 mkIRExprVec_0()
1052 );
1053 break;
1054 case 4:
1055 di = unsafeIRDirty_0_N( 0/*regparms*/,
1056 "MC_(helperc_value_check4_fail)",
1057 &MC_(helperc_value_check4_fail),
1058 mkIRExprVec_0()
1059 );
1060 break;
1061 default:
1062 di = unsafeIRDirty_0_N( 1/*regparms*/,
1063 "MC_(helperc_complain_undef)",
1064 &MC_(helperc_complain_undef),
1065 mkIRExprVec_1( mkIRExpr_HWord( sz ))
1066 );
1067 break;
1068 }
sewardjde8a5ae2004-11-06 14:20:54 +00001069 di->guard = cond;
1070 setHelperAnns( mce, di );
1071 stmt( mce->bb, IRStmt_Dirty(di));
1072
1073 /* Set the shadow tmp to be defined. First, update the
1074 orig->shadow tmp mapping to reflect the fact that this shadow is
1075 getting a new value. */
sewardj496a58d2005-03-20 18:44:44 +00001076 tl_assert(isIRAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001077 /* sameKindedAtoms ... */
sewardj478646f2008-05-01 20:13:04 +00001078 if (vatom->tag == Iex_RdTmp) {
1079 tl_assert(atom->tag == Iex_RdTmp);
1080 newShadowTmp(mce, atom->Iex.RdTmp.tmp);
1081 assign(mce->bb, findShadowTmp(mce, atom->Iex.RdTmp.tmp),
sewardjde8a5ae2004-11-06 14:20:54 +00001082 definedOfType(ty));
1083 }
1084}
1085
1086
1087/*------------------------------------------------------------*/
1088/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
1089/*------------------------------------------------------------*/
1090
1091/* Examine the always-defined sections declared in layout to see if
1092 the (offset,size) section is within one. Note, is is an error to
1093 partially fall into such a region: (offset,size) should either be
1094 completely in such a region or completely not-in such a region.
1095*/
1096static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1097{
1098 Int minoffD, maxoffD, i;
1099 Int minoff = offset;
1100 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001101 tl_assert((minoff & ~0xFFFF) == 0);
1102 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001103
1104 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1105 minoffD = mce->layout->alwaysDefd[i].offset;
1106 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001107 tl_assert((minoffD & ~0xFFFF) == 0);
1108 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001109
1110 if (maxoff < minoffD || maxoffD < minoff)
1111 continue; /* no overlap */
1112 if (minoff >= minoffD && maxoff <= maxoffD)
1113 return True; /* completely contained in an always-defd section */
1114
sewardj69f9e3e2004-12-30 02:05:34 +00001115 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001116 }
1117 return False; /* could not find any containing section */
1118}
1119
1120
1121/* Generate into bb suitable actions to shadow this Put. If the state
1122 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001123 supplied V bits to the shadow state. We can pass in either an
1124 original atom or a V-atom, but not both. In the former case the
1125 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001126*/
1127static
sewardj3598ef92004-11-11 02:13:30 +00001128void do_shadow_PUT ( MCEnv* mce, Int offset,
1129 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001130{
sewardj8fc93742004-11-22 11:29:33 +00001131 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001132 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001133 tl_assert(!vatom);
1134 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001135 vatom = expr2vbits( mce, atom );
1136 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001137 tl_assert(vatom);
1138 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001139 }
1140
sewardj8fc93742004-11-22 11:29:33 +00001141 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001142 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001143 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1144 /* later: no ... */
1145 /* emit code to emit a complaint if any of the vbits are 1. */
1146 /* complainIfUndefined(mce, atom); */
1147 } else {
1148 /* Do a plain shadow Put. */
1149 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1150 }
1151}
1152
1153
1154/* Return an expression which contains the V bits corresponding to the
1155 given GETI (passed in in pieces).
1156*/
1157static
1158void do_shadow_PUTI ( MCEnv* mce,
sewardj478646f2008-05-01 20:13:04 +00001159 IRRegArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
sewardjde8a5ae2004-11-06 14:20:54 +00001160{
sewardj8fc93742004-11-22 11:29:33 +00001161 IRAtom* vatom;
1162 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001163 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001164
sewardj69f9e3e2004-12-30 02:05:34 +00001165 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001166 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001167 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001168 ty = descr->elemTy;
1169 tyS = shadowType(ty);
1170 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001171 tl_assert(ty != Ity_I1);
1172 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001173 complainIfUndefined(mce,ix);
1174 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1175 /* later: no ... */
1176 /* emit code to emit a complaint if any of the vbits are 1. */
1177 /* complainIfUndefined(mce, atom); */
1178 } else {
1179 /* Do a cloned version of the Put that refers to the shadow
1180 area. */
sewardj478646f2008-05-01 20:13:04 +00001181 IRRegArray* new_descr
1182 = mkIRRegArray( descr->base + mce->layout->total_sizeB,
sewardjde8a5ae2004-11-06 14:20:54 +00001183 tyS, descr->nElems);
1184 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1185 }
1186}
1187
1188
1189/* Return an expression which contains the V bits corresponding to the
1190 given GET (passed in in pieces).
1191*/
1192static
1193IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1194{
1195 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001196 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001197 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1198 /* Always defined, return all zeroes of the relevant type */
1199 return definedOfType(tyS);
1200 } else {
1201 /* return a cloned version of the Get that refers to the shadow
1202 area. */
1203 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1204 }
1205}
1206
1207
1208/* Return an expression which contains the V bits corresponding to the
1209 given GETI (passed in in pieces).
1210*/
1211static
sewardj478646f2008-05-01 20:13:04 +00001212IRExpr* shadow_GETI ( MCEnv* mce, IRRegArray* descr, IRAtom* ix, Int bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001213{
1214 IRType ty = descr->elemTy;
1215 IRType tyS = shadowType(ty);
1216 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001217 tl_assert(ty != Ity_I1);
1218 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001219 complainIfUndefined(mce,ix);
1220 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1221 /* Always defined, return all zeroes of the relevant type */
1222 return definedOfType(tyS);
1223 } else {
1224 /* return a cloned version of the Get that refers to the shadow
1225 area. */
sewardj478646f2008-05-01 20:13:04 +00001226 IRRegArray* new_descr
1227 = mkIRRegArray( descr->base + mce->layout->total_sizeB,
sewardjde8a5ae2004-11-06 14:20:54 +00001228 tyS, descr->nElems);
1229 return IRExpr_GetI( new_descr, ix, bias );
1230 }
1231}
1232
1233
1234/*------------------------------------------------------------*/
1235/*--- Generating approximations for unknown operations, ---*/
1236/*--- using lazy-propagate semantics ---*/
1237/*------------------------------------------------------------*/
1238
1239/* Lazy propagation of undefinedness from two values, resulting in the
1240 specified shadow type.
1241*/
1242static
1243IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1244{
1245 /* force everything via 32-bit intermediaries. */
1246 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001247 tl_assert(isShadowAtom(mce,va1));
1248 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001249 at = mkPCastTo(mce, Ity_I32, va1);
1250 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1251 at = mkPCastTo(mce, finalVty, at);
1252 return at;
1253}
1254
1255
1256/* Do the lazy propagation game from a null-terminated vector of
1257 atoms. This is presumably the arguments to a helper call, so the
1258 IRCallee info is also supplied in order that we can know which
1259 arguments should be ignored (via the .mcx_mask field).
1260*/
1261static
1262IRAtom* mkLazyN ( MCEnv* mce,
1263 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1264{
1265 Int i;
1266 IRAtom* here;
1267 IRAtom* curr = definedOfType(Ity_I32);
1268 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001269 tl_assert(i < 32);
1270 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001271 /* Only take notice of this arg if the callee's mc-exclusion
1272 mask does not say it is to be excluded. */
1273 if (cee->mcx_mask & (1<<i)) {
1274 /* the arg is to be excluded from definedness checking. Do
1275 nothing. */
1276 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1277 } else {
1278 /* calculate the arg's definedness, and pessimistically merge
1279 it in. */
1280 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1281 curr = mkUifU32(mce, here, curr);
1282 }
1283 }
1284 return mkPCastTo(mce, finalVtype, curr );
1285}
1286
1287
1288/*------------------------------------------------------------*/
1289/*--- Generating expensive sequences for exact carry-chain ---*/
1290/*--- propagation in add/sub and related operations. ---*/
1291/*------------------------------------------------------------*/
1292
1293static
1294IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1295 IRAtom* aa, IRAtom* bb )
1296{
sewardj69f9e3e2004-12-30 02:05:34 +00001297 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001298 IRType ty;
1299 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001300
sewardj69f9e3e2004-12-30 02:05:34 +00001301 tl_assert(isShadowAtom(mce,qaa));
1302 tl_assert(isShadowAtom(mce,qbb));
1303 tl_assert(isOriginalAtom(mce,aa));
1304 tl_assert(isOriginalAtom(mce,bb));
1305 tl_assert(sameKindedAtoms(qaa,aa));
1306 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001307
sewardj8fc93742004-11-22 11:29:33 +00001308 ty = Ity_I32;
1309 opAND = Iop_And32;
1310 opOR = Iop_Or32;
1311 opXOR = Iop_Xor32;
1312 opNOT = Iop_Not32;
1313 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001314
1315 // a_min = aa & ~qaa
1316 a_min = assignNew(mce,ty,
1317 binop(opAND, aa,
1318 assignNew(mce,ty, unop(opNOT, qaa))));
1319
1320 // b_min = bb & ~qbb
1321 b_min = assignNew(mce,ty,
1322 binop(opAND, bb,
1323 assignNew(mce,ty, unop(opNOT, qbb))));
1324
1325 // a_max = aa | qaa
1326 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1327
1328 // b_max = bb | qbb
1329 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1330
1331 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1332 return
1333 assignNew(mce,ty,
1334 binop( opOR,
1335 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1336 assignNew(mce,ty,
1337 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1338 assignNew(mce,ty, binop(opADD, a_max, b_max))
1339 )
1340 )
1341 )
1342 );
1343}
1344
1345
1346/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001347/*--- Helpers for dealing with vector primops. ---*/
1348/*------------------------------------------------------------*/
1349
1350/* Vector pessimisation -- pessimise within each lane individually. */
1351
1352static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1353{
1354 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1355}
1356
1357static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1358{
1359 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1360}
1361
1362static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1363{
1364 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1365}
1366
1367static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1368{
1369 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1370}
1371
1372
1373/* Here's a simple scheme capable of handling ops derived from SSE1
1374 code and while only generating ops that can be efficiently
1375 implemented in SSE1. */
1376
1377/* All-lanes versions are straightforward:
1378
sewardjf0c1c582005-02-07 23:47:38 +00001379 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj69f9e3e2004-12-30 02:05:34 +00001380
1381 unary32Fx4(x,y) ==> PCast32x4(x#)
1382
1383 Lowest-lane-only versions are more complex:
1384
sewardjf0c1c582005-02-07 23:47:38 +00001385 binary32F0x4(x,y) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001386 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001387 PCast32(V128to32(UifUV128(x#,y#)))
sewardj69f9e3e2004-12-30 02:05:34 +00001388 )
1389
1390 This is perhaps not so obvious. In particular, it's faster to
sewardjf0c1c582005-02-07 23:47:38 +00001391 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj69f9e3e2004-12-30 02:05:34 +00001392 obvious scheme of taking the bottom 32 bits of each operand
1393 and doing a 32-bit UifU. Basically since UifU is fast and
1394 chopping lanes off vector values is slow.
1395
1396 Finally:
1397
sewardjf0c1c582005-02-07 23:47:38 +00001398 unary32F0x4(x) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001399 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001400 PCast32(V128to32(x#))
sewardj69f9e3e2004-12-30 02:05:34 +00001401 )
1402
1403 Where:
1404
1405 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1406 PCast32x4(v#) = CmpNEZ32x4(v#)
1407*/
1408
1409static
1410IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1411{
1412 IRAtom* at;
1413 tl_assert(isShadowAtom(mce, vatomX));
1414 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001415 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001416 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1417 return at;
1418}
1419
1420static
1421IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1422{
1423 IRAtom* at;
1424 tl_assert(isShadowAtom(mce, vatomX));
1425 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1426 return at;
1427}
1428
1429static
1430IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1431{
1432 IRAtom* at;
1433 tl_assert(isShadowAtom(mce, vatomX));
1434 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001435 at = mkUifUV128(mce, vatomX, vatomY);
1436 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001437 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001438 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001439 return at;
1440}
1441
1442static
1443IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1444{
1445 IRAtom* at;
1446 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001447 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001448 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001449 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001450 return at;
1451}
1452
1453/* --- ... and ... 64Fx2 versions of the same ... --- */
1454
1455static
1456IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1457{
1458 IRAtom* at;
1459 tl_assert(isShadowAtom(mce, vatomX));
1460 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001461 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001462 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1463 return at;
1464}
1465
1466static
1467IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1468{
1469 IRAtom* at;
1470 tl_assert(isShadowAtom(mce, vatomX));
1471 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1472 return at;
1473}
1474
1475static
1476IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1477{
1478 IRAtom* at;
1479 tl_assert(isShadowAtom(mce, vatomX));
1480 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001481 at = mkUifUV128(mce, vatomX, vatomY);
1482 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001483 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001484 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001485 return at;
1486}
1487
1488static
1489IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1490{
1491 IRAtom* at;
1492 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001493 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001494 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001495 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001496 return at;
1497}
1498
1499/* --- --- Vector saturated narrowing --- --- */
1500
1501/* This is quite subtle. What to do is simple:
1502
1503 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1504
1505 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1506
1507 Why this is right is not so simple. Consider a lane in the args,
1508 vatom1 or 2, doesn't matter.
1509
1510 After the PCast, that lane is all 0s (defined) or all
1511 1s(undefined).
1512
1513 Both signed and unsigned saturating narrowing of all 0s produces
1514 all 0s, which is what we want.
1515
1516 The all-1s case is more complex. Unsigned narrowing interprets an
1517 all-1s input as the largest unsigned integer, and so produces all
1518 1s as a result since that is the largest unsigned value at the
1519 smaller width.
1520
1521 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1522 to -1, so we still wind up with all 1s at the smaller width.
1523
1524 So: In short, pessimise the args, then apply the original narrowing
1525 op.
1526*/
1527static
sewardjf0c1c582005-02-07 23:47:38 +00001528IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardj69f9e3e2004-12-30 02:05:34 +00001529 IRAtom* vatom1, IRAtom* vatom2)
1530{
1531 IRAtom *at1, *at2, *at3;
1532 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1533 switch (narrow_op) {
1534 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1535 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1536 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardjf0c1c582005-02-07 23:47:38 +00001537 default: VG_(tool_panic)("vectorNarrowV128");
sewardj69f9e3e2004-12-30 02:05:34 +00001538 }
1539 tl_assert(isShadowAtom(mce,vatom1));
1540 tl_assert(isShadowAtom(mce,vatom2));
1541 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1542 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1543 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1544 return at3;
1545}
1546
1547
1548/* --- --- Vector integer arithmetic --- --- */
1549
1550/* Simple ... UifU the args and per-lane pessimise the results. */
1551static
1552IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1553{
1554 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001555 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001556 at = mkPCast8x16(mce, at);
1557 return at;
1558}
1559
1560static
1561IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1562{
1563 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001564 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001565 at = mkPCast16x8(mce, at);
1566 return at;
1567}
1568
1569static
1570IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1571{
1572 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001573 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001574 at = mkPCast32x4(mce, at);
1575 return at;
1576}
1577
1578static
1579IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1580{
1581 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001582 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001583 at = mkPCast64x2(mce, at);
1584 return at;
1585}
1586
1587
1588/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001589/*--- Generate shadow values from all kinds of IRExprs. ---*/
1590/*------------------------------------------------------------*/
1591
1592static
1593IRAtom* expr2vbits_Binop ( MCEnv* mce,
1594 IROp op,
1595 IRAtom* atom1, IRAtom* atom2 )
1596{
1597 IRType and_or_ty;
1598 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1599 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1600 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1601
1602 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1603 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1604
sewardj69f9e3e2004-12-30 02:05:34 +00001605 tl_assert(isOriginalAtom(mce,atom1));
1606 tl_assert(isOriginalAtom(mce,atom2));
1607 tl_assert(isShadowAtom(mce,vatom1));
1608 tl_assert(isShadowAtom(mce,vatom2));
1609 tl_assert(sameKindedAtoms(atom1,vatom1));
1610 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001611 switch (op) {
1612
sewardjf0c1c582005-02-07 23:47:38 +00001613 /* V128-bit SIMD (SSE2-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001614
1615 case Iop_ShrN16x8:
1616 case Iop_ShrN32x4:
1617 case Iop_ShrN64x2:
1618 case Iop_SarN16x8:
1619 case Iop_SarN32x4:
1620 case Iop_ShlN16x8:
1621 case Iop_ShlN32x4:
1622 case Iop_ShlN64x2:
1623 /* Same scheme as with all other shifts. */
1624 complainIfUndefined(mce, atom2);
1625 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1626
1627 case Iop_QSub8Ux16:
1628 case Iop_QSub8Sx16:
1629 case Iop_Sub8x16:
1630 case Iop_Min8Ux16:
1631 case Iop_Max8Ux16:
1632 case Iop_CmpGT8Sx16:
1633 case Iop_CmpEQ8x16:
1634 case Iop_Avg8Ux16:
1635 case Iop_QAdd8Ux16:
1636 case Iop_QAdd8Sx16:
1637 case Iop_Add8x16:
1638 return binary8Ix16(mce, vatom1, vatom2);
1639
1640 case Iop_QSub16Ux8:
1641 case Iop_QSub16Sx8:
1642 case Iop_Sub16x8:
1643 case Iop_Mul16x8:
1644 case Iop_MulHi16Sx8:
1645 case Iop_MulHi16Ux8:
1646 case Iop_Min16Sx8:
1647 case Iop_Max16Sx8:
1648 case Iop_CmpGT16Sx8:
1649 case Iop_CmpEQ16x8:
1650 case Iop_Avg16Ux8:
1651 case Iop_QAdd16Ux8:
1652 case Iop_QAdd16Sx8:
1653 case Iop_Add16x8:
1654 return binary16Ix8(mce, vatom1, vatom2);
1655
1656 case Iop_Sub32x4:
sewardj2fdd4162010-08-22 12:59:02 +00001657 case Iop_QSub32Sx4:
1658 case Iop_QSub32Ux4:
sewardj69f9e3e2004-12-30 02:05:34 +00001659 case Iop_CmpGT32Sx4:
1660 case Iop_CmpEQ32x4:
1661 case Iop_Add32x4:
sewardj2fdd4162010-08-22 12:59:02 +00001662 case Iop_QAdd32Ux4:
1663 case Iop_QAdd32Sx4:
sewardj69f9e3e2004-12-30 02:05:34 +00001664 return binary32Ix4(mce, vatom1, vatom2);
1665
1666 case Iop_Sub64x2:
sewardj2fdd4162010-08-22 12:59:02 +00001667 case Iop_QSub64Ux2:
1668 case Iop_QSub64Sx2:
sewardj69f9e3e2004-12-30 02:05:34 +00001669 case Iop_Add64x2:
sewardj2fdd4162010-08-22 12:59:02 +00001670 case Iop_QAdd64Ux2:
1671 case Iop_QAdd64Sx2:
sewardj69f9e3e2004-12-30 02:05:34 +00001672 return binary64Ix2(mce, vatom1, vatom2);
1673
1674 case Iop_QNarrow32Sx4:
1675 case Iop_QNarrow16Sx8:
1676 case Iop_QNarrow16Ux8:
sewardjf0c1c582005-02-07 23:47:38 +00001677 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001678
1679 case Iop_Sub64Fx2:
1680 case Iop_Mul64Fx2:
1681 case Iop_Min64Fx2:
1682 case Iop_Max64Fx2:
1683 case Iop_Div64Fx2:
1684 case Iop_CmpLT64Fx2:
1685 case Iop_CmpLE64Fx2:
1686 case Iop_CmpEQ64Fx2:
1687 case Iop_Add64Fx2:
1688 return binary64Fx2(mce, vatom1, vatom2);
1689
1690 case Iop_Sub64F0x2:
1691 case Iop_Mul64F0x2:
1692 case Iop_Min64F0x2:
1693 case Iop_Max64F0x2:
1694 case Iop_Div64F0x2:
1695 case Iop_CmpLT64F0x2:
1696 case Iop_CmpLE64F0x2:
1697 case Iop_CmpEQ64F0x2:
1698 case Iop_Add64F0x2:
1699 return binary64F0x2(mce, vatom1, vatom2);
1700
sewardjf0c1c582005-02-07 23:47:38 +00001701 /* V128-bit SIMD (SSE1-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001702
1703 case Iop_Sub32Fx4:
1704 case Iop_Mul32Fx4:
1705 case Iop_Min32Fx4:
1706 case Iop_Max32Fx4:
1707 case Iop_Div32Fx4:
1708 case Iop_CmpLT32Fx4:
1709 case Iop_CmpLE32Fx4:
1710 case Iop_CmpEQ32Fx4:
1711 case Iop_Add32Fx4:
1712 return binary32Fx4(mce, vatom1, vatom2);
1713
1714 case Iop_Sub32F0x4:
1715 case Iop_Mul32F0x4:
1716 case Iop_Min32F0x4:
1717 case Iop_Max32F0x4:
1718 case Iop_Div32F0x4:
1719 case Iop_CmpLT32F0x4:
1720 case Iop_CmpLE32F0x4:
1721 case Iop_CmpEQ32F0x4:
1722 case Iop_Add32F0x4:
1723 return binary32F0x4(mce, vatom1, vatom2);
1724
sewardjf0c1c582005-02-07 23:47:38 +00001725 /* V128-bit data-steering */
1726 case Iop_SetV128lo32:
1727 case Iop_SetV128lo64:
1728 case Iop_64HLtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001729 case Iop_InterleaveLO64x2:
1730 case Iop_InterleaveLO32x4:
1731 case Iop_InterleaveLO16x8:
1732 case Iop_InterleaveLO8x16:
1733 case Iop_InterleaveHI64x2:
1734 case Iop_InterleaveHI32x4:
1735 case Iop_InterleaveHI16x8:
1736 case Iop_InterleaveHI8x16:
1737 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1738
1739 /* Scalar floating point */
1740
sewardj478646f2008-05-01 20:13:04 +00001741 // case Iop_RoundF64:
sewardj1e3830f2011-03-14 11:27:26 +00001742 case Iop_F64toI64S:
1743 case Iop_I64StoF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001744 /* First arg is I32 (rounding mode), second is F64 or I64
1745 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001746 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1747
1748 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1749 /* Takes two F64 args. */
sewardj1e3830f2011-03-14 11:27:26 +00001750 case Iop_F64toI32S:
sewardj69f9e3e2004-12-30 02:05:34 +00001751 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001752 /* First arg is I32 (rounding mode), second is F64 (data). */
1753 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1754
sewardj1e3830f2011-03-14 11:27:26 +00001755 case Iop_F64toI16S:
sewardjde8a5ae2004-11-06 14:20:54 +00001756 /* First arg is I32 (rounding mode), second is F64 (data). */
1757 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1758
sewardj3598ef92004-11-11 02:13:30 +00001759 case Iop_ScaleF64:
1760 case Iop_Yl2xF64:
1761 case Iop_Yl2xp1F64:
1762 case Iop_PRemF64:
1763 case Iop_AtanF64:
1764 case Iop_AddF64:
1765 case Iop_DivF64:
1766 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001767 case Iop_MulF64:
1768 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1769
sewardj3598ef92004-11-11 02:13:30 +00001770 case Iop_CmpF64:
1771 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1772
sewardjde8a5ae2004-11-06 14:20:54 +00001773 /* non-FP after here */
1774
1775 case Iop_DivModU64to32:
1776 case Iop_DivModS64to32:
1777 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1778
sewardj3598ef92004-11-11 02:13:30 +00001779 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001780 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001781 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001782 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001783
1784 case Iop_MullS32:
1785 case Iop_MullU32: {
1786 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1787 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1788 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1789 }
1790
sewardj3598ef92004-11-11 02:13:30 +00001791 case Iop_MullS16:
1792 case Iop_MullU16: {
1793 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1794 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1795 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1796 }
1797
1798 case Iop_MullS8:
1799 case Iop_MullU8: {
1800 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1801 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1802 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1803 }
1804
sewardjde8a5ae2004-11-06 14:20:54 +00001805 case Iop_Add32:
1806# if 0
1807 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1808# endif
1809 case Iop_Sub32:
1810 case Iop_Mul32:
1811 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1812
sewardj3598ef92004-11-11 02:13:30 +00001813 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001814 case Iop_Add16:
1815 case Iop_Sub16:
1816 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1817
1818 case Iop_Sub8:
1819 case Iop_Add8:
1820 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1821
1822 case Iop_CmpLE32S: case Iop_CmpLE32U:
1823 case Iop_CmpLT32U: case Iop_CmpLT32S:
1824 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001825 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001826
sewardj3598ef92004-11-11 02:13:30 +00001827 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001828 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001829
1830 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001831 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001832
1833 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1834 /* Complain if the shift amount is undefined. Then simply
1835 shift the first arg's V bits by the real shift amount. */
1836 complainIfUndefined(mce, atom2);
1837 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1838
sewardj69f9e3e2004-12-30 02:05:34 +00001839 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001840 /* Same scheme as with 32-bit shifts. */
1841 complainIfUndefined(mce, atom2);
1842 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1843
sewardj3598ef92004-11-11 02:13:30 +00001844 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001845 /* Same scheme as with 32-bit shifts. */
1846 complainIfUndefined(mce, atom2);
1847 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1848
1849 case Iop_Shl64: case Iop_Shr64:
1850 /* Same scheme as with 32-bit shifts. */
1851 complainIfUndefined(mce, atom2);
1852 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1853
sewardjf0c1c582005-02-07 23:47:38 +00001854 case Iop_AndV128:
1855 uifu = mkUifUV128; difd = mkDifDV128;
1856 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001857 case Iop_And64:
1858 uifu = mkUifU64; difd = mkDifD64;
1859 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001860 case Iop_And32:
1861 uifu = mkUifU32; difd = mkDifD32;
1862 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001863 case Iop_And16:
1864 uifu = mkUifU16; difd = mkDifD16;
1865 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001866 case Iop_And8:
1867 uifu = mkUifU8; difd = mkDifD8;
1868 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1869
sewardjf0c1c582005-02-07 23:47:38 +00001870 case Iop_OrV128:
1871 uifu = mkUifUV128; difd = mkDifDV128;
1872 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001873 case Iop_Or64:
1874 uifu = mkUifU64; difd = mkDifD64;
1875 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001876 case Iop_Or32:
1877 uifu = mkUifU32; difd = mkDifD32;
1878 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1879 case Iop_Or16:
1880 uifu = mkUifU16; difd = mkDifD16;
1881 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1882 case Iop_Or8:
1883 uifu = mkUifU8; difd = mkDifD8;
1884 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1885
1886 do_And_Or:
1887 return
1888 assignNew(
1889 mce,
1890 and_or_ty,
1891 difd(mce, uifu(mce, vatom1, vatom2),
1892 difd(mce, improve(mce, atom1, vatom1),
1893 improve(mce, atom2, vatom2) ) ) );
1894
1895 case Iop_Xor8:
1896 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001897 case Iop_Xor16:
1898 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001899 case Iop_Xor32:
1900 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001901 case Iop_Xor64:
1902 return mkUifU64(mce, vatom1, vatom2);
sewardjf0c1c582005-02-07 23:47:38 +00001903 case Iop_XorV128:
1904 return mkUifUV128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001905
1906 default:
1907 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001908 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001909 }
1910}
1911
1912
1913static
1914IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1915{
1916 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001917 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001918 switch (op) {
1919
sewardj69f9e3e2004-12-30 02:05:34 +00001920 case Iop_Sqrt64Fx2:
1921 return unary64Fx2(mce, vatom);
1922
1923 case Iop_Sqrt64F0x2:
1924 return unary64F0x2(mce, vatom);
1925
1926 case Iop_Sqrt32Fx4:
1927 case Iop_RSqrt32Fx4:
1928 case Iop_Recip32Fx4:
1929 return unary32Fx4(mce, vatom);
1930
1931 case Iop_Sqrt32F0x4:
1932 case Iop_RSqrt32F0x4:
1933 case Iop_Recip32F0x4:
1934 return unary32F0x4(mce, vatom);
1935
sewardjf0c1c582005-02-07 23:47:38 +00001936 case Iop_32UtoV128:
1937 case Iop_64UtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001938 return assignNew(mce, Ity_V128, unop(op, vatom));
1939
sewardjde8a5ae2004-11-06 14:20:54 +00001940 case Iop_F32toF64:
sewardj1e3830f2011-03-14 11:27:26 +00001941 case Iop_I32StoF64:
sewardj3598ef92004-11-11 02:13:30 +00001942 case Iop_NegF64:
1943 case Iop_SinF64:
1944 case Iop_CosF64:
1945 case Iop_TanF64:
1946 case Iop_SqrtF64:
1947 case Iop_AbsF64:
1948 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001949 return mkPCastTo(mce, Ity_I64, vatom);
1950
sewardj3598ef92004-11-11 02:13:30 +00001951 case Iop_Clz32:
1952 case Iop_Ctz32:
1953 return mkPCastTo(mce, Ity_I32, vatom);
1954
1955 case Iop_32Sto64:
1956 case Iop_32Uto64:
sewardjf0c1c582005-02-07 23:47:38 +00001957 case Iop_V128to64:
1958 case Iop_V128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001959 return assignNew(mce, Ity_I64, unop(op, vatom));
1960
sewardjde8a5ae2004-11-06 14:20:54 +00001961 case Iop_64to32:
1962 case Iop_64HIto32:
1963 case Iop_1Uto32:
1964 case Iop_8Uto32:
1965 case Iop_16Uto32:
1966 case Iop_16Sto32:
1967 case Iop_8Sto32:
1968 return assignNew(mce, Ity_I32, unop(op, vatom));
1969
1970 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001971 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001972 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001973 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001974 return assignNew(mce, Ity_I16, unop(op, vatom));
1975
1976 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001977 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001978 case Iop_32to8:
1979 return assignNew(mce, Ity_I8, unop(op, vatom));
1980
1981 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001982 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001983
sewardj3598ef92004-11-11 02:13:30 +00001984 case Iop_ReinterpF64asI64:
1985 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001986 case Iop_ReinterpI32asF32:
sewardjf0c1c582005-02-07 23:47:38 +00001987 case Iop_NotV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001988 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00001989 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001990 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001991 case Iop_Not8:
1992 case Iop_Not1:
1993 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001994
sewardjde8a5ae2004-11-06 14:20:54 +00001995 default:
1996 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001997 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00001998 }
1999}
2000
2001
sewardj69f9e3e2004-12-30 02:05:34 +00002002/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00002003static
sewardj69f9e3e2004-12-30 02:05:34 +00002004IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00002005{
2006 void* helper;
sewardjde8c9872005-03-25 13:48:55 +00002007 HChar* hname;
sewardjde8a5ae2004-11-06 14:20:54 +00002008 IRDirty* di;
2009 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00002010 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00002011
sewardj69f9e3e2004-12-30 02:05:34 +00002012 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00002013
2014 /* First, emit a definedness test for the address. This also sets
2015 the address (shadow) to 'defined' following the test. */
2016 complainIfUndefined( mce, addr );
2017
2018 /* Now cook up a call to the relevant helper function, to read the
2019 data V bits from shadow memory. */
2020 ty = shadowType(ty);
2021 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00002022 case Ity_I64: helper = &MC_(helperc_LOADV8);
2023 hname = "MC_(helperc_LOADV8)";
2024 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002025 case Ity_I32: helper = &MC_(helperc_LOADV4);
2026 hname = "MC_(helperc_LOADV4)";
2027 break;
2028 case Ity_I16: helper = &MC_(helperc_LOADV2);
2029 hname = "MC_(helperc_LOADV2)";
2030 break;
2031 case Ity_I8: helper = &MC_(helperc_LOADV1);
2032 hname = "MC_(helperc_LOADV1)";
2033 break;
2034 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00002035 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00002036 }
2037
sewardj3598ef92004-11-11 02:13:30 +00002038 /* Generate the actual address into addrAct. */
2039 if (bias == 0) {
2040 addrAct = addr;
2041 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002042 IROp mkAdd;
2043 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00002044 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00002045 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2046 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2047 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00002048 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2049 }
2050
sewardjde8a5ae2004-11-06 14:20:54 +00002051 /* We need to have a place to park the V bits we're just about to
2052 read. */
2053 datavbits = newIRTemp(mce->bb->tyenv, ty);
2054 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00002055 1/*regparms*/, hname, helper,
2056 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00002057 setHelperAnns( mce, di );
2058 stmt( mce->bb, IRStmt_Dirty(di) );
2059
2060 return mkexpr(datavbits);
2061}
2062
2063
2064static
sewardj69f9e3e2004-12-30 02:05:34 +00002065IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
2066{
2067 IRAtom *v64hi, *v64lo;
2068 switch (shadowType(ty)) {
2069 case Ity_I8:
2070 case Ity_I16:
2071 case Ity_I32:
2072 case Ity_I64:
2073 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
2074 case Ity_V128:
2075 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
2076 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
2077 return assignNew( mce,
2078 Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +00002079 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj69f9e3e2004-12-30 02:05:34 +00002080 default:
2081 VG_(tool_panic)("expr2vbits_LDle");
2082 }
2083}
2084
2085
2086static
sewardjde8a5ae2004-11-06 14:20:54 +00002087IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00002088 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00002089{
2090 IRAtom *vbitsC, *vbits0, *vbitsX;
2091 IRType ty;
2092 /* Given Mux0X(cond,expr0,exprX), generate
2093 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2094 That is, steer the V bits like the originals, but trash the
2095 result if the steering value is undefined. This gives
2096 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00002097 tl_assert(isOriginalAtom(mce, cond));
2098 tl_assert(isOriginalAtom(mce, expr0));
2099 tl_assert(isOriginalAtom(mce, exprX));
sewardjde8a5ae2004-11-06 14:20:54 +00002100
2101 vbitsC = expr2vbits(mce, cond);
2102 vbits0 = expr2vbits(mce, expr0);
2103 vbitsX = expr2vbits(mce, exprX);
2104 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2105
2106 return
2107 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2108 mkPCastTo(mce, ty, vbitsC) );
2109}
2110
2111/* --------- This is the main expression-handling function. --------- */
2112
2113static
2114IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2115{
2116 switch (e->tag) {
2117
2118 case Iex_Get:
2119 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2120
2121 case Iex_GetI:
2122 return shadow_GETI( mce, e->Iex.GetI.descr,
2123 e->Iex.GetI.ix, e->Iex.GetI.bias );
2124
sewardj478646f2008-05-01 20:13:04 +00002125 case Iex_RdTmp:
2126 return IRExpr_RdTmp( findShadowTmp(mce, e->Iex.RdTmp.tmp) );
sewardjde8a5ae2004-11-06 14:20:54 +00002127
2128 case Iex_Const:
2129 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2130
2131 case Iex_Binop:
2132 return expr2vbits_Binop(
2133 mce,
2134 e->Iex.Binop.op,
2135 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2136 );
2137
2138 case Iex_Unop:
2139 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2140
sewardj478646f2008-05-01 20:13:04 +00002141 case Iex_Load:
2142 return expr2vbits_LDle( mce, e->Iex.Load.ty,
2143 e->Iex.Load.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002144
2145 case Iex_CCall:
2146 return mkLazyN( mce, e->Iex.CCall.args,
2147 e->Iex.CCall.retty,
2148 e->Iex.CCall.cee );
2149
2150 case Iex_Mux0X:
2151 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2152 e->Iex.Mux0X.exprX);
2153
2154 default:
2155 VG_(printf)("\n");
2156 ppIRExpr(e);
2157 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002158 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002159 }
2160}
2161
2162/*------------------------------------------------------------*/
2163/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2164/*------------------------------------------------------------*/
2165
2166/* Widen a value to the host word size. */
2167
2168static
2169IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2170{
sewardj69f9e3e2004-12-30 02:05:34 +00002171 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002172
sewardj8fc93742004-11-22 11:29:33 +00002173 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002174 tl_assert(isShadowAtom(mce,vatom));
2175
2176 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2177 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002178
sewardjde8a5ae2004-11-06 14:20:54 +00002179 if (tyH == Ity_I32) {
2180 switch (ty) {
2181 case Ity_I32: return vatom;
2182 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2183 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2184 default: goto unhandled;
2185 }
2186 } else {
2187 goto unhandled;
2188 }
2189 unhandled:
2190 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002191 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002192}
2193
2194
sewardj3598ef92004-11-11 02:13:30 +00002195/* Generate a shadow store. addr is always the original address atom.
2196 You can pass in either originals or V-bits for the data atom, but
2197 obviously not both. */
2198
sewardjde8a5ae2004-11-06 14:20:54 +00002199static
sewardj3598ef92004-11-11 02:13:30 +00002200void do_shadow_STle ( MCEnv* mce,
2201 IRAtom* addr, UInt bias,
2202 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002203{
sewardj69f9e3e2004-12-30 02:05:34 +00002204 IROp mkAdd;
2205 IRType ty, tyAddr;
2206 IRDirty *di, *diLo64, *diHi64;
2207 IRAtom *addrAct, *addrLo64, *addrHi64;
2208 IRAtom *vdataLo64, *vdataHi64;
2209 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002210 void* helper = NULL;
sewardj478646f2008-05-01 20:13:04 +00002211 HChar* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002212
2213 tyAddr = mce->hWordTy;
2214 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2215 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2216
2217 di = diLo64 = diHi64 = NULL;
2218 eBias = eBias0 = eBias8 = NULL;
2219 addrAct = addrLo64 = addrHi64 = NULL;
2220 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002221
sewardj3598ef92004-11-11 02:13:30 +00002222 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002223 tl_assert(!vdata);
2224 tl_assert(isOriginalAtom(mce, data));
2225 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002226 vdata = expr2vbits( mce, data );
2227 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002228 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002229 }
sewardjde8a5ae2004-11-06 14:20:54 +00002230
sewardj69f9e3e2004-12-30 02:05:34 +00002231 tl_assert(isOriginalAtom(mce,addr));
2232 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002233
2234 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002235
2236 /* First, emit a definedness test for the address. This also sets
2237 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002238 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002239
sewardj69f9e3e2004-12-30 02:05:34 +00002240 /* Now decide which helper function to call to write the data V
2241 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002242 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002243 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002244 case Ity_I64: helper = &MC_(helperc_STOREV8);
2245 hname = "MC_(helperc_STOREV8)";
2246 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002247 case Ity_I32: helper = &MC_(helperc_STOREV4);
2248 hname = "MC_(helperc_STOREV4)";
2249 break;
2250 case Ity_I16: helper = &MC_(helperc_STOREV2);
2251 hname = "MC_(helperc_STOREV2)";
2252 break;
2253 case Ity_I8: helper = &MC_(helperc_STOREV1);
2254 hname = "MC_(helperc_STOREV1)";
2255 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002256 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002257 }
2258
sewardj69f9e3e2004-12-30 02:05:34 +00002259 if (ty == Ity_V128) {
2260
sewardjf0c1c582005-02-07 23:47:38 +00002261 /* V128-bit case */
sewardj69f9e3e2004-12-30 02:05:34 +00002262 /* See comment in next clause re 64-bit regparms */
2263 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2264 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
sewardjf0c1c582005-02-07 23:47:38 +00002265 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002266 diLo64 = unsafeIRDirty_0_N(
2267 1/*regparms*/, hname, helper,
2268 mkIRExprVec_2( addrLo64, vdataLo64 ));
2269
2270 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2271 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
sewardjf0c1c582005-02-07 23:47:38 +00002272 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002273 diHi64 = unsafeIRDirty_0_N(
2274 1/*regparms*/, hname, helper,
2275 mkIRExprVec_2( addrHi64, vdataHi64 ));
2276
2277 setHelperAnns( mce, diLo64 );
2278 setHelperAnns( mce, diHi64 );
2279 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2280 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2281
sewardj3598ef92004-11-11 02:13:30 +00002282 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002283
2284 /* 8/16/32/64-bit cases */
2285 /* Generate the actual address into addrAct. */
2286 if (bias == 0) {
2287 addrAct = addr;
2288 } else {
2289 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2290 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2291 }
2292
2293 if (ty == Ity_I64) {
2294 /* We can't do this with regparm 2 on 32-bit platforms, since
2295 the back ends aren't clever enough to handle 64-bit
2296 regparm args. Therefore be different. */
2297 di = unsafeIRDirty_0_N(
2298 1/*regparms*/, hname, helper,
2299 mkIRExprVec_2( addrAct, vdata ));
2300 } else {
2301 di = unsafeIRDirty_0_N(
2302 2/*regparms*/, hname, helper,
2303 mkIRExprVec_2( addrAct,
2304 zwidenToHostWord( mce, vdata )));
2305 }
2306 setHelperAnns( mce, di );
2307 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002308 }
2309
sewardjde8a5ae2004-11-06 14:20:54 +00002310}
2311
2312
sewardj3598ef92004-11-11 02:13:30 +00002313/* Do lazy pessimistic propagation through a dirty helper call, by
2314 looking at the annotations on it. This is the most complex part of
2315 Memcheck. */
2316
2317static IRType szToITy ( Int n )
2318{
2319 switch (n) {
2320 case 1: return Ity_I8;
2321 case 2: return Ity_I16;
2322 case 4: return Ity_I32;
2323 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002324 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002325 }
2326}
2327
2328static
2329void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2330{
sewardj69f9e3e2004-12-30 02:05:34 +00002331 Int i, n, offset, toDo, gSz, gOff;
2332 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002333 IRType tyAddr, tySrc, tyDst;
2334 IRTemp dst;
2335
2336 /* First check the guard. */
2337 complainIfUndefined(mce, d->guard);
2338
2339 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002340 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002341
2342 /* Inputs: unmasked args */
2343 for (i = 0; d->args[i]; i++) {
2344 if (d->cee->mcx_mask & (1<<i)) {
2345 /* ignore this arg */
2346 } else {
2347 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2348 curr = mkUifU32(mce, here, curr);
2349 }
2350 }
2351
2352 /* Inputs: guest state that we read. */
2353 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002354 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002355 if (d->fxState[i].fx == Ifx_Write)
2356 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002357
2358 /* Ignore any sections marked as 'always defined'. */
2359 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2360 if (0)
2361 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2362 d->fxState[i].offset, d->fxState[i].size );
2363 continue;
2364 }
2365
sewardj3598ef92004-11-11 02:13:30 +00002366 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002367 consider it. If larger than 8 bytes, deal with it in 8-byte
2368 chunks. */
2369 gSz = d->fxState[i].size;
2370 gOff = d->fxState[i].offset;
2371 tl_assert(gSz > 0);
2372 while (True) {
2373 if (gSz == 0) break;
2374 n = gSz <= 8 ? gSz : 8;
2375 /* update 'curr' with UifU of the state slice
2376 gOff .. gOff+n-1 */
2377 tySrc = szToITy( n );
2378 src = assignNew( mce, tySrc,
2379 shadow_GET(mce, gOff, tySrc ) );
2380 here = mkPCastTo( mce, Ity_I32, src );
2381 curr = mkUifU32(mce, here, curr);
2382 gSz -= n;
2383 gOff += n;
2384 }
2385
sewardj3598ef92004-11-11 02:13:30 +00002386 }
2387
2388 /* Inputs: memory. First set up some info needed regardless of
2389 whether we're doing reads or writes. */
2390 tyAddr = Ity_INVALID;
2391
2392 if (d->mFx != Ifx_None) {
2393 /* Because we may do multiple shadow loads/stores from the same
2394 base address, it's best to do a single test of its
2395 definedness right now. Post-instrumentation optimisation
2396 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002397 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002398 complainIfUndefined(mce, d->mAddr);
2399
2400 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002401 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2402 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002403 }
2404
2405 /* Deal with memory inputs (reads or modifies) */
2406 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2407 offset = 0;
2408 toDo = d->mSize;
2409 /* chew off 32-bit chunks */
2410 while (toDo >= 4) {
2411 here = mkPCastTo(
2412 mce, Ity_I32,
2413 expr2vbits_LDle ( mce, Ity_I32,
2414 d->mAddr, d->mSize - toDo )
2415 );
2416 curr = mkUifU32(mce, here, curr);
2417 toDo -= 4;
2418 }
2419 /* chew off 16-bit chunks */
2420 while (toDo >= 2) {
2421 here = mkPCastTo(
2422 mce, Ity_I32,
2423 expr2vbits_LDle ( mce, Ity_I16,
2424 d->mAddr, d->mSize - toDo )
2425 );
2426 curr = mkUifU32(mce, here, curr);
2427 toDo -= 2;
2428 }
sewardj69f9e3e2004-12-30 02:05:34 +00002429 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002430 }
2431
2432 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2433 all the inputs to the helper. Now we need to re-distribute the
2434 results to all destinations. */
2435
2436 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002437 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002438 dst = findShadowTmp(mce, d->tmp);
2439 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2440 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2441 }
2442
2443 /* Outputs: guest state that we write or modify. */
2444 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002445 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002446 if (d->fxState[i].fx == Ifx_Read)
2447 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002448 /* Ignore any sections marked as 'always defined'. */
2449 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2450 continue;
2451 /* This state element is written or modified. So we need to
2452 consider it. If larger than 8 bytes, deal with it in 8-byte
2453 chunks. */
2454 gSz = d->fxState[i].size;
2455 gOff = d->fxState[i].offset;
2456 tl_assert(gSz > 0);
2457 while (True) {
2458 if (gSz == 0) break;
2459 n = gSz <= 8 ? gSz : 8;
2460 /* Write suitably-casted 'curr' to the state slice
2461 gOff .. gOff+n-1 */
2462 tyDst = szToITy( n );
2463 do_shadow_PUT( mce, gOff,
2464 NULL, /* original atom */
2465 mkPCastTo( mce, tyDst, curr ) );
2466 gSz -= n;
2467 gOff += n;
2468 }
sewardj3598ef92004-11-11 02:13:30 +00002469 }
2470
2471 /* Outputs: memory that we write or modify. */
2472 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2473 offset = 0;
2474 toDo = d->mSize;
2475 /* chew off 32-bit chunks */
2476 while (toDo >= 4) {
2477 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2478 NULL, /* original data */
2479 mkPCastTo( mce, Ity_I32, curr ) );
2480 toDo -= 4;
2481 }
2482 /* chew off 16-bit chunks */
2483 while (toDo >= 2) {
2484 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2485 NULL, /* original data */
2486 mkPCastTo( mce, Ity_I16, curr ) );
2487 toDo -= 2;
2488 }
sewardj69f9e3e2004-12-30 02:05:34 +00002489 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002490 }
2491
2492}
2493
2494
sewardjde8a5ae2004-11-06 14:20:54 +00002495/*------------------------------------------------------------*/
2496/*--- Memcheck main ---*/
2497/*------------------------------------------------------------*/
2498
sewardj3598ef92004-11-11 02:13:30 +00002499static Bool isBogusAtom ( IRAtom* at )
2500{
2501 ULong n = 0;
2502 IRConst* con;
sewardj496a58d2005-03-20 18:44:44 +00002503 tl_assert(isIRAtom(at));
sewardj478646f2008-05-01 20:13:04 +00002504 if (at->tag == Iex_RdTmp)
sewardj3598ef92004-11-11 02:13:30 +00002505 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002506 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002507 con = at->Iex.Const.con;
2508 switch (con->tag) {
2509 case Ico_U8: n = (ULong)con->Ico.U8; break;
2510 case Ico_U16: n = (ULong)con->Ico.U16; break;
2511 case Ico_U32: n = (ULong)con->Ico.U32; break;
2512 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002513 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002514 }
2515 /* VG_(printf)("%llx\n", n); */
2516 return (n == 0xFEFEFEFF
2517 || n == 0x80808080
2518 || n == 0x1010101
2519 || n == 1010100);
2520}
2521
2522static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2523{
2524 Int i;
2525 IRExpr* e;
2526 switch (st->tag) {
sewardj478646f2008-05-01 20:13:04 +00002527 case Ist_WrTmp:
2528 e = st->Ist.WrTmp.data;
sewardj3598ef92004-11-11 02:13:30 +00002529 switch (e->tag) {
2530 case Iex_Get:
sewardj478646f2008-05-01 20:13:04 +00002531 case Iex_RdTmp:
sewardj3598ef92004-11-11 02:13:30 +00002532 return False;
2533 case Iex_Unop:
2534 return isBogusAtom(e->Iex.Unop.arg);
2535 case Iex_Binop:
2536 return isBogusAtom(e->Iex.Binop.arg1)
2537 || isBogusAtom(e->Iex.Binop.arg2);
2538 case Iex_Mux0X:
2539 return isBogusAtom(e->Iex.Mux0X.cond)
2540 || isBogusAtom(e->Iex.Mux0X.expr0)
2541 || isBogusAtom(e->Iex.Mux0X.exprX);
sewardj478646f2008-05-01 20:13:04 +00002542 case Iex_Load:
2543 return isBogusAtom(e->Iex.Load.addr);
sewardj3598ef92004-11-11 02:13:30 +00002544 case Iex_CCall:
2545 for (i = 0; e->Iex.CCall.args[i]; i++)
2546 if (isBogusAtom(e->Iex.CCall.args[i]))
2547 return True;
2548 return False;
2549 default:
2550 goto unhandled;
2551 }
2552 case Ist_Put:
2553 return isBogusAtom(st->Ist.Put.data);
sewardj478646f2008-05-01 20:13:04 +00002554 case Ist_Store:
2555 return isBogusAtom(st->Ist.Store.addr)
2556 || isBogusAtom(st->Ist.Store.data);
sewardj3598ef92004-11-11 02:13:30 +00002557 case Ist_Exit:
sewardj1ea1b612005-03-26 13:02:20 +00002558 return isBogusAtom(st->Ist.Exit.guard);
sewardj3598ef92004-11-11 02:13:30 +00002559 default:
2560 unhandled:
2561 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002562 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002563 }
2564}
sewardj3598ef92004-11-11 02:13:30 +00002565
sewardj478646f2008-05-01 20:13:04 +00002566IRSB* mc_instrument ( void* closureV,
2567 IRSB* bb_in, VexGuestLayout* layout,
2568 VexGuestExtents* vge,
sewardj1ea1b612005-03-26 13:02:20 +00002569 IRType gWordTy, IRType hWordTy )
sewardjde8a5ae2004-11-06 14:20:54 +00002570{
sewardj3598ef92004-11-11 02:13:30 +00002571 Bool verboze = False; //True;
2572
2573 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002574
2575 Int i, j, first_stmt;
2576 IRStmt* st;
2577 MCEnv mce;
2578
2579 /* Set up BB */
sewardjf6c8ebf2007-02-06 01:52:52 +00002580 IRSB* bb = emptyIRSB();
sewardj478646f2008-05-01 20:13:04 +00002581 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
2582 bb->next = deepCopyIRExpr(bb_in->next);
sewardjde8a5ae2004-11-06 14:20:54 +00002583 bb->jumpkind = bb_in->jumpkind;
2584
2585 /* Set up the running environment. Only .bb is modified as we go
2586 along. */
2587 mce.bb = bb;
2588 mce.layout = layout;
2589 mce.n_originalTmps = bb->tyenv->types_used;
2590 mce.hWordTy = hWordTy;
2591 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2592 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002593 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002594
2595 /* Iterate over the stmts. */
2596
2597 for (i = 0; i < bb_in->stmts_used; i++) {
2598 st = bb_in->stmts[i];
2599 if (!st) continue;
2600
sewardj69f9e3e2004-12-30 02:05:34 +00002601 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002602
2603 /*
2604 if (!hasBogusLiterals) {
2605 hasBogusLiterals = checkForBogusLiterals(st);
2606 if (hasBogusLiterals) {
2607 VG_(printf)("bogus: ");
2608 ppIRStmt(st);
2609 VG_(printf)("\n");
2610 }
2611 }
2612 */
sewardjde8a5ae2004-11-06 14:20:54 +00002613 first_stmt = bb->stmts_used;
2614
2615 if (verboze) {
2616 ppIRStmt(st);
2617 VG_(printf)("\n\n");
2618 }
2619
2620 switch (st->tag) {
2621
sewardj478646f2008-05-01 20:13:04 +00002622 case Ist_WrTmp:
2623 assign( bb, findShadowTmp(&mce, st->Ist.WrTmp.tmp),
2624 expr2vbits( &mce, st->Ist.WrTmp.data) );
sewardjde8a5ae2004-11-06 14:20:54 +00002625 break;
2626
2627 case Ist_Put:
2628 do_shadow_PUT( &mce,
2629 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002630 st->Ist.Put.data,
2631 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002632 break;
2633
2634 case Ist_PutI:
2635 do_shadow_PUTI( &mce,
2636 st->Ist.PutI.descr,
2637 st->Ist.PutI.ix,
2638 st->Ist.PutI.bias,
2639 st->Ist.PutI.data );
2640 break;
2641
sewardj478646f2008-05-01 20:13:04 +00002642 case Ist_Store:
2643 do_shadow_STle( &mce, st->Ist.Store.addr, 0/* addr bias */,
2644 st->Ist.Store.data,
sewardj3598ef92004-11-11 02:13:30 +00002645 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002646 break;
2647
2648 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002649 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002650 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002651 break;
2652
2653 case Ist_Dirty:
2654 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002655 break;
2656
sewardj1ea1b612005-03-26 13:02:20 +00002657 case Ist_IMark:
2658 case Ist_NoOp:
2659 break;
2660
sewardjde8a5ae2004-11-06 14:20:54 +00002661 default:
2662 VG_(printf)("\n");
2663 ppIRStmt(st);
2664 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002665 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002666
2667 } /* switch (st->tag) */
2668
2669 if (verboze) {
2670 for (j = first_stmt; j < bb->stmts_used; j++) {
2671 VG_(printf)(" ");
2672 ppIRStmt(bb->stmts[j]);
2673 VG_(printf)("\n");
2674 }
2675 VG_(printf)("\n");
2676 }
2677
sewardjf6c8ebf2007-02-06 01:52:52 +00002678 addStmtToIRSB(bb, st);
sewardjde8a5ae2004-11-06 14:20:54 +00002679
2680 }
2681
2682 /* Now we need to complain if the jump target is undefined. */
2683 first_stmt = bb->stmts_used;
2684
2685 if (verboze) {
2686 VG_(printf)("bb->next = ");
2687 ppIRExpr(bb->next);
2688 VG_(printf)("\n\n");
2689 }
2690
2691 complainIfUndefined( &mce, bb->next );
2692
2693 if (verboze) {
2694 for (j = first_stmt; j < bb->stmts_used; j++) {
2695 VG_(printf)(" ");
2696 ppIRStmt(bb->stmts[j]);
2697 VG_(printf)("\n");
2698 }
2699 VG_(printf)("\n");
2700 }
2701
2702 return bb;
2703}
cerionaee45242005-03-17 14:03:36 +00002704#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002705
2706/*--------------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00002707/*--- end test_main.c ---*/
sewardjde8a5ae2004-11-06 14:20:54 +00002708/*--------------------------------------------------------------------*/