blob: 5ddd5f4268e3477bc3452a879d365831e502daf1 [file] [log] [blame]
sewardjc97096c2004-06-30 09:28:04 +00001
2/*---------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00003/*--- begin test_main.c ---*/
sewardjc97096c2004-06-30 09:28:04 +00004/*---------------------------------------------------------------*/
5
sewardj752f9062010-05-03 21:38:49 +00006/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj25e54732012-08-05 15:36:51 +000010 Copyright (C) 2004-2012 OpenWorks LLP
sewardj752f9062010-05-03 21:38:49 +000011 info@open-works.net
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
34*/
35
sewardjc97096c2004-06-30 09:28:04 +000036#include <stdio.h>
37#include <stdlib.h>
sewardjced9fe52004-07-07 11:55:36 +000038#include <assert.h>
sewardj9b1004e2004-10-30 22:25:40 +000039#include <string.h>
sewardjc97096c2004-06-30 09:28:04 +000040
sewardjced9fe52004-07-07 11:55:36 +000041#include "libvex_basictypes.h"
42#include "libvex.h"
sewardjc97096c2004-06-30 09:28:04 +000043
sewardjabe017e2004-10-29 23:42:36 +000044#include "test_main.h"
45
46
sewardjc97096c2004-06-30 09:28:04 +000047/*---------------------------------------------------------------*/
48/*--- Test ---*/
49/*---------------------------------------------------------------*/
50
sewardjce605f92004-07-05 14:39:15 +000051
sewardj2b515872004-07-05 20:50:45 +000052__attribute__ ((noreturn))
sewardj41f43bc2004-07-08 14:23:22 +000053static
sewardjce605f92004-07-05 14:39:15 +000054void failure_exit ( void )
55{
56 fprintf(stdout, "VEX did failure_exit. Bye.\n");
57 exit(1);
58}
59
sewardj41f43bc2004-07-08 14:23:22 +000060static
sewardj58277842005-02-07 03:11:17 +000061void log_bytes ( HChar* bytes, Int nbytes )
sewardjce605f92004-07-05 14:39:15 +000062{
63 fwrite ( bytes, 1, nbytes, stdout );
64}
65
sewardjced9fe52004-07-07 11:55:36 +000066#define N_LINEBUF 10000
sewardjde8c9872005-03-25 13:48:55 +000067static HChar linebuf[N_LINEBUF];
sewardjced9fe52004-07-07 11:55:36 +000068
cerion094d1392005-06-20 13:45:57 +000069#define N_ORIGBUF 10000
sewardj4459baa2004-09-10 20:00:46 +000070#define N_TRANSBUF 5000
sewardjced9fe52004-07-07 11:55:36 +000071
sewardj4459baa2004-09-10 20:00:46 +000072static UChar origbuf[N_ORIGBUF];
73static UChar transbuf[N_TRANSBUF];
sewardjced9fe52004-07-07 11:55:36 +000074
sewardj1f40a0a2004-07-21 12:28:07 +000075static Bool verbose = True;
sewardjced9fe52004-07-07 11:55:36 +000076
sewardj9b1004e2004-10-30 22:25:40 +000077/* Forwards */
sewardj478646f2008-05-01 20:13:04 +000078#if 1 /* UNUSED */
sewardj5f438dd2011-06-16 11:36:23 +000079//static IRSB* ac_instrument ( IRSB*, VexGuestLayout*, IRType );
sewardj478646f2008-05-01 20:13:04 +000080static
81IRSB* mc_instrument ( void* closureV,
82 IRSB* bb_in, VexGuestLayout* layout,
83 VexGuestExtents* vge,
84 IRType gWordTy, IRType hWordTy );
cerionaee45242005-03-17 14:03:36 +000085#endif
sewardj9b1004e2004-10-30 22:25:40 +000086
sewardjbc161a42011-06-07 21:28:38 +000087static Bool chase_into_not_ok ( void* opaque, Addr64 dst ) {
88 return False;
89}
90static UInt needs_self_check ( void* opaque, VexGuestExtents* vge ) {
91 return 0;
92}
sewardj9b1004e2004-10-30 22:25:40 +000093
sewardjced9fe52004-07-07 11:55:36 +000094int main ( int argc, char** argv )
sewardjce605f92004-07-05 14:39:15 +000095{
sewardjced9fe52004-07-07 11:55:36 +000096 FILE* f;
97 Int i;
sewardj4459baa2004-09-10 20:00:46 +000098 UInt u, sum;
sewardjced9fe52004-07-07 11:55:36 +000099 Addr32 orig_addr;
sewardjabe017e2004-10-29 23:42:36 +0000100 Int bb_number, n_bbs_done = 0;
sewardj72c72812005-01-19 11:49:45 +0000101 Int orig_nbytes, trans_used;
sewardjd887b862005-01-17 18:34:34 +0000102 VexTranslateResult tres;
sewardjb5bf2e02004-10-25 13:06:17 +0000103 VexControl vcon;
sewardj72c72812005-01-19 11:49:45 +0000104 VexGuestExtents vge;
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 */
sewardjabe017e2004-10-29 23:42:36 +0000130 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +0000131 &vcon );
sewardjced9fe52004-07-07 11:55:36 +0000132
sewardjea64e142004-07-22 16:47:21 +0000133
sewardjced9fe52004-07-07 11:55:36 +0000134 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +0000135
sewardj5f438dd2011-06-16 11:36:23 +0000136 __attribute__((unused))
137 char* unused1 = fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +0000138 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +0000139 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +0000140
141 if (n_bbs_done == TEST_N_BBS) break;
142 n_bbs_done++;
143
sewardjced9fe52004-07-07 11:55:36 +0000144 /* first line is: . bb-number bb-addr n-bytes */
145 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
146 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000147 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000148 assert(orig_nbytes >= 1);
149 assert(!feof(f));
sewardj5f438dd2011-06-16 11:36:23 +0000150 __attribute__((unused))
151 char* unused2 = fgets(linebuf, N_LINEBUF,f);
sewardjced9fe52004-07-07 11:55:36 +0000152 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000153
sewardjced9fe52004-07-07 11:55:36 +0000154 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000155 if (verbose)
sewardj07a54cc2005-02-04 21:18:55 +0000156 printf("============ Basic Block %d, Done %d, "
sewardj4459baa2004-09-10 20:00:46 +0000157 "Start %x, nbytes %2d ============",
sewardj07a54cc2005-02-04 21:18:55 +0000158 bb_number, n_bbs_done-1, orig_addr, orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000159
sewardj18475c52013-01-26 11:37:51 +0000160 /* thumb ITstate analysis needs to examine the 18 bytes
161 preceding the first instruction. So let's leave the first 18
162 zeroed out. */
163 memset(origbuf, 0, sizeof(origbuf));
164
sewardjced9fe52004-07-07 11:55:36 +0000165 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
166 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000167 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
sewardj18475c52013-01-26 11:37:51 +0000168 origbuf[18+ i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000169 }
170
sewardj5117ce12006-01-27 21:20:15 +0000171 /* FIXME: put sensible values into the .hwcaps fields */
sewardj9e6491a2005-07-02 19:24:10 +0000172 LibVEX_default_VexArchInfo(&vai_x86);
sewardjc4356f02007-11-09 21:15:04 +0000173 vai_x86.hwcaps = VEX_HWCAPS_X86_SSE1
174 | VEX_HWCAPS_X86_SSE2 | VEX_HWCAPS_X86_SSE3;
sewardj9e6491a2005-07-02 19:24:10 +0000175
176 LibVEX_default_VexArchInfo(&vai_amd64);
sewardj5117ce12006-01-27 21:20:15 +0000177 vai_amd64.hwcaps = 0;
sewardj9e6491a2005-07-02 19:24:10 +0000178
179 LibVEX_default_VexArchInfo(&vai_ppc32);
sewardj5117ce12006-01-27 21:20:15 +0000180 vai_ppc32.hwcaps = 0;
florian9138b172013-08-03 19:36:55 +0000181 vai_ppc32.ppc_icache_line_szB = 128;
sewardj02ef7162005-06-30 12:50:50 +0000182
sewardj18475c52013-01-26 11:37:51 +0000183 LibVEX_default_VexArchInfo(&vai_arm);
184 vai_arm.hwcaps = VEX_HWCAPS_ARM_VFP3 | VEX_HWCAPS_ARM_NEON | 7;
185
sewardjdd40fdf2006-12-24 02:20:24 +0000186 LibVEX_default_VexAbiInfo(&vbi);
sewardjc6f970f2012-04-02 21:54:49 +0000187 vbi.guest_stack_redzone_size = 128;
sewardjaca070a2006-10-17 00:28:22 +0000188
sewardj17c7f952005-12-15 14:02:34 +0000189 /* ----- Set up args for LibVEX_Translate ----- */
sewardjc6f970f2012-04-02 21:54:49 +0000190
sewardj18475c52013-01-26 11:37:51 +0000191 vta.abiinfo_both = vbi;
192 vta.guest_bytes = &origbuf[18];
193 vta.guest_bytes_addr = (Addr64)orig_addr;
194 vta.callback_opaque = NULL;
195 vta.chase_into_ok = chase_into_not_ok;
196 vta.guest_extents = &vge;
197 vta.host_bytes = transbuf;
198 vta.host_bytes_size = N_TRANSBUF;
199 vta.host_bytes_used = &trans_used;
200
sewardjc4356f02007-11-09 21:15:04 +0000201#if 0 /* ppc32 -> ppc32 */
sewardj17c7f952005-12-15 14:02:34 +0000202 vta.arch_guest = VexArchPPC32;
203 vta.archinfo_guest = vai_ppc32;
204 vta.arch_host = VexArchPPC32;
205 vta.archinfo_host = vai_ppc32;
sewardj07a54cc2005-02-04 21:18:55 +0000206#endif
sewardjc279b3f2005-03-16 18:10:45 +0000207#if 0 /* amd64 -> amd64 */
sewardj17c7f952005-12-15 14:02:34 +0000208 vta.arch_guest = VexArchAMD64;
209 vta.archinfo_guest = vai_amd64;
210 vta.arch_host = VexArchAMD64;
211 vta.archinfo_host = vai_amd64;
sewardj07a54cc2005-02-04 21:18:55 +0000212#endif
sewardj18475c52013-01-26 11:37:51 +0000213#if 0 /* x86 -> x86 */
sewardj17c7f952005-12-15 14:02:34 +0000214 vta.arch_guest = VexArchX86;
215 vta.archinfo_guest = vai_x86;
216 vta.arch_host = VexArchX86;
217 vta.archinfo_host = vai_x86;
sewardjc279b3f2005-03-16 18:10:45 +0000218#endif
sewardj18475c52013-01-26 11:37:51 +0000219#if 1 /* arm -> arm */
220 vta.arch_guest = VexArchARM;
221 vta.archinfo_guest = vai_arm;
222 vta.arch_host = VexArchARM;
223 vta.archinfo_host = vai_arm;
224 /* ARM/Thumb only hacks, that are needed to keep the ITstate
225 analyser in the front end happy. */
226 vta.guest_bytes = &origbuf[18 +1];
227 vta.guest_bytes_addr = (Addr64)(&origbuf[18 +1]);
228#endif
sewardjc6f970f2012-04-02 21:54:49 +0000229
230#if 1 /* no instrumentation */
sewardj17c7f952005-12-15 14:02:34 +0000231 vta.instrument1 = NULL;
232 vta.instrument2 = NULL;
sewardj9e7448b2004-11-18 13:44:15 +0000233#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000234#if 0 /* addrcheck */
sewardj17c7f952005-12-15 14:02:34 +0000235 vta.instrument1 = ac_instrument;
236 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000237#endif
sewardjc6f970f2012-04-02 21:54:49 +0000238#if 0 /* memcheck */
sewardj17c7f952005-12-15 14:02:34 +0000239 vta.instrument1 = mc_instrument;
240 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000241#endif
sewardjbc161a42011-06-07 21:28:38 +0000242 vta.needs_self_check = needs_self_check;
sewardjc716aea2006-01-17 01:48:46 +0000243 vta.preamble_function = NULL;
sewardj17c7f952005-12-15 14:02:34 +0000244 vta.traceflags = TEST_FLAGS;
sewardjc6f970f2012-04-02 21:54:49 +0000245 vta.addProfInc = False;
sewardj18475c52013-01-26 11:37:51 +0000246 vta.sigill_diag = True;
sewardjc6f970f2012-04-02 21:54:49 +0000247
248 vta.disp_cp_chain_me_to_slowEP = (void*)0x12345678;
249 vta.disp_cp_chain_me_to_fastEP = (void*)0x12345679;
250 vta.disp_cp_xindir = (void*)0x1234567A;
251 vta.disp_cp_xassisted = (void*)0x1234567B;
sewardj17c7f952005-12-15 14:02:34 +0000252
sewardjc4356f02007-11-09 21:15:04 +0000253 vta.finaltidy = NULL;
254
sewardj17c7f952005-12-15 14:02:34 +0000255 for (i = 0; i < TEST_N_ITERS; i++)
256 tres = LibVEX_Translate ( &vta );
sewardjabe017e2004-10-29 23:42:36 +0000257
sewardjbc161a42011-06-07 21:28:38 +0000258 if (tres.status != VexTransOK)
259 printf("\ntres = %d\n", (Int)tres.status);
260 assert(tres.status == VexTransOK);
261 assert(tres.n_sc_extents == 0);
sewardj72c72812005-01-19 11:49:45 +0000262 assert(vge.n_used == 1);
263 assert((UInt)(vge.len[0]) == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000264
sewardj4459baa2004-09-10 20:00:46 +0000265 sum = 0;
266 for (i = 0; i < trans_used; i++)
267 sum += (UInt)transbuf[i];
sewardjde8c9872005-03-25 13:48:55 +0000268 printf ( " %6.2f ... %u\n",
269 (double)trans_used / (double)vge.len[0], sum );
sewardjced9fe52004-07-07 11:55:36 +0000270 }
271
272 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000273 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000274 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000275
sewardjce605f92004-07-05 14:39:15 +0000276 return 0;
277}
sewardj9b1004e2004-10-30 22:25:40 +0000278
279//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000280//////////////////////////////////////////////////////////////////////
281//////////////////////////////////////////////////////////////////////
282//////////////////////////////////////////////////////////////////////
283//////////////////////////////////////////////////////////////////////
284//////////////////////////////////////////////////////////////////////
285//////////////////////////////////////////////////////////////////////
286//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000287
sewardj1ea1b612005-03-26 13:02:20 +0000288#if 0 /* UNUSED */
289
sewardj9b1004e2004-10-30 22:25:40 +0000290static
sewardjde8a5ae2004-11-06 14:20:54 +0000291__attribute((noreturn))
sewardjde8c9872005-03-25 13:48:55 +0000292void panic ( HChar* s )
sewardj9b1004e2004-10-30 22:25:40 +0000293{
294 printf("\npanic: %s\n", s);
295 failure_exit();
296}
297
298static
sewardjf6c8ebf2007-02-06 01:52:52 +0000299IRSB* ac_instrument (IRSB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000300{
301/* Use this rather than eg. -1 because it's a UInt. */
302#define INVALID_DATA_SIZE 999999
303
304 Int i;
305 Int sz;
306 IRCallee* helper;
307 IRStmt* st;
308 IRExpr* data;
309 IRExpr* addr;
310 Bool needSz;
311
312 /* Set up BB */
sewardjf6c8ebf2007-02-06 01:52:52 +0000313 IRSB* bb = emptyIRSB();
sewardj9b1004e2004-10-30 22:25:40 +0000314 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
315 bb->next = dopyIRExpr(bb_in->next);
316 bb->jumpkind = bb_in->jumpkind;
317
318 /* No loads to consider in ->next. */
sewardj496a58d2005-03-20 18:44:44 +0000319 assert(isIRAtom(bb_in->next));
sewardj9b1004e2004-10-30 22:25:40 +0000320
321 for (i = 0; i < bb_in->stmts_used; i++) {
322 st = bb_in->stmts[i];
323 if (!st) continue;
324
325 switch (st->tag) {
326
327 case Ist_Tmp:
328 data = st->Ist.Tmp.data;
329 if (data->tag == Iex_LDle) {
330 addr = data->Iex.LDle.addr;
331 sz = sizeofIRType(data->Iex.LDle.ty);
332 needSz = False;
333 switch (sz) {
334 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000335 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000336 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000337 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000338 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000339 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000340 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000341 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000342 needSz = True; break;
343 }
344 if (needSz) {
sewardjf6c8ebf2007-02-06 01:52:52 +0000345 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000346 bb,
347 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000348 unsafeIRDirty_0_N( helper->regparms,
349 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000350 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
351 ));
352 } else {
sewardjf6c8ebf2007-02-06 01:52:52 +0000353 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000354 bb,
355 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000356 unsafeIRDirty_0_N( helper->regparms,
357 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000358 mkIRExprVec_1(addr) )
359 ));
360 }
361 }
362 break;
363
364 case Ist_STle:
365 data = st->Ist.STle.data;
366 addr = st->Ist.STle.addr;
sewardj496a58d2005-03-20 18:44:44 +0000367 assert(isIRAtom(data));
368 assert(isIRAtom(addr));
sewardj9b1004e2004-10-30 22:25:40 +0000369 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
370 needSz = False;
371 switch (sz) {
372 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000373 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000374 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000375 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000376 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000377 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000378 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000379 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000380 needSz = True; break;
381 }
382 if (needSz) {
sewardjf6c8ebf2007-02-06 01:52:52 +0000383 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000384 bb,
385 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000386 unsafeIRDirty_0_N( helper->regparms,
387 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000388 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
389 ));
390 } else {
sewardjf6c8ebf2007-02-06 01:52:52 +0000391 addStmtToIRSB(
sewardj9b1004e2004-10-30 22:25:40 +0000392 bb,
393 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000394 unsafeIRDirty_0_N( helper->regparms,
395 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000396 mkIRExprVec_1(addr) )
397 ));
398 }
399 break;
400
401 case Ist_Put:
sewardj496a58d2005-03-20 18:44:44 +0000402 assert(isIRAtom(st->Ist.Put.data));
sewardj9b1004e2004-10-30 22:25:40 +0000403 break;
404
405 case Ist_PutI:
sewardj496a58d2005-03-20 18:44:44 +0000406 assert(isIRAtom(st->Ist.PutI.ix));
407 assert(isIRAtom(st->Ist.PutI.data));
sewardj9b1004e2004-10-30 22:25:40 +0000408 break;
409
410 case Ist_Exit:
sewardj496a58d2005-03-20 18:44:44 +0000411 assert(isIRAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000412 break;
413
414 case Ist_Dirty:
415 /* If the call doesn't interact with memory, we ain't
416 interested. */
417 if (st->Ist.Dirty.details->mFx == Ifx_None)
418 break;
419 goto unhandled;
420
421 default:
422 unhandled:
423 printf("\n");
424 ppIRStmt(st);
425 printf("\n");
426 panic("addrcheck: unhandled IRStmt");
427 }
428
sewardjf6c8ebf2007-02-06 01:52:52 +0000429 addStmtToIRSB( bb, dopyIRStmt(st));
sewardj9b1004e2004-10-30 22:25:40 +0000430 }
431
432 return bb;
433}
cerionaee45242005-03-17 14:03:36 +0000434#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +0000435
436//////////////////////////////////////////////////////////////////////
437//////////////////////////////////////////////////////////////////////
438//////////////////////////////////////////////////////////////////////
439//////////////////////////////////////////////////////////////////////
440//////////////////////////////////////////////////////////////////////
441//////////////////////////////////////////////////////////////////////
442//////////////////////////////////////////////////////////////////////
443//////////////////////////////////////////////////////////////////////
444
sewardj478646f2008-05-01 20:13:04 +0000445#if 1 /* UNUSED */
446
447static
448__attribute((noreturn))
449void panic ( HChar* s )
450{
451 printf("\npanic: %s\n", s);
452 failure_exit();
453}
sewardj1ea1b612005-03-26 13:02:20 +0000454
sewardj69f9e3e2004-12-30 02:05:34 +0000455#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000456#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000457#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000458#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000459#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000460
cerionaee45242005-03-17 14:03:36 +0000461
sewardjde8c9872005-03-25 13:48:55 +0000462static void MC_helperc_complain_undef ( void );
463static void MC_helperc_LOADV8 ( void );
464static void MC_helperc_LOADV4 ( void );
465static void MC_helperc_LOADV2 ( void );
466static void MC_helperc_LOADV1 ( void );
sewardj1ea1b612005-03-26 13:02:20 +0000467static void MC_helperc_STOREV8( void );
468static void MC_helperc_STOREV4( void );
469static void MC_helperc_STOREV2( void );
470static void MC_helperc_STOREV1( void );
sewardjde8c9872005-03-25 13:48:55 +0000471static void MC_helperc_value_check0_fail( void );
472static void MC_helperc_value_check1_fail( void );
473static void MC_helperc_value_check4_fail( void );
474
475static void MC_helperc_complain_undef ( void ) { }
476static void MC_helperc_LOADV8 ( void ) { }
477static void MC_helperc_LOADV4 ( void ) { }
478static void MC_helperc_LOADV2 ( void ) { }
479static void MC_helperc_LOADV1 ( void ) { }
sewardj1ea1b612005-03-26 13:02:20 +0000480static void MC_helperc_STOREV8( void ) { }
481static void MC_helperc_STOREV4( void ) { }
482static void MC_helperc_STOREV2( void ) { }
483static void MC_helperc_STOREV1( void ) { }
sewardjde8c9872005-03-25 13:48:55 +0000484static void MC_helperc_value_check0_fail( void ) { }
485static void MC_helperc_value_check1_fail( void ) { }
486static void MC_helperc_value_check4_fail( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000487
488
sewardj3598ef92004-11-11 02:13:30 +0000489/*--------------------------------------------------------------------*/
490/*--- Instrument IR to perform memory checking operations. ---*/
491/*--- mc_translate.c ---*/
492/*--------------------------------------------------------------------*/
493
494/*
495 This file is part of MemCheck, a heavyweight Valgrind tool for
496 detecting memory errors.
497
sewardj25e54732012-08-05 15:36:51 +0000498 Copyright (C) 2000-2012 Julian Seward
sewardj3598ef92004-11-11 02:13:30 +0000499 jseward@acm.org
500
501 This program is free software; you can redistribute it and/or
502 modify it under the terms of the GNU General Public License as
503 published by the Free Software Foundation; either version 2 of the
504 License, or (at your option) any later version.
505
506 This program is distributed in the hope that it will be useful, but
507 WITHOUT ANY WARRANTY; without even the implied warranty of
508 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
509 General Public License for more details.
510
511 You should have received a copy of the GNU General Public License
512 along with this program; if not, write to the Free Software
513 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
514 02111-1307, USA.
515
516 The GNU General Public License is contained in the file COPYING.
517*/
518
519//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000520
521
522/*------------------------------------------------------------*/
523/*--- Forward decls ---*/
524/*------------------------------------------------------------*/
525
526struct _MCEnv;
527
528static IRType shadowType ( IRType ty );
529static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
530
531
532/*------------------------------------------------------------*/
533/*--- Memcheck running state, and tmp management. ---*/
534/*------------------------------------------------------------*/
535
536/* Carries around state during memcheck instrumentation. */
537typedef
538 struct _MCEnv {
539 /* MODIFIED: the bb being constructed. IRStmts are added. */
sewardjf6c8ebf2007-02-06 01:52:52 +0000540 IRSB* bb;
sewardjde8a5ae2004-11-06 14:20:54 +0000541
542 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
543 original temps to their current their current shadow temp.
544 Initially all entries are IRTemp_INVALID. Entries are added
545 lazily since many original temps are not used due to
546 optimisation prior to instrumentation. Note that floating
547 point original tmps are shadowed by integer tmps of the same
548 size, and Bit-typed original tmps are shadowed by the type
549 Ity_I8. See comment below. */
550 IRTemp* tmpMap;
551 Int n_originalTmps; /* for range checking */
552
553 /* READONLY: the guest layout. This indicates which parts of
554 the guest state should be regarded as 'always defined'. */
555 VexGuestLayout* layout;
556 /* READONLY: the host word type. Needed for constructing
557 arguments of type 'HWord' to be passed to helper functions.
558 Ity_I32 or Ity_I64 only. */
559 IRType hWordTy;
560 }
561 MCEnv;
562
563/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
564 demand), as they are encountered. This is for two reasons.
565
566 (1) (less important reason): Many original tmps are unused due to
567 initial IR optimisation, and we do not want to spaces in tables
568 tracking them.
569
570 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
571 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000572 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000573 It is necessary to support making multiple assignments to a shadow
574 -- specifically, after testing a shadow for definedness, it needs
575 to be made defined. But IR's SSA property disallows this.
576
577 (2) (more important reason): Therefore, when a shadow needs to get
578 a new value, a new temporary is created, the value is assigned to
579 that, and the tmpMap is updated to reflect the new binding.
580
581 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000582 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000583 there's a read-before-write error in the original tmps. The IR
584 sanity checker should catch all such anomalies, however.
585*/
586
587/* Find the tmp currently shadowing the given original tmp. If none
588 so far exists, allocate one. */
589static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
590{
sewardj69f9e3e2004-12-30 02:05:34 +0000591 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000592 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000593 mce->tmpMap[orig]
594 = newIRTemp(mce->bb->tyenv,
595 shadowType(mce->bb->tyenv->types[orig]));
596 }
597 return mce->tmpMap[orig];
598}
599
600/* Allocate a new shadow for the given original tmp. This means any
601 previous shadow is abandoned. This is needed because it is
602 necessary to give a new value to a shadow once it has been tested
603 for undefinedness, but unfortunately IR's SSA property disallows
604 this. Instead we must abandon the old shadow, allocate a new one
605 and use that instead. */
606static void newShadowTmp ( MCEnv* mce, IRTemp orig )
607{
sewardj69f9e3e2004-12-30 02:05:34 +0000608 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000609 mce->tmpMap[orig]
610 = newIRTemp(mce->bb->tyenv,
611 shadowType(mce->bb->tyenv->types[orig]));
612}
613
614
615/*------------------------------------------------------------*/
616/*--- IRAtoms -- a subset of IRExprs ---*/
617/*------------------------------------------------------------*/
618
619/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj496a58d2005-03-20 18:44:44 +0000620 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardjde8a5ae2004-11-06 14:20:54 +0000621 input, most of this code deals in atoms. Usefully, a value atom
622 always has a V-value which is also an atom: constants are shadowed
623 by constants, and temps are shadowed by the corresponding shadow
624 temporary. */
625
626typedef IRExpr IRAtom;
627
628/* (used for sanity checks only): is this an atom which looks
629 like it's from original code? */
630static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
631{
632 if (a1->tag == Iex_Const)
633 return True;
sewardj478646f2008-05-01 20:13:04 +0000634 if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < mce->n_originalTmps)
sewardjde8a5ae2004-11-06 14:20:54 +0000635 return True;
636 return False;
637}
638
639/* (used for sanity checks only): is this an atom which looks
640 like it's from shadow code? */
641static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
642{
643 if (a1->tag == Iex_Const)
644 return True;
sewardj478646f2008-05-01 20:13:04 +0000645 if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= mce->n_originalTmps)
sewardjde8a5ae2004-11-06 14:20:54 +0000646 return True;
647 return False;
648}
649
650/* (used for sanity checks only): check that both args are atoms and
651 are identically-kinded. */
652static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
653{
sewardj478646f2008-05-01 20:13:04 +0000654 if (a1->tag == Iex_RdTmp && a1->tag == Iex_RdTmp)
sewardjde8a5ae2004-11-06 14:20:54 +0000655 return True;
656 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
657 return True;
658 return False;
659}
660
661
662/*------------------------------------------------------------*/
663/*--- Type management ---*/
664/*------------------------------------------------------------*/
665
666/* Shadow state is always accessed using integer types. This returns
667 an integer type with the same size (as per sizeofIRType) as the
668 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000669 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000670
671static IRType shadowType ( IRType ty )
672{
673 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000674 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000675 case Ity_I8:
676 case Ity_I16:
677 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000678 case Ity_I64: return ty;
679 case Ity_F32: return Ity_I32;
680 case Ity_F64: return Ity_I64;
681 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000682 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000683 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000684 }
685}
686
687/* Produce a 'defined' value of the given shadow type. Should only be
688 supplied shadow types (Bit/I8/I16/I32/UI64). */
689static IRExpr* definedOfType ( IRType ty ) {
690 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000691 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
692 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
693 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
694 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
695 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
696 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
697 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000698 }
699}
700
701
702/*------------------------------------------------------------*/
703/*--- Constructing IR fragments ---*/
704/*------------------------------------------------------------*/
705
706/* assign value to tmp */
707#define assign(_bb,_tmp,_expr) \
sewardj478646f2008-05-01 20:13:04 +0000708 addStmtToIRSB((_bb), IRStmt_WrTmp((_tmp),(_expr)))
sewardjde8a5ae2004-11-06 14:20:54 +0000709
710/* add stmt to a bb */
711#define stmt(_bb,_stmt) \
sewardjf6c8ebf2007-02-06 01:52:52 +0000712 addStmtToIRSB((_bb), (_stmt))
sewardjde8a5ae2004-11-06 14:20:54 +0000713
714/* build various kinds of expressions */
715#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
716#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
717#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
718#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
719#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
720#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000721#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardj478646f2008-05-01 20:13:04 +0000722#define mkexpr(_tmp) IRExpr_RdTmp((_tmp))
sewardjde8a5ae2004-11-06 14:20:54 +0000723
724/* bind the given expression to a new temporary, and return the
725 temporary. This effectively converts an arbitrary expression into
726 an atom. */
727static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
728 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
729 assign(mce->bb, t, e);
730 return mkexpr(t);
731}
732
733
734/*------------------------------------------------------------*/
735/*--- Constructing definedness primitive ops ---*/
736/*------------------------------------------------------------*/
737
738/* --------- Defined-if-either-defined --------- */
739
740static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000741 tl_assert(isShadowAtom(mce,a1));
742 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000743 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
744}
745
746static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000747 tl_assert(isShadowAtom(mce,a1));
748 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000749 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
750}
751
752static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000753 tl_assert(isShadowAtom(mce,a1));
754 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000755 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
756}
757
sewardj69f9e3e2004-12-30 02:05:34 +0000758static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
759 tl_assert(isShadowAtom(mce,a1));
760 tl_assert(isShadowAtom(mce,a2));
761 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
762}
763
sewardjf0c1c582005-02-07 23:47:38 +0000764static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000765 tl_assert(isShadowAtom(mce,a1));
766 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000767 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000768}
769
sewardjde8a5ae2004-11-06 14:20:54 +0000770/* --------- Undefined-if-either-undefined --------- */
771
772static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000773 tl_assert(isShadowAtom(mce,a1));
774 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000775 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
776}
777
778static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000779 tl_assert(isShadowAtom(mce,a1));
780 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000781 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
782}
783
784static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000785 tl_assert(isShadowAtom(mce,a1));
786 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000787 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
788}
789
790static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000791 tl_assert(isShadowAtom(mce,a1));
792 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000793 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
794}
795
sewardjf0c1c582005-02-07 23:47:38 +0000796static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000797 tl_assert(isShadowAtom(mce,a1));
798 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000799 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000800}
801
802static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000803 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000804 case Ity_I8: return mkUifU8(mce, a1, a2);
805 case Ity_I16: return mkUifU16(mce, a1, a2);
806 case Ity_I32: return mkUifU32(mce, a1, a2);
807 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardjf0c1c582005-02-07 23:47:38 +0000808 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000809 default:
810 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000811 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000812 }
813}
814
815/* --------- The Left-family of operations. --------- */
816
817static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000818 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000819 /* It's safe to duplicate a1 since it's only an atom */
820 return assignNew(mce, Ity_I8,
821 binop(Iop_Or8, a1,
822 assignNew(mce, Ity_I8,
823 /* unop(Iop_Neg8, a1)))); */
824 binop(Iop_Sub8, mkU8(0), a1) )));
825}
826
827static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000828 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000829 /* It's safe to duplicate a1 since it's only an atom */
830 return assignNew(mce, Ity_I16,
831 binop(Iop_Or16, a1,
832 assignNew(mce, Ity_I16,
833 /* unop(Iop_Neg16, a1)))); */
834 binop(Iop_Sub16, mkU16(0), a1) )));
835}
836
837static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000838 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000839 /* It's safe to duplicate a1 since it's only an atom */
840 return assignNew(mce, Ity_I32,
841 binop(Iop_Or32, a1,
842 assignNew(mce, Ity_I32,
843 /* unop(Iop_Neg32, a1)))); */
844 binop(Iop_Sub32, mkU32(0), a1) )));
845}
846
847/* --------- 'Improvement' functions for AND/OR. --------- */
848
849/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
850 defined (0); all other -> undefined (1).
851*/
852static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
853{
sewardj69f9e3e2004-12-30 02:05:34 +0000854 tl_assert(isOriginalAtom(mce, data));
855 tl_assert(isShadowAtom(mce, vbits));
856 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000857 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
858}
859
sewardj3598ef92004-11-11 02:13:30 +0000860static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
861{
sewardj69f9e3e2004-12-30 02:05:34 +0000862 tl_assert(isOriginalAtom(mce, data));
863 tl_assert(isShadowAtom(mce, vbits));
864 tl_assert(sameKindedAtoms(data, vbits));
sewardj3598ef92004-11-11 02:13:30 +0000865 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
866}
867
sewardjde8a5ae2004-11-06 14:20:54 +0000868static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
869{
sewardj69f9e3e2004-12-30 02:05:34 +0000870 tl_assert(isOriginalAtom(mce, data));
871 tl_assert(isShadowAtom(mce, vbits));
872 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000873 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
874}
875
sewardj69f9e3e2004-12-30 02:05:34 +0000876static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
877{
878 tl_assert(isOriginalAtom(mce, data));
879 tl_assert(isShadowAtom(mce, vbits));
880 tl_assert(sameKindedAtoms(data, vbits));
881 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
882}
883
sewardjf0c1c582005-02-07 23:47:38 +0000884static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000885{
886 tl_assert(isOriginalAtom(mce, data));
887 tl_assert(isShadowAtom(mce, vbits));
888 tl_assert(sameKindedAtoms(data, vbits));
sewardjf0c1c582005-02-07 23:47:38 +0000889 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj69f9e3e2004-12-30 02:05:34 +0000890}
891
sewardjde8a5ae2004-11-06 14:20:54 +0000892/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
893 defined (0); all other -> undefined (1).
894*/
895static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
896{
sewardj69f9e3e2004-12-30 02:05:34 +0000897 tl_assert(isOriginalAtom(mce, data));
898 tl_assert(isShadowAtom(mce, vbits));
899 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000900 return assignNew(
901 mce, Ity_I8,
902 binop(Iop_Or8,
903 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
904 vbits) );
905}
906
907static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
908{
sewardj69f9e3e2004-12-30 02:05:34 +0000909 tl_assert(isOriginalAtom(mce, data));
910 tl_assert(isShadowAtom(mce, vbits));
911 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000912 return assignNew(
913 mce, Ity_I16,
914 binop(Iop_Or16,
915 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
916 vbits) );
917}
918
919static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
920{
sewardj69f9e3e2004-12-30 02:05:34 +0000921 tl_assert(isOriginalAtom(mce, data));
922 tl_assert(isShadowAtom(mce, vbits));
923 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000924 return assignNew(
925 mce, Ity_I32,
926 binop(Iop_Or32,
927 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
928 vbits) );
929}
930
sewardj69f9e3e2004-12-30 02:05:34 +0000931static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
932{
933 tl_assert(isOriginalAtom(mce, data));
934 tl_assert(isShadowAtom(mce, vbits));
935 tl_assert(sameKindedAtoms(data, vbits));
936 return assignNew(
937 mce, Ity_I64,
938 binop(Iop_Or64,
939 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
940 vbits) );
941}
942
sewardjf0c1c582005-02-07 23:47:38 +0000943static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000944{
945 tl_assert(isOriginalAtom(mce, data));
946 tl_assert(isShadowAtom(mce, vbits));
947 tl_assert(sameKindedAtoms(data, vbits));
948 return assignNew(
949 mce, Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +0000950 binop(Iop_OrV128,
951 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj69f9e3e2004-12-30 02:05:34 +0000952 vbits) );
953}
954
sewardjde8a5ae2004-11-06 14:20:54 +0000955/* --------- Pessimising casts. --------- */
956
957static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
958{
sewardj8fc93742004-11-22 11:29:33 +0000959 IRType ty;
960 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000961 /* Note, dst_ty is a shadow type, not an original type. */
962 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000963 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000964 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
965 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000966 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000967 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000968 tmp1 = vbits;
969 break;
970 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000971 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000972 break;
973 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000974 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000975 break;
976 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000977 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000978 break;
979 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000980 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000981 break;
982 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000983 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000984 }
sewardj69f9e3e2004-12-30 02:05:34 +0000985 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000986 /* Now widen up to the dst type. */
987 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000988 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000989 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000990 case Ity_I8:
991 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000992 case Ity_I16:
993 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
994 case Ity_I32:
995 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
996 case Ity_I64:
997 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000998 case Ity_V128:
999 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardjf0c1c582005-02-07 23:47:38 +00001000 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +00001001 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +00001002 default:
1003 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001004 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +00001005 }
1006}
1007
1008
1009/*------------------------------------------------------------*/
1010/*--- Emit a test and complaint if something is undefined. ---*/
1011/*------------------------------------------------------------*/
1012
1013/* Set the annotations on a dirty helper to indicate that the stack
1014 pointer and instruction pointers might be read. This is the
1015 behaviour of all 'emit-a-complaint' style functions we might
1016 call. */
1017
1018static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
1019 di->nFxState = 2;
1020 di->fxState[0].fx = Ifx_Read;
1021 di->fxState[0].offset = mce->layout->offset_SP;
1022 di->fxState[0].size = mce->layout->sizeof_SP;
1023 di->fxState[1].fx = Ifx_Read;
1024 di->fxState[1].offset = mce->layout->offset_IP;
1025 di->fxState[1].size = mce->layout->sizeof_IP;
1026}
1027
1028
1029/* Check the supplied **original** atom for undefinedness, and emit a
1030 complaint if so. Once that happens, mark it as defined. This is
1031 possible because the atom is either a tmp or literal. If it's a
1032 tmp, it will be shadowed by a tmp, and so we can set the shadow to
1033 be defined. In fact as mentioned above, we will have to allocate a
1034 new tmp to carry the new 'defined' shadow value, and update the
1035 original->tmp mapping accordingly; we cannot simply assign a new
1036 value to an existing shadow tmp as this breaks SSAness -- resulting
1037 in the post-instrumentation sanity checker spluttering in disapproval.
1038*/
1039static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
1040{
sewardj8fc93742004-11-22 11:29:33 +00001041 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001042 IRType ty;
1043 Int sz;
sewardj8fc93742004-11-22 11:29:33 +00001044 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +00001045 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +00001046
sewardjde8a5ae2004-11-06 14:20:54 +00001047 /* Since the original expression is atomic, there's no duplicated
1048 work generated by making multiple V-expressions for it. So we
1049 don't really care about the possibility that someone else may
1050 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +00001051 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +00001052 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001053 tl_assert(isShadowAtom(mce, vatom));
1054 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001055
sewardj8fc93742004-11-22 11:29:33 +00001056 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +00001057
1058 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +00001059 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +00001060
sewardj8fc93742004-11-22 11:29:33 +00001061 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +00001062 /* cond will be 0 if all defined, and 1 if any not defined. */
1063
sewardj3598ef92004-11-11 02:13:30 +00001064 switch (sz) {
1065 case 0:
1066 di = unsafeIRDirty_0_N( 0/*regparms*/,
1067 "MC_(helperc_value_check0_fail)",
1068 &MC_(helperc_value_check0_fail),
1069 mkIRExprVec_0()
1070 );
1071 break;
1072 case 1:
1073 di = unsafeIRDirty_0_N( 0/*regparms*/,
1074 "MC_(helperc_value_check1_fail)",
1075 &MC_(helperc_value_check1_fail),
1076 mkIRExprVec_0()
1077 );
1078 break;
1079 case 4:
1080 di = unsafeIRDirty_0_N( 0/*regparms*/,
1081 "MC_(helperc_value_check4_fail)",
1082 &MC_(helperc_value_check4_fail),
1083 mkIRExprVec_0()
1084 );
1085 break;
1086 default:
1087 di = unsafeIRDirty_0_N( 1/*regparms*/,
1088 "MC_(helperc_complain_undef)",
1089 &MC_(helperc_complain_undef),
1090 mkIRExprVec_1( mkIRExpr_HWord( sz ))
1091 );
1092 break;
1093 }
sewardjde8a5ae2004-11-06 14:20:54 +00001094 di->guard = cond;
1095 setHelperAnns( mce, di );
1096 stmt( mce->bb, IRStmt_Dirty(di));
1097
1098 /* Set the shadow tmp to be defined. First, update the
1099 orig->shadow tmp mapping to reflect the fact that this shadow is
1100 getting a new value. */
sewardj496a58d2005-03-20 18:44:44 +00001101 tl_assert(isIRAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001102 /* sameKindedAtoms ... */
sewardj478646f2008-05-01 20:13:04 +00001103 if (vatom->tag == Iex_RdTmp) {
1104 tl_assert(atom->tag == Iex_RdTmp);
1105 newShadowTmp(mce, atom->Iex.RdTmp.tmp);
1106 assign(mce->bb, findShadowTmp(mce, atom->Iex.RdTmp.tmp),
sewardjde8a5ae2004-11-06 14:20:54 +00001107 definedOfType(ty));
1108 }
1109}
1110
1111
1112/*------------------------------------------------------------*/
1113/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
1114/*------------------------------------------------------------*/
1115
1116/* Examine the always-defined sections declared in layout to see if
1117 the (offset,size) section is within one. Note, is is an error to
1118 partially fall into such a region: (offset,size) should either be
1119 completely in such a region or completely not-in such a region.
1120*/
1121static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1122{
1123 Int minoffD, maxoffD, i;
1124 Int minoff = offset;
1125 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001126 tl_assert((minoff & ~0xFFFF) == 0);
1127 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001128
1129 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1130 minoffD = mce->layout->alwaysDefd[i].offset;
1131 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001132 tl_assert((minoffD & ~0xFFFF) == 0);
1133 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001134
1135 if (maxoff < minoffD || maxoffD < minoff)
1136 continue; /* no overlap */
1137 if (minoff >= minoffD && maxoff <= maxoffD)
1138 return True; /* completely contained in an always-defd section */
1139
sewardj69f9e3e2004-12-30 02:05:34 +00001140 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001141 }
1142 return False; /* could not find any containing section */
1143}
1144
1145
1146/* Generate into bb suitable actions to shadow this Put. If the state
1147 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001148 supplied V bits to the shadow state. We can pass in either an
1149 original atom or a V-atom, but not both. In the former case the
1150 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001151*/
1152static
sewardj3598ef92004-11-11 02:13:30 +00001153void do_shadow_PUT ( MCEnv* mce, Int offset,
1154 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001155{
sewardj8fc93742004-11-22 11:29:33 +00001156 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001157 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001158 tl_assert(!vatom);
1159 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001160 vatom = expr2vbits( mce, atom );
1161 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001162 tl_assert(vatom);
1163 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001164 }
1165
sewardj8fc93742004-11-22 11:29:33 +00001166 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001167 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001168 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1169 /* later: no ... */
1170 /* emit code to emit a complaint if any of the vbits are 1. */
1171 /* complainIfUndefined(mce, atom); */
1172 } else {
1173 /* Do a plain shadow Put. */
1174 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1175 }
1176}
1177
1178
1179/* Return an expression which contains the V bits corresponding to the
1180 given GETI (passed in in pieces).
1181*/
1182static
1183void do_shadow_PUTI ( MCEnv* mce,
sewardj478646f2008-05-01 20:13:04 +00001184 IRRegArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
sewardjde8a5ae2004-11-06 14:20:54 +00001185{
sewardj8fc93742004-11-22 11:29:33 +00001186 IRAtom* vatom;
1187 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001188 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001189
sewardj69f9e3e2004-12-30 02:05:34 +00001190 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001191 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001192 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001193 ty = descr->elemTy;
1194 tyS = shadowType(ty);
1195 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001196 tl_assert(ty != Ity_I1);
1197 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001198 complainIfUndefined(mce,ix);
1199 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1200 /* later: no ... */
1201 /* emit code to emit a complaint if any of the vbits are 1. */
1202 /* complainIfUndefined(mce, atom); */
1203 } else {
1204 /* Do a cloned version of the Put that refers to the shadow
1205 area. */
sewardj478646f2008-05-01 20:13:04 +00001206 IRRegArray* new_descr
1207 = mkIRRegArray( descr->base + mce->layout->total_sizeB,
sewardjde8a5ae2004-11-06 14:20:54 +00001208 tyS, descr->nElems);
florian4180af32012-12-24 00:25:34 +00001209 stmt( mce->bb, IRStmt_PutI( mkIRPutI( new_descr, ix, bias, vatom ) ));
sewardjde8a5ae2004-11-06 14:20:54 +00001210 }
1211}
1212
1213
1214/* Return an expression which contains the V bits corresponding to the
1215 given GET (passed in in pieces).
1216*/
1217static
1218IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1219{
1220 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001221 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001222 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1223 /* Always defined, return all zeroes of the relevant type */
1224 return definedOfType(tyS);
1225 } else {
1226 /* return a cloned version of the Get that refers to the shadow
1227 area. */
1228 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1229 }
1230}
1231
1232
1233/* Return an expression which contains the V bits corresponding to the
1234 given GETI (passed in in pieces).
1235*/
1236static
sewardj478646f2008-05-01 20:13:04 +00001237IRExpr* shadow_GETI ( MCEnv* mce, IRRegArray* descr, IRAtom* ix, Int bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001238{
1239 IRType ty = descr->elemTy;
1240 IRType tyS = shadowType(ty);
1241 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001242 tl_assert(ty != Ity_I1);
1243 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001244 complainIfUndefined(mce,ix);
1245 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1246 /* Always defined, return all zeroes of the relevant type */
1247 return definedOfType(tyS);
1248 } else {
1249 /* return a cloned version of the Get that refers to the shadow
1250 area. */
sewardj478646f2008-05-01 20:13:04 +00001251 IRRegArray* new_descr
1252 = mkIRRegArray( descr->base + mce->layout->total_sizeB,
sewardjde8a5ae2004-11-06 14:20:54 +00001253 tyS, descr->nElems);
1254 return IRExpr_GetI( new_descr, ix, bias );
1255 }
1256}
1257
1258
1259/*------------------------------------------------------------*/
1260/*--- Generating approximations for unknown operations, ---*/
1261/*--- using lazy-propagate semantics ---*/
1262/*------------------------------------------------------------*/
1263
1264/* Lazy propagation of undefinedness from two values, resulting in the
1265 specified shadow type.
1266*/
1267static
1268IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1269{
1270 /* force everything via 32-bit intermediaries. */
1271 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001272 tl_assert(isShadowAtom(mce,va1));
1273 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001274 at = mkPCastTo(mce, Ity_I32, va1);
1275 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1276 at = mkPCastTo(mce, finalVty, at);
1277 return at;
1278}
1279
1280
1281/* Do the lazy propagation game from a null-terminated vector of
1282 atoms. This is presumably the arguments to a helper call, so the
1283 IRCallee info is also supplied in order that we can know which
1284 arguments should be ignored (via the .mcx_mask field).
1285*/
1286static
1287IRAtom* mkLazyN ( MCEnv* mce,
1288 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1289{
1290 Int i;
1291 IRAtom* here;
1292 IRAtom* curr = definedOfType(Ity_I32);
1293 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001294 tl_assert(i < 32);
1295 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001296 /* Only take notice of this arg if the callee's mc-exclusion
1297 mask does not say it is to be excluded. */
1298 if (cee->mcx_mask & (1<<i)) {
1299 /* the arg is to be excluded from definedness checking. Do
1300 nothing. */
1301 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1302 } else {
1303 /* calculate the arg's definedness, and pessimistically merge
1304 it in. */
1305 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1306 curr = mkUifU32(mce, here, curr);
1307 }
1308 }
1309 return mkPCastTo(mce, finalVtype, curr );
1310}
1311
1312
1313/*------------------------------------------------------------*/
1314/*--- Generating expensive sequences for exact carry-chain ---*/
1315/*--- propagation in add/sub and related operations. ---*/
1316/*------------------------------------------------------------*/
1317
1318static
sewardj5f438dd2011-06-16 11:36:23 +00001319__attribute__((unused))
sewardjde8a5ae2004-11-06 14:20:54 +00001320IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1321 IRAtom* aa, IRAtom* bb )
1322{
sewardj69f9e3e2004-12-30 02:05:34 +00001323 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001324 IRType ty;
1325 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001326
sewardj69f9e3e2004-12-30 02:05:34 +00001327 tl_assert(isShadowAtom(mce,qaa));
1328 tl_assert(isShadowAtom(mce,qbb));
1329 tl_assert(isOriginalAtom(mce,aa));
1330 tl_assert(isOriginalAtom(mce,bb));
1331 tl_assert(sameKindedAtoms(qaa,aa));
1332 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001333
sewardj8fc93742004-11-22 11:29:33 +00001334 ty = Ity_I32;
1335 opAND = Iop_And32;
1336 opOR = Iop_Or32;
1337 opXOR = Iop_Xor32;
1338 opNOT = Iop_Not32;
1339 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001340
1341 // a_min = aa & ~qaa
1342 a_min = assignNew(mce,ty,
1343 binop(opAND, aa,
1344 assignNew(mce,ty, unop(opNOT, qaa))));
1345
1346 // b_min = bb & ~qbb
1347 b_min = assignNew(mce,ty,
1348 binop(opAND, bb,
1349 assignNew(mce,ty, unop(opNOT, qbb))));
1350
1351 // a_max = aa | qaa
1352 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1353
1354 // b_max = bb | qbb
1355 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1356
1357 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1358 return
1359 assignNew(mce,ty,
1360 binop( opOR,
1361 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1362 assignNew(mce,ty,
1363 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1364 assignNew(mce,ty, binop(opADD, a_max, b_max))
1365 )
1366 )
1367 )
1368 );
1369}
1370
1371
1372/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001373/*--- Helpers for dealing with vector primops. ---*/
1374/*------------------------------------------------------------*/
1375
1376/* Vector pessimisation -- pessimise within each lane individually. */
1377
1378static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1379{
1380 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1381}
1382
1383static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1384{
1385 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1386}
1387
1388static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1389{
1390 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1391}
1392
1393static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1394{
1395 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1396}
1397
1398
1399/* Here's a simple scheme capable of handling ops derived from SSE1
1400 code and while only generating ops that can be efficiently
1401 implemented in SSE1. */
1402
1403/* All-lanes versions are straightforward:
1404
sewardjf0c1c582005-02-07 23:47:38 +00001405 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj69f9e3e2004-12-30 02:05:34 +00001406
1407 unary32Fx4(x,y) ==> PCast32x4(x#)
1408
1409 Lowest-lane-only versions are more complex:
1410
sewardjf0c1c582005-02-07 23:47:38 +00001411 binary32F0x4(x,y) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001412 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001413 PCast32(V128to32(UifUV128(x#,y#)))
sewardj69f9e3e2004-12-30 02:05:34 +00001414 )
1415
1416 This is perhaps not so obvious. In particular, it's faster to
sewardjf0c1c582005-02-07 23:47:38 +00001417 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj69f9e3e2004-12-30 02:05:34 +00001418 obvious scheme of taking the bottom 32 bits of each operand
1419 and doing a 32-bit UifU. Basically since UifU is fast and
1420 chopping lanes off vector values is slow.
1421
1422 Finally:
1423
sewardjf0c1c582005-02-07 23:47:38 +00001424 unary32F0x4(x) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001425 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001426 PCast32(V128to32(x#))
sewardj69f9e3e2004-12-30 02:05:34 +00001427 )
1428
1429 Where:
1430
1431 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1432 PCast32x4(v#) = CmpNEZ32x4(v#)
1433*/
1434
1435static
1436IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1437{
1438 IRAtom* at;
1439 tl_assert(isShadowAtom(mce, vatomX));
1440 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001441 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001442 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1443 return at;
1444}
1445
1446static
1447IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1448{
1449 IRAtom* at;
1450 tl_assert(isShadowAtom(mce, vatomX));
1451 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1452 return at;
1453}
1454
1455static
1456IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1457{
1458 IRAtom* at;
1459 tl_assert(isShadowAtom(mce, vatomX));
1460 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001461 at = mkUifUV128(mce, vatomX, vatomY);
1462 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001463 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001464 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001465 return at;
1466}
1467
1468static
1469IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1470{
1471 IRAtom* at;
1472 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001473 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001474 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001475 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001476 return at;
1477}
1478
1479/* --- ... and ... 64Fx2 versions of the same ... --- */
1480
1481static
1482IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1483{
1484 IRAtom* at;
1485 tl_assert(isShadowAtom(mce, vatomX));
1486 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001487 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001488 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1489 return at;
1490}
1491
1492static
1493IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1494{
1495 IRAtom* at;
1496 tl_assert(isShadowAtom(mce, vatomX));
1497 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1498 return at;
1499}
1500
1501static
1502IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1503{
1504 IRAtom* at;
1505 tl_assert(isShadowAtom(mce, vatomX));
1506 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001507 at = mkUifUV128(mce, vatomX, vatomY);
1508 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001509 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001510 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001511 return at;
1512}
1513
1514static
1515IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1516{
1517 IRAtom* at;
1518 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001519 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001520 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001521 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001522 return at;
1523}
1524
1525/* --- --- Vector saturated narrowing --- --- */
1526
1527/* This is quite subtle. What to do is simple:
1528
1529 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1530
1531 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1532
1533 Why this is right is not so simple. Consider a lane in the args,
1534 vatom1 or 2, doesn't matter.
1535
1536 After the PCast, that lane is all 0s (defined) or all
1537 1s(undefined).
1538
1539 Both signed and unsigned saturating narrowing of all 0s produces
1540 all 0s, which is what we want.
1541
1542 The all-1s case is more complex. Unsigned narrowing interprets an
1543 all-1s input as the largest unsigned integer, and so produces all
1544 1s as a result since that is the largest unsigned value at the
1545 smaller width.
1546
1547 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1548 to -1, so we still wind up with all 1s at the smaller width.
1549
1550 So: In short, pessimise the args, then apply the original narrowing
1551 op.
1552*/
1553static
sewardjf0c1c582005-02-07 23:47:38 +00001554IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardj69f9e3e2004-12-30 02:05:34 +00001555 IRAtom* vatom1, IRAtom* vatom2)
1556{
1557 IRAtom *at1, *at2, *at3;
1558 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1559 switch (narrow_op) {
sewardj5f438dd2011-06-16 11:36:23 +00001560 case Iop_QNarrowBin32Sto16Sx8: pcast = mkPCast32x4; break;
1561 case Iop_QNarrowBin16Sto8Sx16: pcast = mkPCast16x8; break;
1562 case Iop_QNarrowBin16Sto8Ux16: pcast = mkPCast16x8; break;
sewardjf0c1c582005-02-07 23:47:38 +00001563 default: VG_(tool_panic)("vectorNarrowV128");
sewardj69f9e3e2004-12-30 02:05:34 +00001564 }
1565 tl_assert(isShadowAtom(mce,vatom1));
1566 tl_assert(isShadowAtom(mce,vatom2));
1567 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1568 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1569 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1570 return at3;
1571}
1572
1573
1574/* --- --- Vector integer arithmetic --- --- */
1575
1576/* Simple ... UifU the args and per-lane pessimise the results. */
1577static
1578IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1579{
1580 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001581 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001582 at = mkPCast8x16(mce, at);
1583 return at;
1584}
1585
1586static
1587IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1588{
1589 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001590 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001591 at = mkPCast16x8(mce, at);
1592 return at;
1593}
1594
1595static
1596IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1597{
1598 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001599 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001600 at = mkPCast32x4(mce, at);
1601 return at;
1602}
1603
1604static
1605IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1606{
1607 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001608 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001609 at = mkPCast64x2(mce, at);
1610 return at;
1611}
1612
1613
1614/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001615/*--- Generate shadow values from all kinds of IRExprs. ---*/
1616/*------------------------------------------------------------*/
1617
1618static
1619IRAtom* expr2vbits_Binop ( MCEnv* mce,
1620 IROp op,
1621 IRAtom* atom1, IRAtom* atom2 )
1622{
1623 IRType and_or_ty;
1624 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1625 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1626 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1627
1628 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1629 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1630
sewardj69f9e3e2004-12-30 02:05:34 +00001631 tl_assert(isOriginalAtom(mce,atom1));
1632 tl_assert(isOriginalAtom(mce,atom2));
1633 tl_assert(isShadowAtom(mce,vatom1));
1634 tl_assert(isShadowAtom(mce,vatom2));
1635 tl_assert(sameKindedAtoms(atom1,vatom1));
1636 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001637 switch (op) {
1638
sewardjf0c1c582005-02-07 23:47:38 +00001639 /* V128-bit SIMD (SSE2-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001640
1641 case Iop_ShrN16x8:
1642 case Iop_ShrN32x4:
1643 case Iop_ShrN64x2:
1644 case Iop_SarN16x8:
1645 case Iop_SarN32x4:
1646 case Iop_ShlN16x8:
1647 case Iop_ShlN32x4:
1648 case Iop_ShlN64x2:
1649 /* Same scheme as with all other shifts. */
1650 complainIfUndefined(mce, atom2);
1651 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1652
1653 case Iop_QSub8Ux16:
1654 case Iop_QSub8Sx16:
1655 case Iop_Sub8x16:
1656 case Iop_Min8Ux16:
1657 case Iop_Max8Ux16:
1658 case Iop_CmpGT8Sx16:
1659 case Iop_CmpEQ8x16:
1660 case Iop_Avg8Ux16:
1661 case Iop_QAdd8Ux16:
1662 case Iop_QAdd8Sx16:
1663 case Iop_Add8x16:
1664 return binary8Ix16(mce, vatom1, vatom2);
1665
1666 case Iop_QSub16Ux8:
1667 case Iop_QSub16Sx8:
1668 case Iop_Sub16x8:
1669 case Iop_Mul16x8:
1670 case Iop_MulHi16Sx8:
1671 case Iop_MulHi16Ux8:
1672 case Iop_Min16Sx8:
1673 case Iop_Max16Sx8:
1674 case Iop_CmpGT16Sx8:
1675 case Iop_CmpEQ16x8:
1676 case Iop_Avg16Ux8:
1677 case Iop_QAdd16Ux8:
1678 case Iop_QAdd16Sx8:
1679 case Iop_Add16x8:
1680 return binary16Ix8(mce, vatom1, vatom2);
1681
1682 case Iop_Sub32x4:
sewardj2fdd4162010-08-22 12:59:02 +00001683 case Iop_QSub32Sx4:
1684 case Iop_QSub32Ux4:
sewardj69f9e3e2004-12-30 02:05:34 +00001685 case Iop_CmpGT32Sx4:
1686 case Iop_CmpEQ32x4:
1687 case Iop_Add32x4:
sewardj2fdd4162010-08-22 12:59:02 +00001688 case Iop_QAdd32Ux4:
1689 case Iop_QAdd32Sx4:
sewardj69f9e3e2004-12-30 02:05:34 +00001690 return binary32Ix4(mce, vatom1, vatom2);
1691
1692 case Iop_Sub64x2:
sewardj2fdd4162010-08-22 12:59:02 +00001693 case Iop_QSub64Ux2:
1694 case Iop_QSub64Sx2:
sewardj69f9e3e2004-12-30 02:05:34 +00001695 case Iop_Add64x2:
sewardj2fdd4162010-08-22 12:59:02 +00001696 case Iop_QAdd64Ux2:
1697 case Iop_QAdd64Sx2:
sewardj69f9e3e2004-12-30 02:05:34 +00001698 return binary64Ix2(mce, vatom1, vatom2);
1699
sewardj5f438dd2011-06-16 11:36:23 +00001700 case Iop_QNarrowBin32Sto16Sx8:
1701 case Iop_QNarrowBin16Sto8Sx16:
1702 case Iop_QNarrowBin16Sto8Ux16:
sewardjf0c1c582005-02-07 23:47:38 +00001703 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001704
1705 case Iop_Sub64Fx2:
1706 case Iop_Mul64Fx2:
1707 case Iop_Min64Fx2:
1708 case Iop_Max64Fx2:
1709 case Iop_Div64Fx2:
1710 case Iop_CmpLT64Fx2:
1711 case Iop_CmpLE64Fx2:
1712 case Iop_CmpEQ64Fx2:
1713 case Iop_Add64Fx2:
1714 return binary64Fx2(mce, vatom1, vatom2);
1715
1716 case Iop_Sub64F0x2:
1717 case Iop_Mul64F0x2:
1718 case Iop_Min64F0x2:
1719 case Iop_Max64F0x2:
1720 case Iop_Div64F0x2:
1721 case Iop_CmpLT64F0x2:
1722 case Iop_CmpLE64F0x2:
1723 case Iop_CmpEQ64F0x2:
1724 case Iop_Add64F0x2:
1725 return binary64F0x2(mce, vatom1, vatom2);
1726
sewardjf0c1c582005-02-07 23:47:38 +00001727 /* V128-bit SIMD (SSE1-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001728
1729 case Iop_Sub32Fx4:
1730 case Iop_Mul32Fx4:
1731 case Iop_Min32Fx4:
1732 case Iop_Max32Fx4:
1733 case Iop_Div32Fx4:
1734 case Iop_CmpLT32Fx4:
1735 case Iop_CmpLE32Fx4:
1736 case Iop_CmpEQ32Fx4:
1737 case Iop_Add32Fx4:
1738 return binary32Fx4(mce, vatom1, vatom2);
1739
1740 case Iop_Sub32F0x4:
1741 case Iop_Mul32F0x4:
1742 case Iop_Min32F0x4:
1743 case Iop_Max32F0x4:
1744 case Iop_Div32F0x4:
1745 case Iop_CmpLT32F0x4:
1746 case Iop_CmpLE32F0x4:
1747 case Iop_CmpEQ32F0x4:
1748 case Iop_Add32F0x4:
1749 return binary32F0x4(mce, vatom1, vatom2);
1750
sewardjf0c1c582005-02-07 23:47:38 +00001751 /* V128-bit data-steering */
1752 case Iop_SetV128lo32:
1753 case Iop_SetV128lo64:
1754 case Iop_64HLtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001755 case Iop_InterleaveLO64x2:
1756 case Iop_InterleaveLO32x4:
1757 case Iop_InterleaveLO16x8:
1758 case Iop_InterleaveLO8x16:
1759 case Iop_InterleaveHI64x2:
1760 case Iop_InterleaveHI32x4:
1761 case Iop_InterleaveHI16x8:
1762 case Iop_InterleaveHI8x16:
1763 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1764
1765 /* Scalar floating point */
1766
sewardj478646f2008-05-01 20:13:04 +00001767 // case Iop_RoundF64:
sewardj1e3830f2011-03-14 11:27:26 +00001768 case Iop_F64toI64S:
1769 case Iop_I64StoF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001770 /* First arg is I32 (rounding mode), second is F64 or I64
1771 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001772 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1773
1774 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1775 /* Takes two F64 args. */
sewardj1e3830f2011-03-14 11:27:26 +00001776 case Iop_F64toI32S:
sewardj69f9e3e2004-12-30 02:05:34 +00001777 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001778 /* First arg is I32 (rounding mode), second is F64 (data). */
1779 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1780
sewardj1e3830f2011-03-14 11:27:26 +00001781 case Iop_F64toI16S:
sewardjde8a5ae2004-11-06 14:20:54 +00001782 /* First arg is I32 (rounding mode), second is F64 (data). */
1783 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1784
sewardj3598ef92004-11-11 02:13:30 +00001785 case Iop_ScaleF64:
1786 case Iop_Yl2xF64:
1787 case Iop_Yl2xp1F64:
1788 case Iop_PRemF64:
1789 case Iop_AtanF64:
1790 case Iop_AddF64:
1791 case Iop_DivF64:
1792 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001793 case Iop_MulF64:
1794 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1795
sewardj3598ef92004-11-11 02:13:30 +00001796 case Iop_CmpF64:
1797 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1798
sewardjde8a5ae2004-11-06 14:20:54 +00001799 /* non-FP after here */
1800
1801 case Iop_DivModU64to32:
1802 case Iop_DivModS64to32:
1803 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1804
sewardj3598ef92004-11-11 02:13:30 +00001805 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001806 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001807 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001808 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001809
1810 case Iop_MullS32:
1811 case Iop_MullU32: {
1812 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1813 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1814 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1815 }
1816
sewardj3598ef92004-11-11 02:13:30 +00001817 case Iop_MullS16:
1818 case Iop_MullU16: {
1819 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1820 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1821 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1822 }
1823
1824 case Iop_MullS8:
1825 case Iop_MullU8: {
1826 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1827 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1828 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1829 }
1830
sewardjde8a5ae2004-11-06 14:20:54 +00001831 case Iop_Add32:
1832# if 0
1833 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1834# endif
1835 case Iop_Sub32:
1836 case Iop_Mul32:
1837 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1838
sewardj3598ef92004-11-11 02:13:30 +00001839 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001840 case Iop_Add16:
1841 case Iop_Sub16:
1842 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1843
1844 case Iop_Sub8:
1845 case Iop_Add8:
1846 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1847
1848 case Iop_CmpLE32S: case Iop_CmpLE32U:
1849 case Iop_CmpLT32U: case Iop_CmpLT32S:
1850 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001851 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001852
sewardj3598ef92004-11-11 02:13:30 +00001853 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001854 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001855
1856 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001857 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001858
1859 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1860 /* Complain if the shift amount is undefined. Then simply
1861 shift the first arg's V bits by the real shift amount. */
1862 complainIfUndefined(mce, atom2);
1863 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1864
sewardj69f9e3e2004-12-30 02:05:34 +00001865 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001866 /* Same scheme as with 32-bit shifts. */
1867 complainIfUndefined(mce, atom2);
1868 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1869
sewardj3598ef92004-11-11 02:13:30 +00001870 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001871 /* Same scheme as with 32-bit shifts. */
1872 complainIfUndefined(mce, atom2);
1873 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1874
1875 case Iop_Shl64: case Iop_Shr64:
1876 /* Same scheme as with 32-bit shifts. */
1877 complainIfUndefined(mce, atom2);
1878 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1879
sewardjf0c1c582005-02-07 23:47:38 +00001880 case Iop_AndV128:
1881 uifu = mkUifUV128; difd = mkDifDV128;
1882 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001883 case Iop_And64:
1884 uifu = mkUifU64; difd = mkDifD64;
1885 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001886 case Iop_And32:
1887 uifu = mkUifU32; difd = mkDifD32;
1888 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001889 case Iop_And16:
1890 uifu = mkUifU16; difd = mkDifD16;
1891 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001892 case Iop_And8:
1893 uifu = mkUifU8; difd = mkDifD8;
1894 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1895
sewardjf0c1c582005-02-07 23:47:38 +00001896 case Iop_OrV128:
1897 uifu = mkUifUV128; difd = mkDifDV128;
1898 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001899 case Iop_Or64:
1900 uifu = mkUifU64; difd = mkDifD64;
1901 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001902 case Iop_Or32:
1903 uifu = mkUifU32; difd = mkDifD32;
1904 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1905 case Iop_Or16:
1906 uifu = mkUifU16; difd = mkDifD16;
1907 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1908 case Iop_Or8:
1909 uifu = mkUifU8; difd = mkDifD8;
1910 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1911
1912 do_And_Or:
1913 return
1914 assignNew(
1915 mce,
1916 and_or_ty,
1917 difd(mce, uifu(mce, vatom1, vatom2),
1918 difd(mce, improve(mce, atom1, vatom1),
1919 improve(mce, atom2, vatom2) ) ) );
1920
1921 case Iop_Xor8:
1922 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001923 case Iop_Xor16:
1924 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001925 case Iop_Xor32:
1926 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001927 case Iop_Xor64:
1928 return mkUifU64(mce, vatom1, vatom2);
sewardjf0c1c582005-02-07 23:47:38 +00001929 case Iop_XorV128:
1930 return mkUifUV128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001931
1932 default:
1933 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001934 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001935 }
1936}
1937
1938
1939static
1940IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1941{
1942 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001943 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001944 switch (op) {
1945
sewardj69f9e3e2004-12-30 02:05:34 +00001946 case Iop_Sqrt64Fx2:
1947 return unary64Fx2(mce, vatom);
1948
1949 case Iop_Sqrt64F0x2:
1950 return unary64F0x2(mce, vatom);
1951
1952 case Iop_Sqrt32Fx4:
1953 case Iop_RSqrt32Fx4:
1954 case Iop_Recip32Fx4:
1955 return unary32Fx4(mce, vatom);
1956
1957 case Iop_Sqrt32F0x4:
1958 case Iop_RSqrt32F0x4:
1959 case Iop_Recip32F0x4:
1960 return unary32F0x4(mce, vatom);
1961
sewardjf0c1c582005-02-07 23:47:38 +00001962 case Iop_32UtoV128:
1963 case Iop_64UtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001964 return assignNew(mce, Ity_V128, unop(op, vatom));
1965
sewardjde8a5ae2004-11-06 14:20:54 +00001966 case Iop_F32toF64:
sewardj1e3830f2011-03-14 11:27:26 +00001967 case Iop_I32StoF64:
sewardj3598ef92004-11-11 02:13:30 +00001968 case Iop_NegF64:
1969 case Iop_SinF64:
1970 case Iop_CosF64:
1971 case Iop_TanF64:
1972 case Iop_SqrtF64:
1973 case Iop_AbsF64:
1974 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001975 return mkPCastTo(mce, Ity_I64, vatom);
1976
sewardj3598ef92004-11-11 02:13:30 +00001977 case Iop_Clz32:
1978 case Iop_Ctz32:
1979 return mkPCastTo(mce, Ity_I32, vatom);
1980
1981 case Iop_32Sto64:
1982 case Iop_32Uto64:
sewardjf0c1c582005-02-07 23:47:38 +00001983 case Iop_V128to64:
1984 case Iop_V128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001985 return assignNew(mce, Ity_I64, unop(op, vatom));
1986
sewardjde8a5ae2004-11-06 14:20:54 +00001987 case Iop_64to32:
1988 case Iop_64HIto32:
1989 case Iop_1Uto32:
1990 case Iop_8Uto32:
1991 case Iop_16Uto32:
1992 case Iop_16Sto32:
1993 case Iop_8Sto32:
1994 return assignNew(mce, Ity_I32, unop(op, vatom));
1995
1996 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001997 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001998 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001999 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00002000 return assignNew(mce, Ity_I16, unop(op, vatom));
2001
2002 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00002003 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00002004 case Iop_32to8:
2005 return assignNew(mce, Ity_I8, unop(op, vatom));
2006
2007 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00002008 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00002009
sewardj3598ef92004-11-11 02:13:30 +00002010 case Iop_ReinterpF64asI64:
2011 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00002012 case Iop_ReinterpI32asF32:
sewardjf0c1c582005-02-07 23:47:38 +00002013 case Iop_NotV128:
sewardj69f9e3e2004-12-30 02:05:34 +00002014 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00002015 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00002016 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00002017 case Iop_Not8:
2018 case Iop_Not1:
2019 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00002020
sewardjde8a5ae2004-11-06 14:20:54 +00002021 default:
2022 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00002023 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00002024 }
2025}
2026
2027
sewardj69f9e3e2004-12-30 02:05:34 +00002028/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00002029static
sewardj69f9e3e2004-12-30 02:05:34 +00002030IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00002031{
2032 void* helper;
sewardjde8c9872005-03-25 13:48:55 +00002033 HChar* hname;
sewardjde8a5ae2004-11-06 14:20:54 +00002034 IRDirty* di;
2035 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00002036 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00002037
sewardj69f9e3e2004-12-30 02:05:34 +00002038 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00002039
2040 /* First, emit a definedness test for the address. This also sets
2041 the address (shadow) to 'defined' following the test. */
2042 complainIfUndefined( mce, addr );
2043
2044 /* Now cook up a call to the relevant helper function, to read the
2045 data V bits from shadow memory. */
2046 ty = shadowType(ty);
2047 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00002048 case Ity_I64: helper = &MC_(helperc_LOADV8);
2049 hname = "MC_(helperc_LOADV8)";
2050 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002051 case Ity_I32: helper = &MC_(helperc_LOADV4);
2052 hname = "MC_(helperc_LOADV4)";
2053 break;
2054 case Ity_I16: helper = &MC_(helperc_LOADV2);
2055 hname = "MC_(helperc_LOADV2)";
2056 break;
2057 case Ity_I8: helper = &MC_(helperc_LOADV1);
2058 hname = "MC_(helperc_LOADV1)";
2059 break;
2060 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00002061 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00002062 }
2063
sewardj3598ef92004-11-11 02:13:30 +00002064 /* Generate the actual address into addrAct. */
2065 if (bias == 0) {
2066 addrAct = addr;
2067 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002068 IROp mkAdd;
2069 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00002070 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00002071 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2072 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2073 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00002074 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2075 }
2076
sewardjde8a5ae2004-11-06 14:20:54 +00002077 /* We need to have a place to park the V bits we're just about to
2078 read. */
2079 datavbits = newIRTemp(mce->bb->tyenv, ty);
2080 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00002081 1/*regparms*/, hname, helper,
2082 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00002083 setHelperAnns( mce, di );
2084 stmt( mce->bb, IRStmt_Dirty(di) );
2085
2086 return mkexpr(datavbits);
2087}
2088
2089
2090static
sewardj69f9e3e2004-12-30 02:05:34 +00002091IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
2092{
2093 IRAtom *v64hi, *v64lo;
2094 switch (shadowType(ty)) {
2095 case Ity_I8:
2096 case Ity_I16:
2097 case Ity_I32:
2098 case Ity_I64:
2099 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
2100 case Ity_V128:
2101 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
2102 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
2103 return assignNew( mce,
2104 Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +00002105 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj69f9e3e2004-12-30 02:05:34 +00002106 default:
2107 VG_(tool_panic)("expr2vbits_LDle");
2108 }
2109}
2110
2111
2112static
florian99dd03e2013-01-29 03:56:06 +00002113IRAtom* expr2vbits_ITE ( MCEnv* mce,
2114 IRAtom* cond, IRAtom* iftrue, IRAtom* iffalse )
sewardjde8a5ae2004-11-06 14:20:54 +00002115{
florian99dd03e2013-01-29 03:56:06 +00002116 IRAtom *vbitsC, *vbits0, *vbits1;
sewardjde8a5ae2004-11-06 14:20:54 +00002117 IRType ty;
florian99dd03e2013-01-29 03:56:06 +00002118 /* Given ITE(cond,iftrue,iffalse), generate
2119 ITE(cond,iftrue#,iffalse#) `UifU` PCast(cond#)
sewardjde8a5ae2004-11-06 14:20:54 +00002120 That is, steer the V bits like the originals, but trash the
2121 result if the steering value is undefined. This gives
2122 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00002123 tl_assert(isOriginalAtom(mce, cond));
florian99dd03e2013-01-29 03:56:06 +00002124 tl_assert(isOriginalAtom(mce, iftrue));
2125 tl_assert(isOriginalAtom(mce, iffalse));
sewardjde8a5ae2004-11-06 14:20:54 +00002126
2127 vbitsC = expr2vbits(mce, cond);
florian99dd03e2013-01-29 03:56:06 +00002128 vbits0 = expr2vbits(mce, iffalse);
2129 vbits1 = expr2vbits(mce, iftrue);
sewardjde8a5ae2004-11-06 14:20:54 +00002130 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2131
2132 return
florian99dd03e2013-01-29 03:56:06 +00002133 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_ITE(cond, vbits1, vbits0)),
sewardjde8a5ae2004-11-06 14:20:54 +00002134 mkPCastTo(mce, ty, vbitsC) );
2135}
2136
2137/* --------- This is the main expression-handling function. --------- */
2138
2139static
2140IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2141{
2142 switch (e->tag) {
2143
2144 case Iex_Get:
2145 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2146
2147 case Iex_GetI:
2148 return shadow_GETI( mce, e->Iex.GetI.descr,
2149 e->Iex.GetI.ix, e->Iex.GetI.bias );
2150
sewardj478646f2008-05-01 20:13:04 +00002151 case Iex_RdTmp:
2152 return IRExpr_RdTmp( findShadowTmp(mce, e->Iex.RdTmp.tmp) );
sewardjde8a5ae2004-11-06 14:20:54 +00002153
2154 case Iex_Const:
2155 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2156
2157 case Iex_Binop:
2158 return expr2vbits_Binop(
2159 mce,
2160 e->Iex.Binop.op,
2161 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2162 );
2163
2164 case Iex_Unop:
2165 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2166
sewardj478646f2008-05-01 20:13:04 +00002167 case Iex_Load:
2168 return expr2vbits_LDle( mce, e->Iex.Load.ty,
2169 e->Iex.Load.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002170
2171 case Iex_CCall:
2172 return mkLazyN( mce, e->Iex.CCall.args,
2173 e->Iex.CCall.retty,
2174 e->Iex.CCall.cee );
2175
florian99dd03e2013-01-29 03:56:06 +00002176 case Iex_ITE:
2177 return expr2vbits_ITE( mce, e->Iex.ITE.cond, e->Iex.ITE.iftrue,
2178 e->Iex.ITE.iffalse);
sewardjde8a5ae2004-11-06 14:20:54 +00002179
2180 default:
2181 VG_(printf)("\n");
2182 ppIRExpr(e);
2183 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002184 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002185 }
2186}
2187
2188/*------------------------------------------------------------*/
2189/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2190/*------------------------------------------------------------*/
2191
2192/* Widen a value to the host word size. */
2193
2194static
2195IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2196{
sewardj69f9e3e2004-12-30 02:05:34 +00002197 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002198
sewardj8fc93742004-11-22 11:29:33 +00002199 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002200 tl_assert(isShadowAtom(mce,vatom));
2201
2202 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2203 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002204
sewardjde8a5ae2004-11-06 14:20:54 +00002205 if (tyH == Ity_I32) {
2206 switch (ty) {
2207 case Ity_I32: return vatom;
2208 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2209 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2210 default: goto unhandled;
2211 }
2212 } else {
2213 goto unhandled;
2214 }
2215 unhandled:
2216 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002217 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002218}
2219
2220
sewardj3598ef92004-11-11 02:13:30 +00002221/* Generate a shadow store. addr is always the original address atom.
2222 You can pass in either originals or V-bits for the data atom, but
2223 obviously not both. */
2224
sewardjde8a5ae2004-11-06 14:20:54 +00002225static
sewardj3598ef92004-11-11 02:13:30 +00002226void do_shadow_STle ( MCEnv* mce,
2227 IRAtom* addr, UInt bias,
2228 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002229{
sewardj69f9e3e2004-12-30 02:05:34 +00002230 IROp mkAdd;
2231 IRType ty, tyAddr;
2232 IRDirty *di, *diLo64, *diHi64;
2233 IRAtom *addrAct, *addrLo64, *addrHi64;
2234 IRAtom *vdataLo64, *vdataHi64;
2235 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002236 void* helper = NULL;
sewardj478646f2008-05-01 20:13:04 +00002237 HChar* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002238
2239 tyAddr = mce->hWordTy;
2240 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2241 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2242
2243 di = diLo64 = diHi64 = NULL;
2244 eBias = eBias0 = eBias8 = NULL;
2245 addrAct = addrLo64 = addrHi64 = NULL;
2246 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002247
sewardj3598ef92004-11-11 02:13:30 +00002248 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002249 tl_assert(!vdata);
2250 tl_assert(isOriginalAtom(mce, data));
2251 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002252 vdata = expr2vbits( mce, data );
2253 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002254 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002255 }
sewardjde8a5ae2004-11-06 14:20:54 +00002256
sewardj69f9e3e2004-12-30 02:05:34 +00002257 tl_assert(isOriginalAtom(mce,addr));
2258 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002259
2260 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002261
2262 /* First, emit a definedness test for the address. This also sets
2263 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002264 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002265
sewardj69f9e3e2004-12-30 02:05:34 +00002266 /* Now decide which helper function to call to write the data V
2267 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002268 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002269 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002270 case Ity_I64: helper = &MC_(helperc_STOREV8);
2271 hname = "MC_(helperc_STOREV8)";
2272 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002273 case Ity_I32: helper = &MC_(helperc_STOREV4);
2274 hname = "MC_(helperc_STOREV4)";
2275 break;
2276 case Ity_I16: helper = &MC_(helperc_STOREV2);
2277 hname = "MC_(helperc_STOREV2)";
2278 break;
2279 case Ity_I8: helper = &MC_(helperc_STOREV1);
2280 hname = "MC_(helperc_STOREV1)";
2281 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002282 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002283 }
2284
sewardj69f9e3e2004-12-30 02:05:34 +00002285 if (ty == Ity_V128) {
2286
sewardjf0c1c582005-02-07 23:47:38 +00002287 /* V128-bit case */
sewardj69f9e3e2004-12-30 02:05:34 +00002288 /* See comment in next clause re 64-bit regparms */
2289 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2290 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
sewardjf0c1c582005-02-07 23:47:38 +00002291 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002292 diLo64 = unsafeIRDirty_0_N(
2293 1/*regparms*/, hname, helper,
2294 mkIRExprVec_2( addrLo64, vdataLo64 ));
2295
2296 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2297 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
sewardjf0c1c582005-02-07 23:47:38 +00002298 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002299 diHi64 = unsafeIRDirty_0_N(
2300 1/*regparms*/, hname, helper,
2301 mkIRExprVec_2( addrHi64, vdataHi64 ));
2302
2303 setHelperAnns( mce, diLo64 );
2304 setHelperAnns( mce, diHi64 );
2305 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2306 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2307
sewardj3598ef92004-11-11 02:13:30 +00002308 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002309
2310 /* 8/16/32/64-bit cases */
2311 /* Generate the actual address into addrAct. */
2312 if (bias == 0) {
2313 addrAct = addr;
2314 } else {
2315 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2316 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2317 }
2318
2319 if (ty == Ity_I64) {
2320 /* We can't do this with regparm 2 on 32-bit platforms, since
2321 the back ends aren't clever enough to handle 64-bit
2322 regparm args. Therefore be different. */
2323 di = unsafeIRDirty_0_N(
2324 1/*regparms*/, hname, helper,
2325 mkIRExprVec_2( addrAct, vdata ));
2326 } else {
2327 di = unsafeIRDirty_0_N(
2328 2/*regparms*/, hname, helper,
2329 mkIRExprVec_2( addrAct,
2330 zwidenToHostWord( mce, vdata )));
2331 }
2332 setHelperAnns( mce, di );
2333 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002334 }
2335
sewardjde8a5ae2004-11-06 14:20:54 +00002336}
2337
2338
sewardj3598ef92004-11-11 02:13:30 +00002339/* Do lazy pessimistic propagation through a dirty helper call, by
2340 looking at the annotations on it. This is the most complex part of
2341 Memcheck. */
2342
2343static IRType szToITy ( Int n )
2344{
2345 switch (n) {
2346 case 1: return Ity_I8;
2347 case 2: return Ity_I16;
2348 case 4: return Ity_I32;
2349 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002350 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002351 }
2352}
2353
2354static
2355void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2356{
sewardj69f9e3e2004-12-30 02:05:34 +00002357 Int i, n, offset, toDo, gSz, gOff;
2358 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002359 IRType tyAddr, tySrc, tyDst;
2360 IRTemp dst;
2361
2362 /* First check the guard. */
2363 complainIfUndefined(mce, d->guard);
2364
2365 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002366 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002367
2368 /* Inputs: unmasked args */
2369 for (i = 0; d->args[i]; i++) {
2370 if (d->cee->mcx_mask & (1<<i)) {
2371 /* ignore this arg */
2372 } else {
2373 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2374 curr = mkUifU32(mce, here, curr);
2375 }
2376 }
2377
2378 /* Inputs: guest state that we read. */
2379 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002380 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002381 if (d->fxState[i].fx == Ifx_Write)
2382 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002383
2384 /* Ignore any sections marked as 'always defined'. */
2385 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2386 if (0)
2387 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2388 d->fxState[i].offset, d->fxState[i].size );
2389 continue;
2390 }
2391
sewardj3598ef92004-11-11 02:13:30 +00002392 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002393 consider it. If larger than 8 bytes, deal with it in 8-byte
2394 chunks. */
2395 gSz = d->fxState[i].size;
2396 gOff = d->fxState[i].offset;
2397 tl_assert(gSz > 0);
2398 while (True) {
2399 if (gSz == 0) break;
2400 n = gSz <= 8 ? gSz : 8;
2401 /* update 'curr' with UifU of the state slice
2402 gOff .. gOff+n-1 */
2403 tySrc = szToITy( n );
2404 src = assignNew( mce, tySrc,
2405 shadow_GET(mce, gOff, tySrc ) );
2406 here = mkPCastTo( mce, Ity_I32, src );
2407 curr = mkUifU32(mce, here, curr);
2408 gSz -= n;
2409 gOff += n;
2410 }
2411
sewardj3598ef92004-11-11 02:13:30 +00002412 }
2413
2414 /* Inputs: memory. First set up some info needed regardless of
2415 whether we're doing reads or writes. */
2416 tyAddr = Ity_INVALID;
2417
2418 if (d->mFx != Ifx_None) {
2419 /* Because we may do multiple shadow loads/stores from the same
2420 base address, it's best to do a single test of its
2421 definedness right now. Post-instrumentation optimisation
2422 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002423 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002424 complainIfUndefined(mce, d->mAddr);
2425
2426 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002427 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2428 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002429 }
2430
2431 /* Deal with memory inputs (reads or modifies) */
2432 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2433 offset = 0;
2434 toDo = d->mSize;
2435 /* chew off 32-bit chunks */
2436 while (toDo >= 4) {
2437 here = mkPCastTo(
2438 mce, Ity_I32,
2439 expr2vbits_LDle ( mce, Ity_I32,
2440 d->mAddr, d->mSize - toDo )
2441 );
2442 curr = mkUifU32(mce, here, curr);
2443 toDo -= 4;
2444 }
2445 /* chew off 16-bit chunks */
2446 while (toDo >= 2) {
2447 here = mkPCastTo(
2448 mce, Ity_I32,
2449 expr2vbits_LDle ( mce, Ity_I16,
2450 d->mAddr, d->mSize - toDo )
2451 );
2452 curr = mkUifU32(mce, here, curr);
2453 toDo -= 2;
2454 }
sewardj69f9e3e2004-12-30 02:05:34 +00002455 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002456 }
2457
2458 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2459 all the inputs to the helper. Now we need to re-distribute the
2460 results to all destinations. */
2461
2462 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002463 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002464 dst = findShadowTmp(mce, d->tmp);
2465 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2466 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2467 }
2468
2469 /* Outputs: guest state that we write or modify. */
2470 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002471 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002472 if (d->fxState[i].fx == Ifx_Read)
2473 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002474 /* Ignore any sections marked as 'always defined'. */
2475 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2476 continue;
2477 /* This state element is written or modified. So we need to
2478 consider it. If larger than 8 bytes, deal with it in 8-byte
2479 chunks. */
2480 gSz = d->fxState[i].size;
2481 gOff = d->fxState[i].offset;
2482 tl_assert(gSz > 0);
2483 while (True) {
2484 if (gSz == 0) break;
2485 n = gSz <= 8 ? gSz : 8;
2486 /* Write suitably-casted 'curr' to the state slice
2487 gOff .. gOff+n-1 */
2488 tyDst = szToITy( n );
2489 do_shadow_PUT( mce, gOff,
2490 NULL, /* original atom */
2491 mkPCastTo( mce, tyDst, curr ) );
2492 gSz -= n;
2493 gOff += n;
2494 }
sewardj3598ef92004-11-11 02:13:30 +00002495 }
2496
2497 /* Outputs: memory that we write or modify. */
2498 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2499 offset = 0;
2500 toDo = d->mSize;
2501 /* chew off 32-bit chunks */
2502 while (toDo >= 4) {
2503 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2504 NULL, /* original data */
2505 mkPCastTo( mce, Ity_I32, curr ) );
2506 toDo -= 4;
2507 }
2508 /* chew off 16-bit chunks */
2509 while (toDo >= 2) {
2510 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2511 NULL, /* original data */
2512 mkPCastTo( mce, Ity_I16, curr ) );
2513 toDo -= 2;
2514 }
sewardj69f9e3e2004-12-30 02:05:34 +00002515 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002516 }
2517
2518}
2519
2520
sewardjde8a5ae2004-11-06 14:20:54 +00002521/*------------------------------------------------------------*/
2522/*--- Memcheck main ---*/
2523/*------------------------------------------------------------*/
2524
sewardj3598ef92004-11-11 02:13:30 +00002525static Bool isBogusAtom ( IRAtom* at )
2526{
2527 ULong n = 0;
2528 IRConst* con;
sewardj496a58d2005-03-20 18:44:44 +00002529 tl_assert(isIRAtom(at));
sewardj478646f2008-05-01 20:13:04 +00002530 if (at->tag == Iex_RdTmp)
sewardj3598ef92004-11-11 02:13:30 +00002531 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002532 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002533 con = at->Iex.Const.con;
2534 switch (con->tag) {
2535 case Ico_U8: n = (ULong)con->Ico.U8; break;
2536 case Ico_U16: n = (ULong)con->Ico.U16; break;
2537 case Ico_U32: n = (ULong)con->Ico.U32; break;
2538 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002539 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002540 }
2541 /* VG_(printf)("%llx\n", n); */
2542 return (n == 0xFEFEFEFF
2543 || n == 0x80808080
2544 || n == 0x1010101
2545 || n == 1010100);
2546}
2547
sewardj5f438dd2011-06-16 11:36:23 +00002548__attribute__((unused))
sewardj3598ef92004-11-11 02:13:30 +00002549static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2550{
2551 Int i;
2552 IRExpr* e;
2553 switch (st->tag) {
sewardj478646f2008-05-01 20:13:04 +00002554 case Ist_WrTmp:
2555 e = st->Ist.WrTmp.data;
sewardj3598ef92004-11-11 02:13:30 +00002556 switch (e->tag) {
2557 case Iex_Get:
sewardj478646f2008-05-01 20:13:04 +00002558 case Iex_RdTmp:
sewardj3598ef92004-11-11 02:13:30 +00002559 return False;
2560 case Iex_Unop:
2561 return isBogusAtom(e->Iex.Unop.arg);
2562 case Iex_Binop:
2563 return isBogusAtom(e->Iex.Binop.arg1)
2564 || isBogusAtom(e->Iex.Binop.arg2);
florian99dd03e2013-01-29 03:56:06 +00002565 case Iex_ITE:
2566 return isBogusAtom(e->Iex.ITE.cond)
2567 || isBogusAtom(e->Iex.ITE.iftrue)
2568 || isBogusAtom(e->Iex.ITE.iffalse);
sewardj478646f2008-05-01 20:13:04 +00002569 case Iex_Load:
2570 return isBogusAtom(e->Iex.Load.addr);
sewardj3598ef92004-11-11 02:13:30 +00002571 case Iex_CCall:
2572 for (i = 0; e->Iex.CCall.args[i]; i++)
2573 if (isBogusAtom(e->Iex.CCall.args[i]))
2574 return True;
2575 return False;
2576 default:
2577 goto unhandled;
2578 }
2579 case Ist_Put:
2580 return isBogusAtom(st->Ist.Put.data);
sewardj478646f2008-05-01 20:13:04 +00002581 case Ist_Store:
2582 return isBogusAtom(st->Ist.Store.addr)
2583 || isBogusAtom(st->Ist.Store.data);
sewardj3598ef92004-11-11 02:13:30 +00002584 case Ist_Exit:
sewardj1ea1b612005-03-26 13:02:20 +00002585 return isBogusAtom(st->Ist.Exit.guard);
sewardj3598ef92004-11-11 02:13:30 +00002586 default:
2587 unhandled:
2588 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002589 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002590 }
2591}
sewardj3598ef92004-11-11 02:13:30 +00002592
sewardj478646f2008-05-01 20:13:04 +00002593IRSB* mc_instrument ( void* closureV,
2594 IRSB* bb_in, VexGuestLayout* layout,
2595 VexGuestExtents* vge,
sewardj1ea1b612005-03-26 13:02:20 +00002596 IRType gWordTy, IRType hWordTy )
sewardjde8a5ae2004-11-06 14:20:54 +00002597{
sewardj3598ef92004-11-11 02:13:30 +00002598 Bool verboze = False; //True;
2599
2600 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002601
2602 Int i, j, first_stmt;
2603 IRStmt* st;
2604 MCEnv mce;
2605
2606 /* Set up BB */
sewardjf6c8ebf2007-02-06 01:52:52 +00002607 IRSB* bb = emptyIRSB();
sewardj478646f2008-05-01 20:13:04 +00002608 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
2609 bb->next = deepCopyIRExpr(bb_in->next);
sewardjde8a5ae2004-11-06 14:20:54 +00002610 bb->jumpkind = bb_in->jumpkind;
2611
2612 /* Set up the running environment. Only .bb is modified as we go
2613 along. */
2614 mce.bb = bb;
2615 mce.layout = layout;
2616 mce.n_originalTmps = bb->tyenv->types_used;
2617 mce.hWordTy = hWordTy;
2618 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2619 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002620 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002621
2622 /* Iterate over the stmts. */
2623
2624 for (i = 0; i < bb_in->stmts_used; i++) {
2625 st = bb_in->stmts[i];
2626 if (!st) continue;
2627
sewardj69f9e3e2004-12-30 02:05:34 +00002628 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002629
2630 /*
2631 if (!hasBogusLiterals) {
2632 hasBogusLiterals = checkForBogusLiterals(st);
2633 if (hasBogusLiterals) {
2634 VG_(printf)("bogus: ");
2635 ppIRStmt(st);
2636 VG_(printf)("\n");
2637 }
2638 }
2639 */
sewardjde8a5ae2004-11-06 14:20:54 +00002640 first_stmt = bb->stmts_used;
2641
2642 if (verboze) {
2643 ppIRStmt(st);
2644 VG_(printf)("\n\n");
2645 }
2646
2647 switch (st->tag) {
2648
sewardj478646f2008-05-01 20:13:04 +00002649 case Ist_WrTmp:
2650 assign( bb, findShadowTmp(&mce, st->Ist.WrTmp.tmp),
2651 expr2vbits( &mce, st->Ist.WrTmp.data) );
sewardjde8a5ae2004-11-06 14:20:54 +00002652 break;
2653
2654 case Ist_Put:
2655 do_shadow_PUT( &mce,
2656 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002657 st->Ist.Put.data,
2658 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002659 break;
2660
2661 case Ist_PutI:
2662 do_shadow_PUTI( &mce,
florian4180af32012-12-24 00:25:34 +00002663 st->Ist.PutI.details->descr,
2664 st->Ist.PutI.details->ix,
2665 st->Ist.PutI.details->bias,
2666 st->Ist.PutI.details->data );
sewardjde8a5ae2004-11-06 14:20:54 +00002667 break;
2668
sewardj478646f2008-05-01 20:13:04 +00002669 case Ist_Store:
2670 do_shadow_STle( &mce, st->Ist.Store.addr, 0/* addr bias */,
2671 st->Ist.Store.data,
sewardj3598ef92004-11-11 02:13:30 +00002672 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002673 break;
2674
2675 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002676 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002677 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002678 break;
2679
2680 case Ist_Dirty:
2681 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002682 break;
2683
sewardj1ea1b612005-03-26 13:02:20 +00002684 case Ist_IMark:
2685 case Ist_NoOp:
2686 break;
2687
sewardjde8a5ae2004-11-06 14:20:54 +00002688 default:
2689 VG_(printf)("\n");
2690 ppIRStmt(st);
2691 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002692 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002693
2694 } /* switch (st->tag) */
2695
2696 if (verboze) {
2697 for (j = first_stmt; j < bb->stmts_used; j++) {
2698 VG_(printf)(" ");
2699 ppIRStmt(bb->stmts[j]);
2700 VG_(printf)("\n");
2701 }
2702 VG_(printf)("\n");
2703 }
2704
sewardjf6c8ebf2007-02-06 01:52:52 +00002705 addStmtToIRSB(bb, st);
sewardjde8a5ae2004-11-06 14:20:54 +00002706
2707 }
2708
2709 /* Now we need to complain if the jump target is undefined. */
2710 first_stmt = bb->stmts_used;
2711
2712 if (verboze) {
2713 VG_(printf)("bb->next = ");
2714 ppIRExpr(bb->next);
2715 VG_(printf)("\n\n");
2716 }
2717
2718 complainIfUndefined( &mce, bb->next );
2719
2720 if (verboze) {
2721 for (j = first_stmt; j < bb->stmts_used; j++) {
2722 VG_(printf)(" ");
2723 ppIRStmt(bb->stmts[j]);
2724 VG_(printf)("\n");
2725 }
2726 VG_(printf)("\n");
2727 }
2728
2729 return bb;
2730}
cerionaee45242005-03-17 14:03:36 +00002731#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002732
2733/*--------------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00002734/*--- end test_main.c ---*/
sewardjde8a5ae2004-11-06 14:20:54 +00002735/*--------------------------------------------------------------------*/