blob: 802827cde0a2d38170890fe55461079fd96cf7b6 [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
sewardj89ae8472013-10-18 14:12:58 +000010 Copyright (C) 2004-2013 OpenWorks LLP
sewardj752f9062010-05-03 21:38:49 +000011 info@open-works.net
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
34*/
35
sewardjc97096c2004-06-30 09:28:04 +000036#include <stdio.h>
37#include <stdlib.h>
sewardjced9fe52004-07-07 11:55:36 +000038#include <assert.h>
sewardj9b1004e2004-10-30 22:25:40 +000039#include <string.h>
sewardjc97096c2004-06-30 09:28:04 +000040
sewardjced9fe52004-07-07 11:55:36 +000041#include "libvex_basictypes.h"
42#include "libvex.h"
sewardjc97096c2004-06-30 09:28:04 +000043
sewardjabe017e2004-10-29 23:42:36 +000044#include "test_main.h"
45
46
sewardjc97096c2004-06-30 09:28:04 +000047/*---------------------------------------------------------------*/
48/*--- Test ---*/
49/*---------------------------------------------------------------*/
50
sewardjce605f92004-07-05 14:39:15 +000051
sewardj2b515872004-07-05 20:50:45 +000052__attribute__ ((noreturn))
sewardj41f43bc2004-07-08 14:23:22 +000053static
sewardjce605f92004-07-05 14:39:15 +000054void failure_exit ( void )
55{
56 fprintf(stdout, "VEX did failure_exit. Bye.\n");
57 exit(1);
58}
59
sewardj41f43bc2004-07-08 14:23:22 +000060static
sewardj58277842005-02-07 03:11:17 +000061void log_bytes ( HChar* bytes, Int nbytes )
sewardjce605f92004-07-05 14:39:15 +000062{
63 fwrite ( bytes, 1, nbytes, stdout );
64}
65
sewardjced9fe52004-07-07 11:55:36 +000066#define N_LINEBUF 10000
sewardjde8c9872005-03-25 13:48:55 +000067static HChar linebuf[N_LINEBUF];
sewardjced9fe52004-07-07 11:55:36 +000068
cerion094d1392005-06-20 13:45:57 +000069#define N_ORIGBUF 10000
sewardj4459baa2004-09-10 20:00:46 +000070#define N_TRANSBUF 5000
sewardjced9fe52004-07-07 11:55:36 +000071
sewardj4459baa2004-09-10 20:00:46 +000072static UChar origbuf[N_ORIGBUF];
73static UChar transbuf[N_TRANSBUF];
sewardjced9fe52004-07-07 11:55:36 +000074
sewardj1f40a0a2004-07-21 12:28:07 +000075static Bool verbose = True;
sewardjced9fe52004-07-07 11:55:36 +000076
sewardj9b1004e2004-10-30 22:25:40 +000077/* Forwards */
sewardj478646f2008-05-01 20:13:04 +000078#if 1 /* UNUSED */
sewardj5f438dd2011-06-16 11:36:23 +000079//static IRSB* ac_instrument ( IRSB*, VexGuestLayout*, IRType );
sewardj478646f2008-05-01 20:13:04 +000080static
81IRSB* mc_instrument ( void* closureV,
82 IRSB* bb_in, VexGuestLayout* layout,
83 VexGuestExtents* vge,
84 IRType gWordTy, IRType hWordTy );
cerionaee45242005-03-17 14:03:36 +000085#endif
sewardj9b1004e2004-10-30 22:25:40 +000086
sewardjbc161a42011-06-07 21:28:38 +000087static Bool chase_into_not_ok ( void* opaque, Addr64 dst ) {
88 return False;
89}
90static UInt needs_self_check ( void* opaque, VexGuestExtents* vge ) {
91 return 0;
92}
sewardj9b1004e2004-10-30 22:25:40 +000093
sewardjced9fe52004-07-07 11:55:36 +000094int main ( int argc, char** argv )
sewardjce605f92004-07-05 14:39:15 +000095{
sewardjced9fe52004-07-07 11:55:36 +000096 FILE* f;
97 Int i;
sewardj4459baa2004-09-10 20:00:46 +000098 UInt u, sum;
sewardjced9fe52004-07-07 11:55:36 +000099 Addr32 orig_addr;
sewardjabe017e2004-10-29 23:42:36 +0000100 Int bb_number, n_bbs_done = 0;
sewardj72c72812005-01-19 11:49:45 +0000101 Int orig_nbytes, trans_used;
sewardjd887b862005-01-17 18:34:34 +0000102 VexTranslateResult tres;
sewardjb5bf2e02004-10-25 13:06:17 +0000103 VexControl vcon;
sewardj72c72812005-01-19 11:49:45 +0000104 VexGuestExtents vge;
sewardj18475c52013-01-26 11:37:51 +0000105 VexArchInfo vai_x86, vai_amd64, vai_ppc32, vai_arm;
sewardjdd40fdf2006-12-24 02:20:24 +0000106 VexAbiInfo vbi;
sewardj17c7f952005-12-15 14:02:34 +0000107 VexTranslateArgs vta;
sewardjced9fe52004-07-07 11:55:36 +0000108
109 if (argc != 2) {
sewardjc6f970f2012-04-02 21:54:49 +0000110 fprintf(stderr, "usage: vex file.orig\n");
sewardjced9fe52004-07-07 11:55:36 +0000111 exit(1);
112 }
113 f = fopen(argv[1], "r");
114 if (!f) {
115 fprintf(stderr, "can't open `%s'\n", argv[1]);
116 exit(1);
117 }
118
sewardjb5bf2e02004-10-25 13:06:17 +0000119 /* Run with default params. However, we can't allow bb chasing
120 since that causes the front end to get segfaults when it tries
sewardj5bd4d162004-11-10 13:02:48 +0000121 to read code outside the initial BB we hand it. So when calling
122 LibVEX_Translate, send in a chase-into predicate that always
123 returns False. */
sewardjb5bf2e02004-10-25 13:06:17 +0000124 LibVEX_default_VexControl ( &vcon );
sewardjb4952402004-10-26 13:24:50 +0000125 vcon.iropt_level = 2;
sewardj18475c52013-01-26 11:37:51 +0000126 vcon.guest_max_insns = 60;
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 */
sewardjb5bf2e02004-10-25 13:06:17 +0000130 &vcon );
sewardjced9fe52004-07-07 11:55:36 +0000131
sewardjea64e142004-07-22 16:47:21 +0000132
sewardjced9fe52004-07-07 11:55:36 +0000133 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +0000134
sewardj5f438dd2011-06-16 11:36:23 +0000135 __attribute__((unused))
136 char* unused1 = 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));
sewardj5f438dd2011-06-16 11:36:23 +0000149 __attribute__((unused))
150 char* unused2 = fgets(linebuf, N_LINEBUF,f);
sewardjced9fe52004-07-07 11:55:36 +0000151 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000152
sewardjced9fe52004-07-07 11:55:36 +0000153 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000154 if (verbose)
sewardj07a54cc2005-02-04 21:18:55 +0000155 printf("============ Basic Block %d, Done %d, "
sewardj4459baa2004-09-10 20:00:46 +0000156 "Start %x, nbytes %2d ============",
sewardj07a54cc2005-02-04 21:18:55 +0000157 bb_number, n_bbs_done-1, orig_addr, orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000158
sewardj18475c52013-01-26 11:37:51 +0000159 /* thumb ITstate analysis needs to examine the 18 bytes
160 preceding the first instruction. So let's leave the first 18
161 zeroed out. */
162 memset(origbuf, 0, sizeof(origbuf));
163
sewardjced9fe52004-07-07 11:55:36 +0000164 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
165 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000166 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
sewardj18475c52013-01-26 11:37:51 +0000167 origbuf[18+ i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000168 }
169
sewardj5117ce12006-01-27 21:20:15 +0000170 /* FIXME: put sensible values into the .hwcaps fields */
sewardj9e6491a2005-07-02 19:24:10 +0000171 LibVEX_default_VexArchInfo(&vai_x86);
sewardjc4356f02007-11-09 21:15:04 +0000172 vai_x86.hwcaps = VEX_HWCAPS_X86_SSE1
173 | VEX_HWCAPS_X86_SSE2 | VEX_HWCAPS_X86_SSE3;
sewardj9e6491a2005-07-02 19:24:10 +0000174
175 LibVEX_default_VexArchInfo(&vai_amd64);
sewardj5117ce12006-01-27 21:20:15 +0000176 vai_amd64.hwcaps = 0;
sewardj9e6491a2005-07-02 19:24:10 +0000177
178 LibVEX_default_VexArchInfo(&vai_ppc32);
sewardj5117ce12006-01-27 21:20:15 +0000179 vai_ppc32.hwcaps = 0;
florian9138b172013-08-03 19:36:55 +0000180 vai_ppc32.ppc_icache_line_szB = 128;
sewardj02ef7162005-06-30 12:50:50 +0000181
sewardj18475c52013-01-26 11:37:51 +0000182 LibVEX_default_VexArchInfo(&vai_arm);
183 vai_arm.hwcaps = VEX_HWCAPS_ARM_VFP3 | VEX_HWCAPS_ARM_NEON | 7;
184
sewardjdd40fdf2006-12-24 02:20:24 +0000185 LibVEX_default_VexAbiInfo(&vbi);
sewardjc6f970f2012-04-02 21:54:49 +0000186 vbi.guest_stack_redzone_size = 128;
sewardjaca070a2006-10-17 00:28:22 +0000187
sewardj17c7f952005-12-15 14:02:34 +0000188 /* ----- Set up args for LibVEX_Translate ----- */
sewardjc6f970f2012-04-02 21:54:49 +0000189
sewardj18475c52013-01-26 11:37:51 +0000190 vta.abiinfo_both = vbi;
191 vta.guest_bytes = &origbuf[18];
192 vta.guest_bytes_addr = (Addr64)orig_addr;
193 vta.callback_opaque = NULL;
194 vta.chase_into_ok = chase_into_not_ok;
195 vta.guest_extents = &vge;
196 vta.host_bytes = transbuf;
197 vta.host_bytes_size = N_TRANSBUF;
198 vta.host_bytes_used = &trans_used;
199
sewardjc4356f02007-11-09 21:15:04 +0000200#if 0 /* ppc32 -> ppc32 */
sewardj17c7f952005-12-15 14:02:34 +0000201 vta.arch_guest = VexArchPPC32;
202 vta.archinfo_guest = vai_ppc32;
203 vta.arch_host = VexArchPPC32;
204 vta.archinfo_host = vai_ppc32;
sewardj07a54cc2005-02-04 21:18:55 +0000205#endif
sewardjc279b3f2005-03-16 18:10:45 +0000206#if 0 /* amd64 -> amd64 */
sewardj17c7f952005-12-15 14:02:34 +0000207 vta.arch_guest = VexArchAMD64;
208 vta.archinfo_guest = vai_amd64;
209 vta.arch_host = VexArchAMD64;
210 vta.archinfo_host = vai_amd64;
sewardj07a54cc2005-02-04 21:18:55 +0000211#endif
sewardj18475c52013-01-26 11:37:51 +0000212#if 0 /* x86 -> x86 */
sewardj17c7f952005-12-15 14:02:34 +0000213 vta.arch_guest = VexArchX86;
214 vta.archinfo_guest = vai_x86;
215 vta.arch_host = VexArchX86;
216 vta.archinfo_host = vai_x86;
sewardjc279b3f2005-03-16 18:10:45 +0000217#endif
sewardj18475c52013-01-26 11:37:51 +0000218#if 1 /* arm -> arm */
219 vta.arch_guest = VexArchARM;
220 vta.archinfo_guest = vai_arm;
221 vta.arch_host = VexArchARM;
222 vta.archinfo_host = vai_arm;
223 /* ARM/Thumb only hacks, that are needed to keep the ITstate
224 analyser in the front end happy. */
225 vta.guest_bytes = &origbuf[18 +1];
226 vta.guest_bytes_addr = (Addr64)(&origbuf[18 +1]);
227#endif
sewardjc6f970f2012-04-02 21:54:49 +0000228
229#if 1 /* no instrumentation */
sewardj17c7f952005-12-15 14:02:34 +0000230 vta.instrument1 = NULL;
231 vta.instrument2 = NULL;
sewardj9e7448b2004-11-18 13:44:15 +0000232#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000233#if 0 /* addrcheck */
sewardj17c7f952005-12-15 14:02:34 +0000234 vta.instrument1 = ac_instrument;
235 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000236#endif
sewardjc6f970f2012-04-02 21:54:49 +0000237#if 0 /* memcheck */
sewardj17c7f952005-12-15 14:02:34 +0000238 vta.instrument1 = mc_instrument;
239 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000240#endif
sewardjbc161a42011-06-07 21:28:38 +0000241 vta.needs_self_check = needs_self_check;
sewardjc716aea2006-01-17 01:48:46 +0000242 vta.preamble_function = NULL;
sewardj17c7f952005-12-15 14:02:34 +0000243 vta.traceflags = TEST_FLAGS;
sewardjc6f970f2012-04-02 21:54:49 +0000244 vta.addProfInc = False;
sewardj18475c52013-01-26 11:37:51 +0000245 vta.sigill_diag = True;
sewardjc6f970f2012-04-02 21:54:49 +0000246
247 vta.disp_cp_chain_me_to_slowEP = (void*)0x12345678;
248 vta.disp_cp_chain_me_to_fastEP = (void*)0x12345679;
249 vta.disp_cp_xindir = (void*)0x1234567A;
250 vta.disp_cp_xassisted = (void*)0x1234567B;
sewardj17c7f952005-12-15 14:02:34 +0000251
sewardjc4356f02007-11-09 21:15:04 +0000252 vta.finaltidy = NULL;
253
sewardj17c7f952005-12-15 14:02:34 +0000254 for (i = 0; i < TEST_N_ITERS; i++)
255 tres = LibVEX_Translate ( &vta );
sewardjabe017e2004-10-29 23:42:36 +0000256
sewardjbc161a42011-06-07 21:28:38 +0000257 if (tres.status != VexTransOK)
258 printf("\ntres = %d\n", (Int)tres.status);
259 assert(tres.status == VexTransOK);
260 assert(tres.n_sc_extents == 0);
sewardj72c72812005-01-19 11:49:45 +0000261 assert(vge.n_used == 1);
262 assert((UInt)(vge.len[0]) == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000263
sewardj4459baa2004-09-10 20:00:46 +0000264 sum = 0;
265 for (i = 0; i < trans_used; i++)
266 sum += (UInt)transbuf[i];
sewardjde8c9872005-03-25 13:48:55 +0000267 printf ( " %6.2f ... %u\n",
268 (double)trans_used / (double)vge.len[0], sum );
sewardjced9fe52004-07-07 11:55:36 +0000269 }
270
271 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000272 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000273 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000274
sewardjce605f92004-07-05 14:39:15 +0000275 return 0;
276}
sewardj9b1004e2004-10-30 22:25:40 +0000277
278//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000279//////////////////////////////////////////////////////////////////////
280//////////////////////////////////////////////////////////////////////
281//////////////////////////////////////////////////////////////////////
282//////////////////////////////////////////////////////////////////////
283//////////////////////////////////////////////////////////////////////
284//////////////////////////////////////////////////////////////////////
285//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000286
sewardj1ea1b612005-03-26 13:02:20 +0000287#if 0 /* UNUSED */
288
sewardj9b1004e2004-10-30 22:25:40 +0000289static
sewardjde8a5ae2004-11-06 14:20:54 +0000290__attribute((noreturn))
sewardjde8c9872005-03-25 13:48:55 +0000291void panic ( HChar* s )
sewardj9b1004e2004-10-30 22:25:40 +0000292{
293 printf("\npanic: %s\n", s);
294 failure_exit();
295}
296
297static
sewardjf6c8ebf2007-02-06 01:52:52 +0000298IRSB* ac_instrument (IRSB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000299{
300/* Use this rather than eg. -1 because it's a UInt. */
301#define INVALID_DATA_SIZE 999999
302
303 Int i;
304 Int sz;
305 IRCallee* helper;
306 IRStmt* st;
307 IRExpr* data;
308 IRExpr* addr;
309 Bool needSz;
310
311 /* Set up BB */
sewardjf6c8ebf2007-02-06 01:52:52 +0000312 IRSB* bb = emptyIRSB();
sewardj9b1004e2004-10-30 22:25:40 +0000313 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
314 bb->next = dopyIRExpr(bb_in->next);
315 bb->jumpkind = bb_in->jumpkind;
316
317 /* No loads to consider in ->next. */
sewardj496a58d2005-03-20 18:44:44 +0000318 assert(isIRAtom(bb_in->next));
sewardj9b1004e2004-10-30 22:25:40 +0000319
320 for (i = 0; i < bb_in->stmts_used; i++) {
321 st = bb_in->stmts[i];
322 if (!st) continue;
323
324 switch (st->tag) {
325
326 case Ist_Tmp:
327 data = st->Ist.Tmp.data;
328 if (data->tag == Iex_LDle) {
329 addr = data->Iex.LDle.addr;
330 sz = sizeofIRType(data->Iex.LDle.ty);
331 needSz = False;
332 switch (sz) {
333 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000334 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000335 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000336 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000337 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000338 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000339 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000340 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000341 needSz = True; break;
342 }
343 if (needSz) {
sewardjf6c8ebf2007-02-06 01:52:52 +0000344 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000345 bb,
346 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000347 unsafeIRDirty_0_N( helper->regparms,
348 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000349 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
350 ));
351 } else {
sewardjf6c8ebf2007-02-06 01:52:52 +0000352 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000353 bb,
354 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000355 unsafeIRDirty_0_N( helper->regparms,
356 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000357 mkIRExprVec_1(addr) )
358 ));
359 }
360 }
361 break;
362
363 case Ist_STle:
364 data = st->Ist.STle.data;
365 addr = st->Ist.STle.addr;
sewardj496a58d2005-03-20 18:44:44 +0000366 assert(isIRAtom(data));
367 assert(isIRAtom(addr));
sewardj9b1004e2004-10-30 22:25:40 +0000368 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
369 needSz = False;
370 switch (sz) {
371 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000372 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000373 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000374 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000375 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000376 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000377 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000378 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000379 needSz = True; break;
380 }
381 if (needSz) {
sewardjf6c8ebf2007-02-06 01:52:52 +0000382 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000383 bb,
384 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000385 unsafeIRDirty_0_N( helper->regparms,
386 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000387 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
388 ));
389 } else {
sewardjf6c8ebf2007-02-06 01:52:52 +0000390 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000391 bb,
392 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000393 unsafeIRDirty_0_N( helper->regparms,
394 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000395 mkIRExprVec_1(addr) )
396 ));
397 }
398 break;
399
400 case Ist_Put:
sewardj496a58d2005-03-20 18:44:44 +0000401 assert(isIRAtom(st->Ist.Put.data));
sewardj9b1004e2004-10-30 22:25:40 +0000402 break;
403
404 case Ist_PutI:
sewardj496a58d2005-03-20 18:44:44 +0000405 assert(isIRAtom(st->Ist.PutI.ix));
406 assert(isIRAtom(st->Ist.PutI.data));
sewardj9b1004e2004-10-30 22:25:40 +0000407 break;
408
409 case Ist_Exit:
sewardj496a58d2005-03-20 18:44:44 +0000410 assert(isIRAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000411 break;
412
413 case Ist_Dirty:
414 /* If the call doesn't interact with memory, we ain't
415 interested. */
416 if (st->Ist.Dirty.details->mFx == Ifx_None)
417 break;
418 goto unhandled;
419
420 default:
421 unhandled:
422 printf("\n");
423 ppIRStmt(st);
424 printf("\n");
425 panic("addrcheck: unhandled IRStmt");
426 }
427
sewardjf6c8ebf2007-02-06 01:52:52 +0000428 addStmtToIRSB( bb, dopyIRStmt(st));
sewardj9b1004e2004-10-30 22:25:40 +0000429 }
430
431 return bb;
432}
cerionaee45242005-03-17 14:03:36 +0000433#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +0000434
435//////////////////////////////////////////////////////////////////////
436//////////////////////////////////////////////////////////////////////
437//////////////////////////////////////////////////////////////////////
438//////////////////////////////////////////////////////////////////////
439//////////////////////////////////////////////////////////////////////
440//////////////////////////////////////////////////////////////////////
441//////////////////////////////////////////////////////////////////////
442//////////////////////////////////////////////////////////////////////
443
sewardj478646f2008-05-01 20:13:04 +0000444#if 1 /* UNUSED */
445
446static
447__attribute((noreturn))
448void panic ( HChar* s )
449{
450 printf("\npanic: %s\n", s);
451 failure_exit();
452}
sewardj1ea1b612005-03-26 13:02:20 +0000453
sewardj69f9e3e2004-12-30 02:05:34 +0000454#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000455#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000456#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000457#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000458#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000459
cerionaee45242005-03-17 14:03:36 +0000460
sewardjde8c9872005-03-25 13:48:55 +0000461static void MC_helperc_complain_undef ( void );
462static void MC_helperc_LOADV8 ( void );
463static void MC_helperc_LOADV4 ( void );
464static void MC_helperc_LOADV2 ( void );
465static void MC_helperc_LOADV1 ( void );
sewardj1ea1b612005-03-26 13:02:20 +0000466static void MC_helperc_STOREV8( void );
467static void MC_helperc_STOREV4( void );
468static void MC_helperc_STOREV2( void );
469static void MC_helperc_STOREV1( void );
sewardjde8c9872005-03-25 13:48:55 +0000470static void MC_helperc_value_check0_fail( void );
471static void MC_helperc_value_check1_fail( void );
472static void MC_helperc_value_check4_fail( void );
473
474static void MC_helperc_complain_undef ( void ) { }
475static void MC_helperc_LOADV8 ( void ) { }
476static void MC_helperc_LOADV4 ( void ) { }
477static void MC_helperc_LOADV2 ( void ) { }
478static void MC_helperc_LOADV1 ( void ) { }
sewardj1ea1b612005-03-26 13:02:20 +0000479static void MC_helperc_STOREV8( void ) { }
480static void MC_helperc_STOREV4( void ) { }
481static void MC_helperc_STOREV2( void ) { }
482static void MC_helperc_STOREV1( void ) { }
sewardjde8c9872005-03-25 13:48:55 +0000483static void MC_helperc_value_check0_fail( void ) { }
484static void MC_helperc_value_check1_fail( void ) { }
485static void MC_helperc_value_check4_fail( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000486
487
sewardj3598ef92004-11-11 02:13:30 +0000488/*--------------------------------------------------------------------*/
489/*--- Instrument IR to perform memory checking operations. ---*/
490/*--- mc_translate.c ---*/
491/*--------------------------------------------------------------------*/
492
493/*
494 This file is part of MemCheck, a heavyweight Valgrind tool for
495 detecting memory errors.
496
sewardj89ae8472013-10-18 14:12:58 +0000497 Copyright (C) 2000-2013 Julian Seward
sewardj3598ef92004-11-11 02:13:30 +0000498 jseward@acm.org
499
500 This program is free software; you can redistribute it and/or
501 modify it under the terms of the GNU General Public License as
502 published by the Free Software Foundation; either version 2 of the
503 License, or (at your option) any later version.
504
505 This program is distributed in the hope that it will be useful, but
506 WITHOUT ANY WARRANTY; without even the implied warranty of
507 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
508 General Public License for more details.
509
510 You should have received a copy of the GNU General Public License
511 along with this program; if not, write to the Free Software
512 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
513 02111-1307, USA.
514
515 The GNU General Public License is contained in the file COPYING.
516*/
517
518//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000519
520
521/*------------------------------------------------------------*/
522/*--- Forward decls ---*/
523/*------------------------------------------------------------*/
524
525struct _MCEnv;
526
527static IRType shadowType ( IRType ty );
528static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
529
530
531/*------------------------------------------------------------*/
532/*--- Memcheck running state, and tmp management. ---*/
533/*------------------------------------------------------------*/
534
535/* Carries around state during memcheck instrumentation. */
536typedef
537 struct _MCEnv {
538 /* MODIFIED: the bb being constructed. IRStmts are added. */
sewardjf6c8ebf2007-02-06 01:52:52 +0000539 IRSB* bb;
sewardjde8a5ae2004-11-06 14:20:54 +0000540
541 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
542 original temps to their current their current shadow temp.
543 Initially all entries are IRTemp_INVALID. Entries are added
544 lazily since many original temps are not used due to
545 optimisation prior to instrumentation. Note that floating
546 point original tmps are shadowed by integer tmps of the same
547 size, and Bit-typed original tmps are shadowed by the type
548 Ity_I8. See comment below. */
549 IRTemp* tmpMap;
550 Int n_originalTmps; /* for range checking */
551
552 /* READONLY: the guest layout. This indicates which parts of
553 the guest state should be regarded as 'always defined'. */
554 VexGuestLayout* layout;
555 /* READONLY: the host word type. Needed for constructing
556 arguments of type 'HWord' to be passed to helper functions.
557 Ity_I32 or Ity_I64 only. */
558 IRType hWordTy;
559 }
560 MCEnv;
561
562/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
563 demand), as they are encountered. This is for two reasons.
564
565 (1) (less important reason): Many original tmps are unused due to
566 initial IR optimisation, and we do not want to spaces in tables
567 tracking them.
568
569 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
570 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000571 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000572 It is necessary to support making multiple assignments to a shadow
573 -- specifically, after testing a shadow for definedness, it needs
574 to be made defined. But IR's SSA property disallows this.
575
576 (2) (more important reason): Therefore, when a shadow needs to get
577 a new value, a new temporary is created, the value is assigned to
578 that, and the tmpMap is updated to reflect the new binding.
579
580 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000581 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000582 there's a read-before-write error in the original tmps. The IR
583 sanity checker should catch all such anomalies, however.
584*/
585
586/* Find the tmp currently shadowing the given original tmp. If none
587 so far exists, allocate one. */
588static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
589{
sewardj69f9e3e2004-12-30 02:05:34 +0000590 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000591 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000592 mce->tmpMap[orig]
593 = newIRTemp(mce->bb->tyenv,
594 shadowType(mce->bb->tyenv->types[orig]));
595 }
596 return mce->tmpMap[orig];
597}
598
599/* Allocate a new shadow for the given original tmp. This means any
600 previous shadow is abandoned. This is needed because it is
601 necessary to give a new value to a shadow once it has been tested
602 for undefinedness, but unfortunately IR's SSA property disallows
603 this. Instead we must abandon the old shadow, allocate a new one
604 and use that instead. */
605static void newShadowTmp ( MCEnv* mce, IRTemp orig )
606{
sewardj69f9e3e2004-12-30 02:05:34 +0000607 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000608 mce->tmpMap[orig]
609 = newIRTemp(mce->bb->tyenv,
610 shadowType(mce->bb->tyenv->types[orig]));
611}
612
613
614/*------------------------------------------------------------*/
615/*--- IRAtoms -- a subset of IRExprs ---*/
616/*------------------------------------------------------------*/
617
618/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj496a58d2005-03-20 18:44:44 +0000619 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardjde8a5ae2004-11-06 14:20:54 +0000620 input, most of this code deals in atoms. Usefully, a value atom
621 always has a V-value which is also an atom: constants are shadowed
622 by constants, and temps are shadowed by the corresponding shadow
623 temporary. */
624
625typedef IRExpr IRAtom;
626
627/* (used for sanity checks only): is this an atom which looks
628 like it's from original code? */
629static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
630{
631 if (a1->tag == Iex_Const)
632 return True;
sewardj478646f2008-05-01 20:13:04 +0000633 if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < mce->n_originalTmps)
sewardjde8a5ae2004-11-06 14:20:54 +0000634 return True;
635 return False;
636}
637
638/* (used for sanity checks only): is this an atom which looks
639 like it's from shadow code? */
640static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
641{
642 if (a1->tag == Iex_Const)
643 return True;
sewardj478646f2008-05-01 20:13:04 +0000644 if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= mce->n_originalTmps)
sewardjde8a5ae2004-11-06 14:20:54 +0000645 return True;
646 return False;
647}
648
649/* (used for sanity checks only): check that both args are atoms and
650 are identically-kinded. */
651static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
652{
sewardj478646f2008-05-01 20:13:04 +0000653 if (a1->tag == Iex_RdTmp && a1->tag == Iex_RdTmp)
sewardjde8a5ae2004-11-06 14:20:54 +0000654 return True;
655 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
656 return True;
657 return False;
658}
659
660
661/*------------------------------------------------------------*/
662/*--- Type management ---*/
663/*------------------------------------------------------------*/
664
665/* Shadow state is always accessed using integer types. This returns
666 an integer type with the same size (as per sizeofIRType) as the
667 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000668 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000669
670static IRType shadowType ( IRType ty )
671{
672 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000673 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000674 case Ity_I8:
675 case Ity_I16:
676 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000677 case Ity_I64: return ty;
678 case Ity_F32: return Ity_I32;
679 case Ity_F64: return Ity_I64;
680 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000681 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000682 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000683 }
684}
685
686/* Produce a 'defined' value of the given shadow type. Should only be
687 supplied shadow types (Bit/I8/I16/I32/UI64). */
688static IRExpr* definedOfType ( IRType ty ) {
689 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000690 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
691 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
692 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
693 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
694 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
695 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
696 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000697 }
698}
699
700
701/*------------------------------------------------------------*/
702/*--- Constructing IR fragments ---*/
703/*------------------------------------------------------------*/
704
705/* assign value to tmp */
706#define assign(_bb,_tmp,_expr) \
sewardj478646f2008-05-01 20:13:04 +0000707 addStmtToIRSB((_bb), IRStmt_WrTmp((_tmp),(_expr)))
sewardjde8a5ae2004-11-06 14:20:54 +0000708
709/* add stmt to a bb */
710#define stmt(_bb,_stmt) \
sewardjf6c8ebf2007-02-06 01:52:52 +0000711 addStmtToIRSB((_bb), (_stmt))
sewardjde8a5ae2004-11-06 14:20:54 +0000712
713/* build various kinds of expressions */
714#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
715#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
716#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
717#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
718#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
719#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000720#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardj478646f2008-05-01 20:13:04 +0000721#define mkexpr(_tmp) IRExpr_RdTmp((_tmp))
sewardjde8a5ae2004-11-06 14:20:54 +0000722
723/* bind the given expression to a new temporary, and return the
724 temporary. This effectively converts an arbitrary expression into
725 an atom. */
726static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
727 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
728 assign(mce->bb, t, e);
729 return mkexpr(t);
730}
731
732
733/*------------------------------------------------------------*/
734/*--- Constructing definedness primitive ops ---*/
735/*------------------------------------------------------------*/
736
737/* --------- Defined-if-either-defined --------- */
738
739static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000740 tl_assert(isShadowAtom(mce,a1));
741 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000742 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
743}
744
745static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000746 tl_assert(isShadowAtom(mce,a1));
747 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000748 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
749}
750
751static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000752 tl_assert(isShadowAtom(mce,a1));
753 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000754 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
755}
756
sewardj69f9e3e2004-12-30 02:05:34 +0000757static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
758 tl_assert(isShadowAtom(mce,a1));
759 tl_assert(isShadowAtom(mce,a2));
760 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
761}
762
sewardjf0c1c582005-02-07 23:47:38 +0000763static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000764 tl_assert(isShadowAtom(mce,a1));
765 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000766 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000767}
768
sewardjde8a5ae2004-11-06 14:20:54 +0000769/* --------- Undefined-if-either-undefined --------- */
770
771static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000772 tl_assert(isShadowAtom(mce,a1));
773 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000774 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
775}
776
777static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000778 tl_assert(isShadowAtom(mce,a1));
779 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000780 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
781}
782
783static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000784 tl_assert(isShadowAtom(mce,a1));
785 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000786 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
787}
788
789static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000790 tl_assert(isShadowAtom(mce,a1));
791 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000792 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
793}
794
sewardjf0c1c582005-02-07 23:47:38 +0000795static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000796 tl_assert(isShadowAtom(mce,a1));
797 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000798 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000799}
800
801static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000802 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000803 case Ity_I8: return mkUifU8(mce, a1, a2);
804 case Ity_I16: return mkUifU16(mce, a1, a2);
805 case Ity_I32: return mkUifU32(mce, a1, a2);
806 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardjf0c1c582005-02-07 23:47:38 +0000807 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000808 default:
809 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000810 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000811 }
812}
813
814/* --------- The Left-family of operations. --------- */
815
816static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000817 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000818 /* It's safe to duplicate a1 since it's only an atom */
819 return assignNew(mce, Ity_I8,
820 binop(Iop_Or8, a1,
821 assignNew(mce, Ity_I8,
822 /* unop(Iop_Neg8, a1)))); */
823 binop(Iop_Sub8, mkU8(0), a1) )));
824}
825
826static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000827 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000828 /* It's safe to duplicate a1 since it's only an atom */
829 return assignNew(mce, Ity_I16,
830 binop(Iop_Or16, a1,
831 assignNew(mce, Ity_I16,
832 /* unop(Iop_Neg16, a1)))); */
833 binop(Iop_Sub16, mkU16(0), a1) )));
834}
835
836static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000837 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000838 /* It's safe to duplicate a1 since it's only an atom */
839 return assignNew(mce, Ity_I32,
840 binop(Iop_Or32, a1,
841 assignNew(mce, Ity_I32,
842 /* unop(Iop_Neg32, a1)))); */
843 binop(Iop_Sub32, mkU32(0), a1) )));
844}
845
846/* --------- 'Improvement' functions for AND/OR. --------- */
847
848/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
849 defined (0); all other -> undefined (1).
850*/
851static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
852{
sewardj69f9e3e2004-12-30 02:05:34 +0000853 tl_assert(isOriginalAtom(mce, data));
854 tl_assert(isShadowAtom(mce, vbits));
855 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000856 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
857}
858
sewardj3598ef92004-11-11 02:13:30 +0000859static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
860{
sewardj69f9e3e2004-12-30 02:05:34 +0000861 tl_assert(isOriginalAtom(mce, data));
862 tl_assert(isShadowAtom(mce, vbits));
863 tl_assert(sameKindedAtoms(data, vbits));
sewardj3598ef92004-11-11 02:13:30 +0000864 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
865}
866
sewardjde8a5ae2004-11-06 14:20:54 +0000867static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
868{
sewardj69f9e3e2004-12-30 02:05:34 +0000869 tl_assert(isOriginalAtom(mce, data));
870 tl_assert(isShadowAtom(mce, vbits));
871 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000872 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
873}
874
sewardj69f9e3e2004-12-30 02:05:34 +0000875static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
876{
877 tl_assert(isOriginalAtom(mce, data));
878 tl_assert(isShadowAtom(mce, vbits));
879 tl_assert(sameKindedAtoms(data, vbits));
880 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
881}
882
sewardjf0c1c582005-02-07 23:47:38 +0000883static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000884{
885 tl_assert(isOriginalAtom(mce, data));
886 tl_assert(isShadowAtom(mce, vbits));
887 tl_assert(sameKindedAtoms(data, vbits));
sewardjf0c1c582005-02-07 23:47:38 +0000888 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj69f9e3e2004-12-30 02:05:34 +0000889}
890
sewardjde8a5ae2004-11-06 14:20:54 +0000891/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
892 defined (0); all other -> undefined (1).
893*/
894static IRAtom* mkImproveOR8 ( 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_I8,
901 binop(Iop_Or8,
902 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
903 vbits) );
904}
905
906static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
907{
sewardj69f9e3e2004-12-30 02:05:34 +0000908 tl_assert(isOriginalAtom(mce, data));
909 tl_assert(isShadowAtom(mce, vbits));
910 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000911 return assignNew(
912 mce, Ity_I16,
913 binop(Iop_Or16,
914 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
915 vbits) );
916}
917
918static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
919{
sewardj69f9e3e2004-12-30 02:05:34 +0000920 tl_assert(isOriginalAtom(mce, data));
921 tl_assert(isShadowAtom(mce, vbits));
922 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000923 return assignNew(
924 mce, Ity_I32,
925 binop(Iop_Or32,
926 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
927 vbits) );
928}
929
sewardj69f9e3e2004-12-30 02:05:34 +0000930static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
931{
932 tl_assert(isOriginalAtom(mce, data));
933 tl_assert(isShadowAtom(mce, vbits));
934 tl_assert(sameKindedAtoms(data, vbits));
935 return assignNew(
936 mce, Ity_I64,
937 binop(Iop_Or64,
938 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
939 vbits) );
940}
941
sewardjf0c1c582005-02-07 23:47:38 +0000942static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000943{
944 tl_assert(isOriginalAtom(mce, data));
945 tl_assert(isShadowAtom(mce, vbits));
946 tl_assert(sameKindedAtoms(data, vbits));
947 return assignNew(
948 mce, Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +0000949 binop(Iop_OrV128,
950 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj69f9e3e2004-12-30 02:05:34 +0000951 vbits) );
952}
953
sewardjde8a5ae2004-11-06 14:20:54 +0000954/* --------- Pessimising casts. --------- */
955
956static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
957{
sewardj8fc93742004-11-22 11:29:33 +0000958 IRType ty;
959 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000960 /* Note, dst_ty is a shadow type, not an original type. */
961 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000962 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000963 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
964 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000965 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000966 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000967 tmp1 = vbits;
968 break;
969 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000970 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000971 break;
972 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000973 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000974 break;
975 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000976 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000977 break;
978 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000979 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000980 break;
981 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000982 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000983 }
sewardj69f9e3e2004-12-30 02:05:34 +0000984 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000985 /* Now widen up to the dst type. */
986 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000987 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000988 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000989 case Ity_I8:
990 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000991 case Ity_I16:
992 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
993 case Ity_I32:
994 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
995 case Ity_I64:
996 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000997 case Ity_V128:
998 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardjf0c1c582005-02-07 23:47:38 +0000999 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +00001000 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +00001001 default:
1002 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001003 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +00001004 }
1005}
1006
1007
1008/*------------------------------------------------------------*/
1009/*--- Emit a test and complaint if something is undefined. ---*/
1010/*------------------------------------------------------------*/
1011
1012/* Set the annotations on a dirty helper to indicate that the stack
1013 pointer and instruction pointers might be read. This is the
1014 behaviour of all 'emit-a-complaint' style functions we might
1015 call. */
1016
1017static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
1018 di->nFxState = 2;
1019 di->fxState[0].fx = Ifx_Read;
1020 di->fxState[0].offset = mce->layout->offset_SP;
1021 di->fxState[0].size = mce->layout->sizeof_SP;
1022 di->fxState[1].fx = Ifx_Read;
1023 di->fxState[1].offset = mce->layout->offset_IP;
1024 di->fxState[1].size = mce->layout->sizeof_IP;
1025}
1026
1027
1028/* Check the supplied **original** atom for undefinedness, and emit a
1029 complaint if so. Once that happens, mark it as defined. This is
1030 possible because the atom is either a tmp or literal. If it's a
1031 tmp, it will be shadowed by a tmp, and so we can set the shadow to
1032 be defined. In fact as mentioned above, we will have to allocate a
1033 new tmp to carry the new 'defined' shadow value, and update the
1034 original->tmp mapping accordingly; we cannot simply assign a new
1035 value to an existing shadow tmp as this breaks SSAness -- resulting
1036 in the post-instrumentation sanity checker spluttering in disapproval.
1037*/
1038static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
1039{
sewardj8fc93742004-11-22 11:29:33 +00001040 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001041 IRType ty;
1042 Int sz;
sewardj8fc93742004-11-22 11:29:33 +00001043 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +00001044 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +00001045
sewardjde8a5ae2004-11-06 14:20:54 +00001046 /* Since the original expression is atomic, there's no duplicated
1047 work generated by making multiple V-expressions for it. So we
1048 don't really care about the possibility that someone else may
1049 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +00001050 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +00001051 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001052 tl_assert(isShadowAtom(mce, vatom));
1053 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001054
sewardj8fc93742004-11-22 11:29:33 +00001055 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +00001056
1057 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +00001058 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +00001059
sewardj8fc93742004-11-22 11:29:33 +00001060 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +00001061 /* cond will be 0 if all defined, and 1 if any not defined. */
1062
sewardj3598ef92004-11-11 02:13:30 +00001063 switch (sz) {
1064 case 0:
1065 di = unsafeIRDirty_0_N( 0/*regparms*/,
1066 "MC_(helperc_value_check0_fail)",
1067 &MC_(helperc_value_check0_fail),
1068 mkIRExprVec_0()
1069 );
1070 break;
1071 case 1:
1072 di = unsafeIRDirty_0_N( 0/*regparms*/,
1073 "MC_(helperc_value_check1_fail)",
1074 &MC_(helperc_value_check1_fail),
1075 mkIRExprVec_0()
1076 );
1077 break;
1078 case 4:
1079 di = unsafeIRDirty_0_N( 0/*regparms*/,
1080 "MC_(helperc_value_check4_fail)",
1081 &MC_(helperc_value_check4_fail),
1082 mkIRExprVec_0()
1083 );
1084 break;
1085 default:
1086 di = unsafeIRDirty_0_N( 1/*regparms*/,
1087 "MC_(helperc_complain_undef)",
1088 &MC_(helperc_complain_undef),
1089 mkIRExprVec_1( mkIRExpr_HWord( sz ))
1090 );
1091 break;
1092 }
sewardjde8a5ae2004-11-06 14:20:54 +00001093 di->guard = cond;
1094 setHelperAnns( mce, di );
1095 stmt( mce->bb, IRStmt_Dirty(di));
1096
1097 /* Set the shadow tmp to be defined. First, update the
1098 orig->shadow tmp mapping to reflect the fact that this shadow is
1099 getting a new value. */
sewardj496a58d2005-03-20 18:44:44 +00001100 tl_assert(isIRAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001101 /* sameKindedAtoms ... */
sewardj478646f2008-05-01 20:13:04 +00001102 if (vatom->tag == Iex_RdTmp) {
1103 tl_assert(atom->tag == Iex_RdTmp);
1104 newShadowTmp(mce, atom->Iex.RdTmp.tmp);
1105 assign(mce->bb, findShadowTmp(mce, atom->Iex.RdTmp.tmp),
sewardjde8a5ae2004-11-06 14:20:54 +00001106 definedOfType(ty));
1107 }
1108}
1109
1110
1111/*------------------------------------------------------------*/
1112/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
1113/*------------------------------------------------------------*/
1114
1115/* Examine the always-defined sections declared in layout to see if
1116 the (offset,size) section is within one. Note, is is an error to
1117 partially fall into such a region: (offset,size) should either be
1118 completely in such a region or completely not-in such a region.
1119*/
1120static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1121{
1122 Int minoffD, maxoffD, i;
1123 Int minoff = offset;
1124 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001125 tl_assert((minoff & ~0xFFFF) == 0);
1126 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001127
1128 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1129 minoffD = mce->layout->alwaysDefd[i].offset;
1130 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001131 tl_assert((minoffD & ~0xFFFF) == 0);
1132 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001133
1134 if (maxoff < minoffD || maxoffD < minoff)
1135 continue; /* no overlap */
1136 if (minoff >= minoffD && maxoff <= maxoffD)
1137 return True; /* completely contained in an always-defd section */
1138
sewardj69f9e3e2004-12-30 02:05:34 +00001139 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001140 }
1141 return False; /* could not find any containing section */
1142}
1143
1144
1145/* Generate into bb suitable actions to shadow this Put. If the state
1146 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001147 supplied V bits to the shadow state. We can pass in either an
1148 original atom or a V-atom, but not both. In the former case the
1149 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001150*/
1151static
sewardj3598ef92004-11-11 02:13:30 +00001152void do_shadow_PUT ( MCEnv* mce, Int offset,
1153 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001154{
sewardj8fc93742004-11-22 11:29:33 +00001155 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001156 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001157 tl_assert(!vatom);
1158 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001159 vatom = expr2vbits( mce, atom );
1160 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001161 tl_assert(vatom);
1162 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001163 }
1164
sewardj8fc93742004-11-22 11:29:33 +00001165 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001166 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001167 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1168 /* later: no ... */
1169 /* emit code to emit a complaint if any of the vbits are 1. */
1170 /* complainIfUndefined(mce, atom); */
1171 } else {
1172 /* Do a plain shadow Put. */
1173 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1174 }
1175}
1176
1177
1178/* Return an expression which contains the V bits corresponding to the
1179 given GETI (passed in in pieces).
1180*/
1181static
1182void do_shadow_PUTI ( MCEnv* mce,
sewardj478646f2008-05-01 20:13:04 +00001183 IRRegArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
sewardjde8a5ae2004-11-06 14:20:54 +00001184{
sewardj8fc93742004-11-22 11:29:33 +00001185 IRAtom* vatom;
1186 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001187 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001188
sewardj69f9e3e2004-12-30 02:05:34 +00001189 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001190 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001191 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001192 ty = descr->elemTy;
1193 tyS = shadowType(ty);
1194 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001195 tl_assert(ty != Ity_I1);
1196 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001197 complainIfUndefined(mce,ix);
1198 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1199 /* later: no ... */
1200 /* emit code to emit a complaint if any of the vbits are 1. */
1201 /* complainIfUndefined(mce, atom); */
1202 } else {
1203 /* Do a cloned version of the Put that refers to the shadow
1204 area. */
sewardj478646f2008-05-01 20:13:04 +00001205 IRRegArray* new_descr
1206 = mkIRRegArray( descr->base + mce->layout->total_sizeB,
sewardjde8a5ae2004-11-06 14:20:54 +00001207 tyS, descr->nElems);
florian4180af32012-12-24 00:25:34 +00001208 stmt( mce->bb, IRStmt_PutI( mkIRPutI( new_descr, ix, bias, vatom ) ));
sewardjde8a5ae2004-11-06 14:20:54 +00001209 }
1210}
1211
1212
1213/* Return an expression which contains the V bits corresponding to the
1214 given GET (passed in in pieces).
1215*/
1216static
1217IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1218{
1219 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001220 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001221 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1222 /* Always defined, return all zeroes of the relevant type */
1223 return definedOfType(tyS);
1224 } else {
1225 /* return a cloned version of the Get that refers to the shadow
1226 area. */
1227 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1228 }
1229}
1230
1231
1232/* Return an expression which contains the V bits corresponding to the
1233 given GETI (passed in in pieces).
1234*/
1235static
sewardj478646f2008-05-01 20:13:04 +00001236IRExpr* shadow_GETI ( MCEnv* mce, IRRegArray* descr, IRAtom* ix, Int bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001237{
1238 IRType ty = descr->elemTy;
1239 IRType tyS = shadowType(ty);
1240 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001241 tl_assert(ty != Ity_I1);
1242 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001243 complainIfUndefined(mce,ix);
1244 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1245 /* Always defined, return all zeroes of the relevant type */
1246 return definedOfType(tyS);
1247 } else {
1248 /* return a cloned version of the Get that refers to the shadow
1249 area. */
sewardj478646f2008-05-01 20:13:04 +00001250 IRRegArray* new_descr
1251 = mkIRRegArray( descr->base + mce->layout->total_sizeB,
sewardjde8a5ae2004-11-06 14:20:54 +00001252 tyS, descr->nElems);
1253 return IRExpr_GetI( new_descr, ix, bias );
1254 }
1255}
1256
1257
1258/*------------------------------------------------------------*/
1259/*--- Generating approximations for unknown operations, ---*/
1260/*--- using lazy-propagate semantics ---*/
1261/*------------------------------------------------------------*/
1262
1263/* Lazy propagation of undefinedness from two values, resulting in the
1264 specified shadow type.
1265*/
1266static
1267IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1268{
1269 /* force everything via 32-bit intermediaries. */
1270 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001271 tl_assert(isShadowAtom(mce,va1));
1272 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001273 at = mkPCastTo(mce, Ity_I32, va1);
1274 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1275 at = mkPCastTo(mce, finalVty, at);
1276 return at;
1277}
1278
1279
1280/* Do the lazy propagation game from a null-terminated vector of
1281 atoms. This is presumably the arguments to a helper call, so the
1282 IRCallee info is also supplied in order that we can know which
1283 arguments should be ignored (via the .mcx_mask field).
1284*/
1285static
1286IRAtom* mkLazyN ( MCEnv* mce,
1287 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1288{
1289 Int i;
1290 IRAtom* here;
1291 IRAtom* curr = definedOfType(Ity_I32);
1292 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001293 tl_assert(i < 32);
1294 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001295 /* Only take notice of this arg if the callee's mc-exclusion
1296 mask does not say it is to be excluded. */
1297 if (cee->mcx_mask & (1<<i)) {
1298 /* the arg is to be excluded from definedness checking. Do
1299 nothing. */
1300 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1301 } else {
1302 /* calculate the arg's definedness, and pessimistically merge
1303 it in. */
1304 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1305 curr = mkUifU32(mce, here, curr);
1306 }
1307 }
1308 return mkPCastTo(mce, finalVtype, curr );
1309}
1310
1311
1312/*------------------------------------------------------------*/
1313/*--- Generating expensive sequences for exact carry-chain ---*/
1314/*--- propagation in add/sub and related operations. ---*/
1315/*------------------------------------------------------------*/
1316
1317static
sewardj5f438dd2011-06-16 11:36:23 +00001318__attribute__((unused))
sewardjde8a5ae2004-11-06 14:20:54 +00001319IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1320 IRAtom* aa, IRAtom* bb )
1321{
sewardj69f9e3e2004-12-30 02:05:34 +00001322 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001323 IRType ty;
1324 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001325
sewardj69f9e3e2004-12-30 02:05:34 +00001326 tl_assert(isShadowAtom(mce,qaa));
1327 tl_assert(isShadowAtom(mce,qbb));
1328 tl_assert(isOriginalAtom(mce,aa));
1329 tl_assert(isOriginalAtom(mce,bb));
1330 tl_assert(sameKindedAtoms(qaa,aa));
1331 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001332
sewardj8fc93742004-11-22 11:29:33 +00001333 ty = Ity_I32;
1334 opAND = Iop_And32;
1335 opOR = Iop_Or32;
1336 opXOR = Iop_Xor32;
1337 opNOT = Iop_Not32;
1338 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001339
1340 // a_min = aa & ~qaa
1341 a_min = assignNew(mce,ty,
1342 binop(opAND, aa,
1343 assignNew(mce,ty, unop(opNOT, qaa))));
1344
1345 // b_min = bb & ~qbb
1346 b_min = assignNew(mce,ty,
1347 binop(opAND, bb,
1348 assignNew(mce,ty, unop(opNOT, qbb))));
1349
1350 // a_max = aa | qaa
1351 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1352
1353 // b_max = bb | qbb
1354 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1355
1356 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1357 return
1358 assignNew(mce,ty,
1359 binop( opOR,
1360 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1361 assignNew(mce,ty,
1362 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1363 assignNew(mce,ty, binop(opADD, a_max, b_max))
1364 )
1365 )
1366 )
1367 );
1368}
1369
1370
1371/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001372/*--- Helpers for dealing with vector primops. ---*/
1373/*------------------------------------------------------------*/
1374
1375/* Vector pessimisation -- pessimise within each lane individually. */
1376
1377static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1378{
1379 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1380}
1381
1382static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1383{
1384 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1385}
1386
1387static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1388{
1389 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1390}
1391
1392static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1393{
1394 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1395}
1396
1397
1398/* Here's a simple scheme capable of handling ops derived from SSE1
1399 code and while only generating ops that can be efficiently
1400 implemented in SSE1. */
1401
1402/* All-lanes versions are straightforward:
1403
sewardjf0c1c582005-02-07 23:47:38 +00001404 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj69f9e3e2004-12-30 02:05:34 +00001405
1406 unary32Fx4(x,y) ==> PCast32x4(x#)
1407
1408 Lowest-lane-only versions are more complex:
1409
sewardjf0c1c582005-02-07 23:47:38 +00001410 binary32F0x4(x,y) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001411 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001412 PCast32(V128to32(UifUV128(x#,y#)))
sewardj69f9e3e2004-12-30 02:05:34 +00001413 )
1414
1415 This is perhaps not so obvious. In particular, it's faster to
sewardjf0c1c582005-02-07 23:47:38 +00001416 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj69f9e3e2004-12-30 02:05:34 +00001417 obvious scheme of taking the bottom 32 bits of each operand
1418 and doing a 32-bit UifU. Basically since UifU is fast and
1419 chopping lanes off vector values is slow.
1420
1421 Finally:
1422
sewardjf0c1c582005-02-07 23:47:38 +00001423 unary32F0x4(x) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001424 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001425 PCast32(V128to32(x#))
sewardj69f9e3e2004-12-30 02:05:34 +00001426 )
1427
1428 Where:
1429
1430 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1431 PCast32x4(v#) = CmpNEZ32x4(v#)
1432*/
1433
1434static
1435IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1436{
1437 IRAtom* at;
1438 tl_assert(isShadowAtom(mce, vatomX));
1439 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001440 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001441 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1442 return at;
1443}
1444
1445static
1446IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1447{
1448 IRAtom* at;
1449 tl_assert(isShadowAtom(mce, vatomX));
1450 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1451 return at;
1452}
1453
1454static
1455IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1456{
1457 IRAtom* at;
1458 tl_assert(isShadowAtom(mce, vatomX));
1459 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001460 at = mkUifUV128(mce, vatomX, vatomY);
1461 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001462 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001463 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001464 return at;
1465}
1466
1467static
1468IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1469{
1470 IRAtom* at;
1471 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001472 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001473 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001474 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001475 return at;
1476}
1477
1478/* --- ... and ... 64Fx2 versions of the same ... --- */
1479
1480static
1481IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1482{
1483 IRAtom* at;
1484 tl_assert(isShadowAtom(mce, vatomX));
1485 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001486 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001487 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1488 return at;
1489}
1490
1491static
1492IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1493{
1494 IRAtom* at;
1495 tl_assert(isShadowAtom(mce, vatomX));
1496 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1497 return at;
1498}
1499
1500static
1501IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1502{
1503 IRAtom* at;
1504 tl_assert(isShadowAtom(mce, vatomX));
1505 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001506 at = mkUifUV128(mce, vatomX, vatomY);
1507 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001508 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001509 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001510 return at;
1511}
1512
1513static
1514IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1515{
1516 IRAtom* at;
1517 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001518 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001519 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001520 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001521 return at;
1522}
1523
1524/* --- --- Vector saturated narrowing --- --- */
1525
1526/* This is quite subtle. What to do is simple:
1527
1528 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1529
1530 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1531
1532 Why this is right is not so simple. Consider a lane in the args,
1533 vatom1 or 2, doesn't matter.
1534
1535 After the PCast, that lane is all 0s (defined) or all
1536 1s(undefined).
1537
1538 Both signed and unsigned saturating narrowing of all 0s produces
1539 all 0s, which is what we want.
1540
1541 The all-1s case is more complex. Unsigned narrowing interprets an
1542 all-1s input as the largest unsigned integer, and so produces all
1543 1s as a result since that is the largest unsigned value at the
1544 smaller width.
1545
1546 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1547 to -1, so we still wind up with all 1s at the smaller width.
1548
1549 So: In short, pessimise the args, then apply the original narrowing
1550 op.
1551*/
1552static
sewardjf0c1c582005-02-07 23:47:38 +00001553IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardj69f9e3e2004-12-30 02:05:34 +00001554 IRAtom* vatom1, IRAtom* vatom2)
1555{
1556 IRAtom *at1, *at2, *at3;
1557 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1558 switch (narrow_op) {
sewardj5f438dd2011-06-16 11:36:23 +00001559 case Iop_QNarrowBin32Sto16Sx8: pcast = mkPCast32x4; break;
1560 case Iop_QNarrowBin16Sto8Sx16: pcast = mkPCast16x8; break;
1561 case Iop_QNarrowBin16Sto8Ux16: pcast = mkPCast16x8; break;
sewardjf0c1c582005-02-07 23:47:38 +00001562 default: VG_(tool_panic)("vectorNarrowV128");
sewardj69f9e3e2004-12-30 02:05:34 +00001563 }
1564 tl_assert(isShadowAtom(mce,vatom1));
1565 tl_assert(isShadowAtom(mce,vatom2));
1566 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1567 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1568 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1569 return at3;
1570}
1571
1572
1573/* --- --- Vector integer arithmetic --- --- */
1574
1575/* Simple ... UifU the args and per-lane pessimise the results. */
1576static
1577IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1578{
1579 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001580 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001581 at = mkPCast8x16(mce, at);
1582 return at;
1583}
1584
1585static
1586IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1587{
1588 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001589 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001590 at = mkPCast16x8(mce, at);
1591 return at;
1592}
1593
1594static
1595IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1596{
1597 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001598 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001599 at = mkPCast32x4(mce, at);
1600 return at;
1601}
1602
1603static
1604IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1605{
1606 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001607 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001608 at = mkPCast64x2(mce, at);
1609 return at;
1610}
1611
1612
1613/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001614/*--- Generate shadow values from all kinds of IRExprs. ---*/
1615/*------------------------------------------------------------*/
1616
1617static
1618IRAtom* expr2vbits_Binop ( MCEnv* mce,
1619 IROp op,
1620 IRAtom* atom1, IRAtom* atom2 )
1621{
1622 IRType and_or_ty;
1623 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1624 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1625 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1626
1627 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1628 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1629
sewardj69f9e3e2004-12-30 02:05:34 +00001630 tl_assert(isOriginalAtom(mce,atom1));
1631 tl_assert(isOriginalAtom(mce,atom2));
1632 tl_assert(isShadowAtom(mce,vatom1));
1633 tl_assert(isShadowAtom(mce,vatom2));
1634 tl_assert(sameKindedAtoms(atom1,vatom1));
1635 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001636 switch (op) {
1637
sewardjf0c1c582005-02-07 23:47:38 +00001638 /* V128-bit SIMD (SSE2-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001639
1640 case Iop_ShrN16x8:
1641 case Iop_ShrN32x4:
1642 case Iop_ShrN64x2:
1643 case Iop_SarN16x8:
1644 case Iop_SarN32x4:
1645 case Iop_ShlN16x8:
1646 case Iop_ShlN32x4:
1647 case Iop_ShlN64x2:
1648 /* Same scheme as with all other shifts. */
1649 complainIfUndefined(mce, atom2);
1650 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1651
1652 case Iop_QSub8Ux16:
1653 case Iop_QSub8Sx16:
1654 case Iop_Sub8x16:
1655 case Iop_Min8Ux16:
1656 case Iop_Max8Ux16:
1657 case Iop_CmpGT8Sx16:
1658 case Iop_CmpEQ8x16:
1659 case Iop_Avg8Ux16:
1660 case Iop_QAdd8Ux16:
1661 case Iop_QAdd8Sx16:
1662 case Iop_Add8x16:
1663 return binary8Ix16(mce, vatom1, vatom2);
1664
1665 case Iop_QSub16Ux8:
1666 case Iop_QSub16Sx8:
1667 case Iop_Sub16x8:
1668 case Iop_Mul16x8:
1669 case Iop_MulHi16Sx8:
1670 case Iop_MulHi16Ux8:
1671 case Iop_Min16Sx8:
1672 case Iop_Max16Sx8:
1673 case Iop_CmpGT16Sx8:
1674 case Iop_CmpEQ16x8:
1675 case Iop_Avg16Ux8:
1676 case Iop_QAdd16Ux8:
1677 case Iop_QAdd16Sx8:
1678 case Iop_Add16x8:
1679 return binary16Ix8(mce, vatom1, vatom2);
1680
1681 case Iop_Sub32x4:
sewardj2fdd4162010-08-22 12:59:02 +00001682 case Iop_QSub32Sx4:
1683 case Iop_QSub32Ux4:
sewardj69f9e3e2004-12-30 02:05:34 +00001684 case Iop_CmpGT32Sx4:
1685 case Iop_CmpEQ32x4:
1686 case Iop_Add32x4:
sewardj2fdd4162010-08-22 12:59:02 +00001687 case Iop_QAdd32Ux4:
1688 case Iop_QAdd32Sx4:
sewardj69f9e3e2004-12-30 02:05:34 +00001689 return binary32Ix4(mce, vatom1, vatom2);
1690
1691 case Iop_Sub64x2:
sewardj2fdd4162010-08-22 12:59:02 +00001692 case Iop_QSub64Ux2:
1693 case Iop_QSub64Sx2:
sewardj69f9e3e2004-12-30 02:05:34 +00001694 case Iop_Add64x2:
sewardj2fdd4162010-08-22 12:59:02 +00001695 case Iop_QAdd64Ux2:
1696 case Iop_QAdd64Sx2:
sewardj69f9e3e2004-12-30 02:05:34 +00001697 return binary64Ix2(mce, vatom1, vatom2);
1698
sewardj5f438dd2011-06-16 11:36:23 +00001699 case Iop_QNarrowBin32Sto16Sx8:
1700 case Iop_QNarrowBin16Sto8Sx16:
1701 case Iop_QNarrowBin16Sto8Ux16:
sewardjf0c1c582005-02-07 23:47:38 +00001702 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001703
1704 case Iop_Sub64Fx2:
1705 case Iop_Mul64Fx2:
1706 case Iop_Min64Fx2:
1707 case Iop_Max64Fx2:
1708 case Iop_Div64Fx2:
1709 case Iop_CmpLT64Fx2:
1710 case Iop_CmpLE64Fx2:
1711 case Iop_CmpEQ64Fx2:
1712 case Iop_Add64Fx2:
1713 return binary64Fx2(mce, vatom1, vatom2);
1714
1715 case Iop_Sub64F0x2:
1716 case Iop_Mul64F0x2:
1717 case Iop_Min64F0x2:
1718 case Iop_Max64F0x2:
1719 case Iop_Div64F0x2:
1720 case Iop_CmpLT64F0x2:
1721 case Iop_CmpLE64F0x2:
1722 case Iop_CmpEQ64F0x2:
1723 case Iop_Add64F0x2:
1724 return binary64F0x2(mce, vatom1, vatom2);
1725
sewardjf0c1c582005-02-07 23:47:38 +00001726 /* V128-bit SIMD (SSE1-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001727
1728 case Iop_Sub32Fx4:
1729 case Iop_Mul32Fx4:
1730 case Iop_Min32Fx4:
1731 case Iop_Max32Fx4:
1732 case Iop_Div32Fx4:
1733 case Iop_CmpLT32Fx4:
1734 case Iop_CmpLE32Fx4:
1735 case Iop_CmpEQ32Fx4:
1736 case Iop_Add32Fx4:
1737 return binary32Fx4(mce, vatom1, vatom2);
1738
1739 case Iop_Sub32F0x4:
1740 case Iop_Mul32F0x4:
1741 case Iop_Min32F0x4:
1742 case Iop_Max32F0x4:
1743 case Iop_Div32F0x4:
1744 case Iop_CmpLT32F0x4:
1745 case Iop_CmpLE32F0x4:
1746 case Iop_CmpEQ32F0x4:
1747 case Iop_Add32F0x4:
1748 return binary32F0x4(mce, vatom1, vatom2);
1749
sewardjf0c1c582005-02-07 23:47:38 +00001750 /* V128-bit data-steering */
1751 case Iop_SetV128lo32:
1752 case Iop_SetV128lo64:
1753 case Iop_64HLtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001754 case Iop_InterleaveLO64x2:
1755 case Iop_InterleaveLO32x4:
1756 case Iop_InterleaveLO16x8:
1757 case Iop_InterleaveLO8x16:
1758 case Iop_InterleaveHI64x2:
1759 case Iop_InterleaveHI32x4:
1760 case Iop_InterleaveHI16x8:
1761 case Iop_InterleaveHI8x16:
1762 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1763
1764 /* Scalar floating point */
1765
sewardj478646f2008-05-01 20:13:04 +00001766 // case Iop_RoundF64:
sewardj1e3830f2011-03-14 11:27:26 +00001767 case Iop_F64toI64S:
1768 case Iop_I64StoF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001769 /* First arg is I32 (rounding mode), second is F64 or I64
1770 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001771 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1772
1773 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1774 /* Takes two F64 args. */
sewardj1e3830f2011-03-14 11:27:26 +00001775 case Iop_F64toI32S:
sewardj69f9e3e2004-12-30 02:05:34 +00001776 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001777 /* First arg is I32 (rounding mode), second is F64 (data). */
1778 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1779
sewardj1e3830f2011-03-14 11:27:26 +00001780 case Iop_F64toI16S:
sewardjde8a5ae2004-11-06 14:20:54 +00001781 /* First arg is I32 (rounding mode), second is F64 (data). */
1782 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1783
sewardj3598ef92004-11-11 02:13:30 +00001784 case Iop_ScaleF64:
1785 case Iop_Yl2xF64:
1786 case Iop_Yl2xp1F64:
1787 case Iop_PRemF64:
1788 case Iop_AtanF64:
1789 case Iop_AddF64:
1790 case Iop_DivF64:
1791 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001792 case Iop_MulF64:
1793 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1794
sewardj3598ef92004-11-11 02:13:30 +00001795 case Iop_CmpF64:
1796 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1797
sewardjde8a5ae2004-11-06 14:20:54 +00001798 /* non-FP after here */
1799
1800 case Iop_DivModU64to32:
1801 case Iop_DivModS64to32:
1802 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1803
sewardj3598ef92004-11-11 02:13:30 +00001804 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001805 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001806 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001807 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001808
1809 case Iop_MullS32:
1810 case Iop_MullU32: {
1811 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1812 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1813 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1814 }
1815
sewardj3598ef92004-11-11 02:13:30 +00001816 case Iop_MullS16:
1817 case Iop_MullU16: {
1818 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1819 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1820 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1821 }
1822
1823 case Iop_MullS8:
1824 case Iop_MullU8: {
1825 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1826 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1827 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1828 }
1829
sewardjde8a5ae2004-11-06 14:20:54 +00001830 case Iop_Add32:
1831# if 0
1832 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1833# endif
1834 case Iop_Sub32:
1835 case Iop_Mul32:
1836 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1837
sewardj3598ef92004-11-11 02:13:30 +00001838 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001839 case Iop_Add16:
1840 case Iop_Sub16:
1841 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1842
1843 case Iop_Sub8:
1844 case Iop_Add8:
1845 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1846
1847 case Iop_CmpLE32S: case Iop_CmpLE32U:
1848 case Iop_CmpLT32U: case Iop_CmpLT32S:
1849 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001850 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001851
sewardj3598ef92004-11-11 02:13:30 +00001852 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001853 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001854
1855 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001856 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001857
1858 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1859 /* Complain if the shift amount is undefined. Then simply
1860 shift the first arg's V bits by the real shift amount. */
1861 complainIfUndefined(mce, atom2);
1862 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1863
sewardj69f9e3e2004-12-30 02:05:34 +00001864 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001865 /* Same scheme as with 32-bit shifts. */
1866 complainIfUndefined(mce, atom2);
1867 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1868
sewardj3598ef92004-11-11 02:13:30 +00001869 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001870 /* Same scheme as with 32-bit shifts. */
1871 complainIfUndefined(mce, atom2);
1872 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1873
1874 case Iop_Shl64: case Iop_Shr64:
1875 /* Same scheme as with 32-bit shifts. */
1876 complainIfUndefined(mce, atom2);
1877 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1878
sewardjf0c1c582005-02-07 23:47:38 +00001879 case Iop_AndV128:
1880 uifu = mkUifUV128; difd = mkDifDV128;
1881 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001882 case Iop_And64:
1883 uifu = mkUifU64; difd = mkDifD64;
1884 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001885 case Iop_And32:
1886 uifu = mkUifU32; difd = mkDifD32;
1887 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001888 case Iop_And16:
1889 uifu = mkUifU16; difd = mkDifD16;
1890 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001891 case Iop_And8:
1892 uifu = mkUifU8; difd = mkDifD8;
1893 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1894
sewardjf0c1c582005-02-07 23:47:38 +00001895 case Iop_OrV128:
1896 uifu = mkUifUV128; difd = mkDifDV128;
1897 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001898 case Iop_Or64:
1899 uifu = mkUifU64; difd = mkDifD64;
1900 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001901 case Iop_Or32:
1902 uifu = mkUifU32; difd = mkDifD32;
1903 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1904 case Iop_Or16:
1905 uifu = mkUifU16; difd = mkDifD16;
1906 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1907 case Iop_Or8:
1908 uifu = mkUifU8; difd = mkDifD8;
1909 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1910
1911 do_And_Or:
1912 return
1913 assignNew(
1914 mce,
1915 and_or_ty,
1916 difd(mce, uifu(mce, vatom1, vatom2),
1917 difd(mce, improve(mce, atom1, vatom1),
1918 improve(mce, atom2, vatom2) ) ) );
1919
1920 case Iop_Xor8:
1921 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001922 case Iop_Xor16:
1923 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001924 case Iop_Xor32:
1925 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001926 case Iop_Xor64:
1927 return mkUifU64(mce, vatom1, vatom2);
sewardjf0c1c582005-02-07 23:47:38 +00001928 case Iop_XorV128:
1929 return mkUifUV128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001930
1931 default:
1932 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001933 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001934 }
1935}
1936
1937
1938static
1939IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1940{
1941 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001942 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001943 switch (op) {
1944
sewardj69f9e3e2004-12-30 02:05:34 +00001945 case Iop_Sqrt64Fx2:
1946 return unary64Fx2(mce, vatom);
1947
1948 case Iop_Sqrt64F0x2:
1949 return unary64F0x2(mce, vatom);
1950
1951 case Iop_Sqrt32Fx4:
1952 case Iop_RSqrt32Fx4:
1953 case Iop_Recip32Fx4:
1954 return unary32Fx4(mce, vatom);
1955
1956 case Iop_Sqrt32F0x4:
1957 case Iop_RSqrt32F0x4:
1958 case Iop_Recip32F0x4:
1959 return unary32F0x4(mce, vatom);
1960
sewardjf0c1c582005-02-07 23:47:38 +00001961 case Iop_32UtoV128:
1962 case Iop_64UtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001963 return assignNew(mce, Ity_V128, unop(op, vatom));
1964
sewardjde8a5ae2004-11-06 14:20:54 +00001965 case Iop_F32toF64:
sewardj1e3830f2011-03-14 11:27:26 +00001966 case Iop_I32StoF64:
sewardj3598ef92004-11-11 02:13:30 +00001967 case Iop_NegF64:
1968 case Iop_SinF64:
1969 case Iop_CosF64:
1970 case Iop_TanF64:
1971 case Iop_SqrtF64:
1972 case Iop_AbsF64:
1973 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001974 return mkPCastTo(mce, Ity_I64, vatom);
1975
sewardj3598ef92004-11-11 02:13:30 +00001976 case Iop_Clz32:
1977 case Iop_Ctz32:
1978 return mkPCastTo(mce, Ity_I32, vatom);
1979
1980 case Iop_32Sto64:
1981 case Iop_32Uto64:
sewardjf0c1c582005-02-07 23:47:38 +00001982 case Iop_V128to64:
1983 case Iop_V128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001984 return assignNew(mce, Ity_I64, unop(op, vatom));
1985
sewardjde8a5ae2004-11-06 14:20:54 +00001986 case Iop_64to32:
1987 case Iop_64HIto32:
1988 case Iop_1Uto32:
1989 case Iop_8Uto32:
1990 case Iop_16Uto32:
1991 case Iop_16Sto32:
1992 case Iop_8Sto32:
1993 return assignNew(mce, Ity_I32, unop(op, vatom));
1994
1995 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001996 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001997 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001998 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001999 return assignNew(mce, Ity_I16, unop(op, vatom));
2000
2001 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00002002 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00002003 case Iop_32to8:
2004 return assignNew(mce, Ity_I8, unop(op, vatom));
2005
2006 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00002007 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00002008
sewardj3598ef92004-11-11 02:13:30 +00002009 case Iop_ReinterpF64asI64:
2010 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00002011 case Iop_ReinterpI32asF32:
sewardjf0c1c582005-02-07 23:47:38 +00002012 case Iop_NotV128:
sewardj69f9e3e2004-12-30 02:05:34 +00002013 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00002014 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00002015 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00002016 case Iop_Not8:
2017 case Iop_Not1:
2018 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00002019
sewardjde8a5ae2004-11-06 14:20:54 +00002020 default:
2021 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00002022 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00002023 }
2024}
2025
2026
sewardj69f9e3e2004-12-30 02:05:34 +00002027/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00002028static
sewardj69f9e3e2004-12-30 02:05:34 +00002029IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00002030{
2031 void* helper;
sewardjde8c9872005-03-25 13:48:55 +00002032 HChar* hname;
sewardjde8a5ae2004-11-06 14:20:54 +00002033 IRDirty* di;
2034 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00002035 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00002036
sewardj69f9e3e2004-12-30 02:05:34 +00002037 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00002038
2039 /* First, emit a definedness test for the address. This also sets
2040 the address (shadow) to 'defined' following the test. */
2041 complainIfUndefined( mce, addr );
2042
2043 /* Now cook up a call to the relevant helper function, to read the
2044 data V bits from shadow memory. */
2045 ty = shadowType(ty);
2046 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00002047 case Ity_I64: helper = &MC_(helperc_LOADV8);
2048 hname = "MC_(helperc_LOADV8)";
2049 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002050 case Ity_I32: helper = &MC_(helperc_LOADV4);
2051 hname = "MC_(helperc_LOADV4)";
2052 break;
2053 case Ity_I16: helper = &MC_(helperc_LOADV2);
2054 hname = "MC_(helperc_LOADV2)";
2055 break;
2056 case Ity_I8: helper = &MC_(helperc_LOADV1);
2057 hname = "MC_(helperc_LOADV1)";
2058 break;
2059 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00002060 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00002061 }
2062
sewardj3598ef92004-11-11 02:13:30 +00002063 /* Generate the actual address into addrAct. */
2064 if (bias == 0) {
2065 addrAct = addr;
2066 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002067 IROp mkAdd;
2068 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00002069 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00002070 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2071 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2072 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00002073 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2074 }
2075
sewardjde8a5ae2004-11-06 14:20:54 +00002076 /* We need to have a place to park the V bits we're just about to
2077 read. */
2078 datavbits = newIRTemp(mce->bb->tyenv, ty);
2079 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00002080 1/*regparms*/, hname, helper,
2081 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00002082 setHelperAnns( mce, di );
2083 stmt( mce->bb, IRStmt_Dirty(di) );
2084
2085 return mkexpr(datavbits);
2086}
2087
2088
2089static
sewardj69f9e3e2004-12-30 02:05:34 +00002090IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
2091{
2092 IRAtom *v64hi, *v64lo;
2093 switch (shadowType(ty)) {
2094 case Ity_I8:
2095 case Ity_I16:
2096 case Ity_I32:
2097 case Ity_I64:
2098 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
2099 case Ity_V128:
2100 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
2101 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
2102 return assignNew( mce,
2103 Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +00002104 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj69f9e3e2004-12-30 02:05:34 +00002105 default:
2106 VG_(tool_panic)("expr2vbits_LDle");
2107 }
2108}
2109
2110
2111static
florian99dd03e2013-01-29 03:56:06 +00002112IRAtom* expr2vbits_ITE ( MCEnv* mce,
2113 IRAtom* cond, IRAtom* iftrue, IRAtom* iffalse )
sewardjde8a5ae2004-11-06 14:20:54 +00002114{
florian99dd03e2013-01-29 03:56:06 +00002115 IRAtom *vbitsC, *vbits0, *vbits1;
sewardjde8a5ae2004-11-06 14:20:54 +00002116 IRType ty;
florian99dd03e2013-01-29 03:56:06 +00002117 /* Given ITE(cond,iftrue,iffalse), generate
2118 ITE(cond,iftrue#,iffalse#) `UifU` PCast(cond#)
sewardjde8a5ae2004-11-06 14:20:54 +00002119 That is, steer the V bits like the originals, but trash the
2120 result if the steering value is undefined. This gives
2121 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00002122 tl_assert(isOriginalAtom(mce, cond));
florian99dd03e2013-01-29 03:56:06 +00002123 tl_assert(isOriginalAtom(mce, iftrue));
2124 tl_assert(isOriginalAtom(mce, iffalse));
sewardjde8a5ae2004-11-06 14:20:54 +00002125
2126 vbitsC = expr2vbits(mce, cond);
florian99dd03e2013-01-29 03:56:06 +00002127 vbits0 = expr2vbits(mce, iffalse);
2128 vbits1 = expr2vbits(mce, iftrue);
sewardjde8a5ae2004-11-06 14:20:54 +00002129 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2130
2131 return
florian99dd03e2013-01-29 03:56:06 +00002132 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_ITE(cond, vbits1, vbits0)),
sewardjde8a5ae2004-11-06 14:20:54 +00002133 mkPCastTo(mce, ty, vbitsC) );
2134}
2135
2136/* --------- This is the main expression-handling function. --------- */
2137
2138static
2139IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2140{
2141 switch (e->tag) {
2142
2143 case Iex_Get:
2144 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2145
2146 case Iex_GetI:
2147 return shadow_GETI( mce, e->Iex.GetI.descr,
2148 e->Iex.GetI.ix, e->Iex.GetI.bias );
2149
sewardj478646f2008-05-01 20:13:04 +00002150 case Iex_RdTmp:
2151 return IRExpr_RdTmp( findShadowTmp(mce, e->Iex.RdTmp.tmp) );
sewardjde8a5ae2004-11-06 14:20:54 +00002152
2153 case Iex_Const:
2154 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2155
2156 case Iex_Binop:
2157 return expr2vbits_Binop(
2158 mce,
2159 e->Iex.Binop.op,
2160 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2161 );
2162
2163 case Iex_Unop:
2164 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2165
sewardj478646f2008-05-01 20:13:04 +00002166 case Iex_Load:
2167 return expr2vbits_LDle( mce, e->Iex.Load.ty,
2168 e->Iex.Load.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002169
2170 case Iex_CCall:
2171 return mkLazyN( mce, e->Iex.CCall.args,
2172 e->Iex.CCall.retty,
2173 e->Iex.CCall.cee );
2174
florian99dd03e2013-01-29 03:56:06 +00002175 case Iex_ITE:
2176 return expr2vbits_ITE( mce, e->Iex.ITE.cond, e->Iex.ITE.iftrue,
2177 e->Iex.ITE.iffalse);
sewardjde8a5ae2004-11-06 14:20:54 +00002178
2179 default:
2180 VG_(printf)("\n");
2181 ppIRExpr(e);
2182 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002183 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002184 }
2185}
2186
2187/*------------------------------------------------------------*/
2188/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2189/*------------------------------------------------------------*/
2190
2191/* Widen a value to the host word size. */
2192
2193static
2194IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2195{
sewardj69f9e3e2004-12-30 02:05:34 +00002196 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002197
sewardj8fc93742004-11-22 11:29:33 +00002198 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002199 tl_assert(isShadowAtom(mce,vatom));
2200
2201 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2202 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002203
sewardjde8a5ae2004-11-06 14:20:54 +00002204 if (tyH == Ity_I32) {
2205 switch (ty) {
2206 case Ity_I32: return vatom;
2207 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2208 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2209 default: goto unhandled;
2210 }
2211 } else {
2212 goto unhandled;
2213 }
2214 unhandled:
2215 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002216 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002217}
2218
2219
sewardj3598ef92004-11-11 02:13:30 +00002220/* Generate a shadow store. addr is always the original address atom.
2221 You can pass in either originals or V-bits for the data atom, but
2222 obviously not both. */
2223
sewardjde8a5ae2004-11-06 14:20:54 +00002224static
sewardj3598ef92004-11-11 02:13:30 +00002225void do_shadow_STle ( MCEnv* mce,
2226 IRAtom* addr, UInt bias,
2227 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002228{
sewardj69f9e3e2004-12-30 02:05:34 +00002229 IROp mkAdd;
2230 IRType ty, tyAddr;
2231 IRDirty *di, *diLo64, *diHi64;
2232 IRAtom *addrAct, *addrLo64, *addrHi64;
2233 IRAtom *vdataLo64, *vdataHi64;
2234 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002235 void* helper = NULL;
sewardj478646f2008-05-01 20:13:04 +00002236 HChar* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002237
2238 tyAddr = mce->hWordTy;
2239 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2240 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2241
2242 di = diLo64 = diHi64 = NULL;
2243 eBias = eBias0 = eBias8 = NULL;
2244 addrAct = addrLo64 = addrHi64 = NULL;
2245 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002246
sewardj3598ef92004-11-11 02:13:30 +00002247 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002248 tl_assert(!vdata);
2249 tl_assert(isOriginalAtom(mce, data));
2250 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002251 vdata = expr2vbits( mce, data );
2252 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002253 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002254 }
sewardjde8a5ae2004-11-06 14:20:54 +00002255
sewardj69f9e3e2004-12-30 02:05:34 +00002256 tl_assert(isOriginalAtom(mce,addr));
2257 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002258
2259 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002260
2261 /* First, emit a definedness test for the address. This also sets
2262 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002263 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002264
sewardj69f9e3e2004-12-30 02:05:34 +00002265 /* Now decide which helper function to call to write the data V
2266 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002267 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002268 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002269 case Ity_I64: helper = &MC_(helperc_STOREV8);
2270 hname = "MC_(helperc_STOREV8)";
2271 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002272 case Ity_I32: helper = &MC_(helperc_STOREV4);
2273 hname = "MC_(helperc_STOREV4)";
2274 break;
2275 case Ity_I16: helper = &MC_(helperc_STOREV2);
2276 hname = "MC_(helperc_STOREV2)";
2277 break;
2278 case Ity_I8: helper = &MC_(helperc_STOREV1);
2279 hname = "MC_(helperc_STOREV1)";
2280 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002281 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002282 }
2283
sewardj69f9e3e2004-12-30 02:05:34 +00002284 if (ty == Ity_V128) {
2285
sewardjf0c1c582005-02-07 23:47:38 +00002286 /* V128-bit case */
sewardj69f9e3e2004-12-30 02:05:34 +00002287 /* See comment in next clause re 64-bit regparms */
2288 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2289 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
sewardjf0c1c582005-02-07 23:47:38 +00002290 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002291 diLo64 = unsafeIRDirty_0_N(
2292 1/*regparms*/, hname, helper,
2293 mkIRExprVec_2( addrLo64, vdataLo64 ));
2294
2295 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2296 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
sewardjf0c1c582005-02-07 23:47:38 +00002297 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002298 diHi64 = unsafeIRDirty_0_N(
2299 1/*regparms*/, hname, helper,
2300 mkIRExprVec_2( addrHi64, vdataHi64 ));
2301
2302 setHelperAnns( mce, diLo64 );
2303 setHelperAnns( mce, diHi64 );
2304 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2305 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2306
sewardj3598ef92004-11-11 02:13:30 +00002307 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002308
2309 /* 8/16/32/64-bit cases */
2310 /* Generate the actual address into addrAct. */
2311 if (bias == 0) {
2312 addrAct = addr;
2313 } else {
2314 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2315 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2316 }
2317
2318 if (ty == Ity_I64) {
2319 /* We can't do this with regparm 2 on 32-bit platforms, since
2320 the back ends aren't clever enough to handle 64-bit
2321 regparm args. Therefore be different. */
2322 di = unsafeIRDirty_0_N(
2323 1/*regparms*/, hname, helper,
2324 mkIRExprVec_2( addrAct, vdata ));
2325 } else {
2326 di = unsafeIRDirty_0_N(
2327 2/*regparms*/, hname, helper,
2328 mkIRExprVec_2( addrAct,
2329 zwidenToHostWord( mce, vdata )));
2330 }
2331 setHelperAnns( mce, di );
2332 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002333 }
2334
sewardjde8a5ae2004-11-06 14:20:54 +00002335}
2336
2337
sewardj3598ef92004-11-11 02:13:30 +00002338/* Do lazy pessimistic propagation through a dirty helper call, by
2339 looking at the annotations on it. This is the most complex part of
2340 Memcheck. */
2341
2342static IRType szToITy ( Int n )
2343{
2344 switch (n) {
2345 case 1: return Ity_I8;
2346 case 2: return Ity_I16;
2347 case 4: return Ity_I32;
2348 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002349 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002350 }
2351}
2352
2353static
2354void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2355{
sewardj69f9e3e2004-12-30 02:05:34 +00002356 Int i, n, offset, toDo, gSz, gOff;
2357 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002358 IRType tyAddr, tySrc, tyDst;
2359 IRTemp dst;
2360
2361 /* First check the guard. */
2362 complainIfUndefined(mce, d->guard);
2363
2364 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002365 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002366
2367 /* Inputs: unmasked args */
2368 for (i = 0; d->args[i]; i++) {
2369 if (d->cee->mcx_mask & (1<<i)) {
2370 /* ignore this arg */
2371 } else {
2372 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2373 curr = mkUifU32(mce, here, curr);
2374 }
2375 }
2376
2377 /* Inputs: guest state that we read. */
2378 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002379 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002380 if (d->fxState[i].fx == Ifx_Write)
2381 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002382
2383 /* Ignore any sections marked as 'always defined'. */
2384 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2385 if (0)
2386 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2387 d->fxState[i].offset, d->fxState[i].size );
2388 continue;
2389 }
2390
sewardj3598ef92004-11-11 02:13:30 +00002391 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002392 consider it. If larger than 8 bytes, deal with it in 8-byte
2393 chunks. */
2394 gSz = d->fxState[i].size;
2395 gOff = d->fxState[i].offset;
2396 tl_assert(gSz > 0);
2397 while (True) {
2398 if (gSz == 0) break;
2399 n = gSz <= 8 ? gSz : 8;
2400 /* update 'curr' with UifU of the state slice
2401 gOff .. gOff+n-1 */
2402 tySrc = szToITy( n );
2403 src = assignNew( mce, tySrc,
2404 shadow_GET(mce, gOff, tySrc ) );
2405 here = mkPCastTo( mce, Ity_I32, src );
2406 curr = mkUifU32(mce, here, curr);
2407 gSz -= n;
2408 gOff += n;
2409 }
2410
sewardj3598ef92004-11-11 02:13:30 +00002411 }
2412
2413 /* Inputs: memory. First set up some info needed regardless of
2414 whether we're doing reads or writes. */
2415 tyAddr = Ity_INVALID;
2416
2417 if (d->mFx != Ifx_None) {
2418 /* Because we may do multiple shadow loads/stores from the same
2419 base address, it's best to do a single test of its
2420 definedness right now. Post-instrumentation optimisation
2421 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002422 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002423 complainIfUndefined(mce, d->mAddr);
2424
2425 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002426 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2427 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002428 }
2429
2430 /* Deal with memory inputs (reads or modifies) */
2431 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2432 offset = 0;
2433 toDo = d->mSize;
2434 /* chew off 32-bit chunks */
2435 while (toDo >= 4) {
2436 here = mkPCastTo(
2437 mce, Ity_I32,
2438 expr2vbits_LDle ( mce, Ity_I32,
2439 d->mAddr, d->mSize - toDo )
2440 );
2441 curr = mkUifU32(mce, here, curr);
2442 toDo -= 4;
2443 }
2444 /* chew off 16-bit chunks */
2445 while (toDo >= 2) {
2446 here = mkPCastTo(
2447 mce, Ity_I32,
2448 expr2vbits_LDle ( mce, Ity_I16,
2449 d->mAddr, d->mSize - toDo )
2450 );
2451 curr = mkUifU32(mce, here, curr);
2452 toDo -= 2;
2453 }
sewardj69f9e3e2004-12-30 02:05:34 +00002454 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002455 }
2456
2457 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2458 all the inputs to the helper. Now we need to re-distribute the
2459 results to all destinations. */
2460
2461 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002462 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002463 dst = findShadowTmp(mce, d->tmp);
2464 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2465 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2466 }
2467
2468 /* Outputs: guest state that we write or modify. */
2469 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002470 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002471 if (d->fxState[i].fx == Ifx_Read)
2472 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002473 /* Ignore any sections marked as 'always defined'. */
2474 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2475 continue;
2476 /* This state element is written or modified. So we need to
2477 consider it. If larger than 8 bytes, deal with it in 8-byte
2478 chunks. */
2479 gSz = d->fxState[i].size;
2480 gOff = d->fxState[i].offset;
2481 tl_assert(gSz > 0);
2482 while (True) {
2483 if (gSz == 0) break;
2484 n = gSz <= 8 ? gSz : 8;
2485 /* Write suitably-casted 'curr' to the state slice
2486 gOff .. gOff+n-1 */
2487 tyDst = szToITy( n );
2488 do_shadow_PUT( mce, gOff,
2489 NULL, /* original atom */
2490 mkPCastTo( mce, tyDst, curr ) );
2491 gSz -= n;
2492 gOff += n;
2493 }
sewardj3598ef92004-11-11 02:13:30 +00002494 }
2495
2496 /* Outputs: memory that we write or modify. */
2497 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2498 offset = 0;
2499 toDo = d->mSize;
2500 /* chew off 32-bit chunks */
2501 while (toDo >= 4) {
2502 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2503 NULL, /* original data */
2504 mkPCastTo( mce, Ity_I32, curr ) );
2505 toDo -= 4;
2506 }
2507 /* chew off 16-bit chunks */
2508 while (toDo >= 2) {
2509 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2510 NULL, /* original data */
2511 mkPCastTo( mce, Ity_I16, curr ) );
2512 toDo -= 2;
2513 }
sewardj69f9e3e2004-12-30 02:05:34 +00002514 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002515 }
2516
2517}
2518
2519
sewardjde8a5ae2004-11-06 14:20:54 +00002520/*------------------------------------------------------------*/
2521/*--- Memcheck main ---*/
2522/*------------------------------------------------------------*/
2523
sewardj3598ef92004-11-11 02:13:30 +00002524static Bool isBogusAtom ( IRAtom* at )
2525{
2526 ULong n = 0;
2527 IRConst* con;
sewardj496a58d2005-03-20 18:44:44 +00002528 tl_assert(isIRAtom(at));
sewardj478646f2008-05-01 20:13:04 +00002529 if (at->tag == Iex_RdTmp)
sewardj3598ef92004-11-11 02:13:30 +00002530 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002531 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002532 con = at->Iex.Const.con;
2533 switch (con->tag) {
2534 case Ico_U8: n = (ULong)con->Ico.U8; break;
2535 case Ico_U16: n = (ULong)con->Ico.U16; break;
2536 case Ico_U32: n = (ULong)con->Ico.U32; break;
2537 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002538 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002539 }
2540 /* VG_(printf)("%llx\n", n); */
2541 return (n == 0xFEFEFEFF
2542 || n == 0x80808080
2543 || n == 0x1010101
2544 || n == 1010100);
2545}
2546
sewardj5f438dd2011-06-16 11:36:23 +00002547__attribute__((unused))
sewardj3598ef92004-11-11 02:13:30 +00002548static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2549{
2550 Int i;
2551 IRExpr* e;
2552 switch (st->tag) {
sewardj478646f2008-05-01 20:13:04 +00002553 case Ist_WrTmp:
2554 e = st->Ist.WrTmp.data;
sewardj3598ef92004-11-11 02:13:30 +00002555 switch (e->tag) {
2556 case Iex_Get:
sewardj478646f2008-05-01 20:13:04 +00002557 case Iex_RdTmp:
sewardj3598ef92004-11-11 02:13:30 +00002558 return False;
2559 case Iex_Unop:
2560 return isBogusAtom(e->Iex.Unop.arg);
2561 case Iex_Binop:
2562 return isBogusAtom(e->Iex.Binop.arg1)
2563 || isBogusAtom(e->Iex.Binop.arg2);
florian99dd03e2013-01-29 03:56:06 +00002564 case Iex_ITE:
2565 return isBogusAtom(e->Iex.ITE.cond)
2566 || isBogusAtom(e->Iex.ITE.iftrue)
2567 || isBogusAtom(e->Iex.ITE.iffalse);
sewardj478646f2008-05-01 20:13:04 +00002568 case Iex_Load:
2569 return isBogusAtom(e->Iex.Load.addr);
sewardj3598ef92004-11-11 02:13:30 +00002570 case Iex_CCall:
2571 for (i = 0; e->Iex.CCall.args[i]; i++)
2572 if (isBogusAtom(e->Iex.CCall.args[i]))
2573 return True;
2574 return False;
2575 default:
2576 goto unhandled;
2577 }
2578 case Ist_Put:
2579 return isBogusAtom(st->Ist.Put.data);
sewardj478646f2008-05-01 20:13:04 +00002580 case Ist_Store:
2581 return isBogusAtom(st->Ist.Store.addr)
2582 || isBogusAtom(st->Ist.Store.data);
sewardj3598ef92004-11-11 02:13:30 +00002583 case Ist_Exit:
sewardj1ea1b612005-03-26 13:02:20 +00002584 return isBogusAtom(st->Ist.Exit.guard);
sewardj3598ef92004-11-11 02:13:30 +00002585 default:
2586 unhandled:
2587 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002588 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002589 }
2590}
sewardj3598ef92004-11-11 02:13:30 +00002591
sewardj478646f2008-05-01 20:13:04 +00002592IRSB* mc_instrument ( void* closureV,
2593 IRSB* bb_in, VexGuestLayout* layout,
2594 VexGuestExtents* vge,
sewardj1ea1b612005-03-26 13:02:20 +00002595 IRType gWordTy, IRType hWordTy )
sewardjde8a5ae2004-11-06 14:20:54 +00002596{
sewardj3598ef92004-11-11 02:13:30 +00002597 Bool verboze = False; //True;
2598
2599 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002600
2601 Int i, j, first_stmt;
2602 IRStmt* st;
2603 MCEnv mce;
2604
2605 /* Set up BB */
sewardjf6c8ebf2007-02-06 01:52:52 +00002606 IRSB* bb = emptyIRSB();
sewardj478646f2008-05-01 20:13:04 +00002607 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
2608 bb->next = deepCopyIRExpr(bb_in->next);
sewardjde8a5ae2004-11-06 14:20:54 +00002609 bb->jumpkind = bb_in->jumpkind;
2610
2611 /* Set up the running environment. Only .bb is modified as we go
2612 along. */
2613 mce.bb = bb;
2614 mce.layout = layout;
2615 mce.n_originalTmps = bb->tyenv->types_used;
2616 mce.hWordTy = hWordTy;
2617 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2618 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002619 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002620
2621 /* Iterate over the stmts. */
2622
2623 for (i = 0; i < bb_in->stmts_used; i++) {
2624 st = bb_in->stmts[i];
2625 if (!st) continue;
2626
sewardj69f9e3e2004-12-30 02:05:34 +00002627 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002628
2629 /*
2630 if (!hasBogusLiterals) {
2631 hasBogusLiterals = checkForBogusLiterals(st);
2632 if (hasBogusLiterals) {
2633 VG_(printf)("bogus: ");
2634 ppIRStmt(st);
2635 VG_(printf)("\n");
2636 }
2637 }
2638 */
sewardjde8a5ae2004-11-06 14:20:54 +00002639 first_stmt = bb->stmts_used;
2640
2641 if (verboze) {
2642 ppIRStmt(st);
2643 VG_(printf)("\n\n");
2644 }
2645
2646 switch (st->tag) {
2647
sewardj478646f2008-05-01 20:13:04 +00002648 case Ist_WrTmp:
2649 assign( bb, findShadowTmp(&mce, st->Ist.WrTmp.tmp),
2650 expr2vbits( &mce, st->Ist.WrTmp.data) );
sewardjde8a5ae2004-11-06 14:20:54 +00002651 break;
2652
2653 case Ist_Put:
2654 do_shadow_PUT( &mce,
2655 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002656 st->Ist.Put.data,
2657 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002658 break;
2659
2660 case Ist_PutI:
2661 do_shadow_PUTI( &mce,
florian4180af32012-12-24 00:25:34 +00002662 st->Ist.PutI.details->descr,
2663 st->Ist.PutI.details->ix,
2664 st->Ist.PutI.details->bias,
2665 st->Ist.PutI.details->data );
sewardjde8a5ae2004-11-06 14:20:54 +00002666 break;
2667
sewardj478646f2008-05-01 20:13:04 +00002668 case Ist_Store:
2669 do_shadow_STle( &mce, st->Ist.Store.addr, 0/* addr bias */,
2670 st->Ist.Store.data,
sewardj3598ef92004-11-11 02:13:30 +00002671 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002672 break;
2673
2674 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002675 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002676 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002677 break;
2678
2679 case Ist_Dirty:
2680 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002681 break;
2682
sewardj1ea1b612005-03-26 13:02:20 +00002683 case Ist_IMark:
2684 case Ist_NoOp:
2685 break;
2686
sewardjde8a5ae2004-11-06 14:20:54 +00002687 default:
2688 VG_(printf)("\n");
2689 ppIRStmt(st);
2690 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002691 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002692
2693 } /* switch (st->tag) */
2694
2695 if (verboze) {
2696 for (j = first_stmt; j < bb->stmts_used; j++) {
2697 VG_(printf)(" ");
2698 ppIRStmt(bb->stmts[j]);
2699 VG_(printf)("\n");
2700 }
2701 VG_(printf)("\n");
2702 }
2703
sewardjf6c8ebf2007-02-06 01:52:52 +00002704 addStmtToIRSB(bb, st);
sewardjde8a5ae2004-11-06 14:20:54 +00002705
2706 }
2707
2708 /* Now we need to complain if the jump target is undefined. */
2709 first_stmt = bb->stmts_used;
2710
2711 if (verboze) {
2712 VG_(printf)("bb->next = ");
2713 ppIRExpr(bb->next);
2714 VG_(printf)("\n\n");
2715 }
2716
2717 complainIfUndefined( &mce, bb->next );
2718
2719 if (verboze) {
2720 for (j = first_stmt; j < bb->stmts_used; j++) {
2721 VG_(printf)(" ");
2722 ppIRStmt(bb->stmts[j]);
2723 VG_(printf)("\n");
2724 }
2725 VG_(printf)("\n");
2726 }
2727
2728 return bb;
2729}
cerionaee45242005-03-17 14:03:36 +00002730#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002731
2732/*--------------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00002733/*--- end test_main.c ---*/
sewardjde8a5ae2004-11-06 14:20:54 +00002734/*--------------------------------------------------------------------*/