blob: 4c7248ba8955ebefe955af5b1e2380afda4b70ac [file] [log] [blame]
sewardjc97096c2004-06-30 09:28:04 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
4/*--- This file (test_main.c) is ---*/
sewardjdbcfae72005-08-02 11:14:04 +00005/*--- Copyright (C) 2005 OpenWorks LLP. All rights reserved. ---*/
sewardjc97096c2004-06-30 09:28:04 +00006/*--- ---*/
7/*---------------------------------------------------------------*/
8
9#include <stdio.h>
10#include <stdlib.h>
sewardjced9fe52004-07-07 11:55:36 +000011#include <assert.h>
sewardj9b1004e2004-10-30 22:25:40 +000012#include <string.h>
sewardjc97096c2004-06-30 09:28:04 +000013
sewardjced9fe52004-07-07 11:55:36 +000014#include "libvex_basictypes.h"
15#include "libvex.h"
sewardjc97096c2004-06-30 09:28:04 +000016
sewardjabe017e2004-10-29 23:42:36 +000017#include "test_main.h"
18
19
sewardjc97096c2004-06-30 09:28:04 +000020/*---------------------------------------------------------------*/
21/*--- Test ---*/
22/*---------------------------------------------------------------*/
23
sewardjce605f92004-07-05 14:39:15 +000024
sewardj2b515872004-07-05 20:50:45 +000025__attribute__ ((noreturn))
sewardj41f43bc2004-07-08 14:23:22 +000026static
sewardjce605f92004-07-05 14:39:15 +000027void failure_exit ( void )
28{
29 fprintf(stdout, "VEX did failure_exit. Bye.\n");
30 exit(1);
31}
32
sewardj41f43bc2004-07-08 14:23:22 +000033static
sewardj58277842005-02-07 03:11:17 +000034void log_bytes ( HChar* bytes, Int nbytes )
sewardjce605f92004-07-05 14:39:15 +000035{
36 fwrite ( bytes, 1, nbytes, stdout );
37}
38
sewardjced9fe52004-07-07 11:55:36 +000039#define N_LINEBUF 10000
sewardjde8c9872005-03-25 13:48:55 +000040static HChar linebuf[N_LINEBUF];
sewardjced9fe52004-07-07 11:55:36 +000041
cerion094d1392005-06-20 13:45:57 +000042#define N_ORIGBUF 10000
sewardj4459baa2004-09-10 20:00:46 +000043#define N_TRANSBUF 5000
sewardjced9fe52004-07-07 11:55:36 +000044
sewardj4459baa2004-09-10 20:00:46 +000045static UChar origbuf[N_ORIGBUF];
46static UChar transbuf[N_TRANSBUF];
sewardjced9fe52004-07-07 11:55:36 +000047
sewardj1f40a0a2004-07-21 12:28:07 +000048static Bool verbose = True;
sewardjced9fe52004-07-07 11:55:36 +000049
sewardj9b1004e2004-10-30 22:25:40 +000050/* Forwards */
cerionaee45242005-03-17 14:03:36 +000051#if 0 /* UNUSED */
sewardj9578a8b2004-11-04 19:44:48 +000052static IRBB* ac_instrument ( IRBB*, VexGuestLayout*, IRType );
sewardj1ea1b612005-03-26 13:02:20 +000053static IRBB* mc_instrument ( IRBB*, VexGuestLayout*, IRType, IRType );
cerionaee45242005-03-17 14:03:36 +000054#endif
sewardj9b1004e2004-10-30 22:25:40 +000055
sewardjc716aea2006-01-17 01:48:46 +000056static Bool chase_into_not_ok ( void* opaque, Addr64 dst ) { return False; }
sewardj9b1004e2004-10-30 22:25:40 +000057
sewardjced9fe52004-07-07 11:55:36 +000058int main ( int argc, char** argv )
sewardjce605f92004-07-05 14:39:15 +000059{
sewardjced9fe52004-07-07 11:55:36 +000060 FILE* f;
61 Int i;
sewardj4459baa2004-09-10 20:00:46 +000062 UInt u, sum;
sewardjced9fe52004-07-07 11:55:36 +000063 Addr32 orig_addr;
sewardjabe017e2004-10-29 23:42:36 +000064 Int bb_number, n_bbs_done = 0;
sewardj72c72812005-01-19 11:49:45 +000065 Int orig_nbytes, trans_used;
sewardjd887b862005-01-17 18:34:34 +000066 VexTranslateResult tres;
sewardjb5bf2e02004-10-25 13:06:17 +000067 VexControl vcon;
sewardj72c72812005-01-19 11:49:45 +000068 VexGuestExtents vge;
sewardj9e6491a2005-07-02 19:24:10 +000069 VexArchInfo vai_x86, vai_amd64, vai_ppc32;
sewardjdd40fdf2006-12-24 02:20:24 +000070 VexAbiInfo vbi;
sewardj17c7f952005-12-15 14:02:34 +000071 VexTranslateArgs vta;
sewardjced9fe52004-07-07 11:55:36 +000072
73 if (argc != 2) {
74 fprintf(stderr, "usage: vex file.org\n");
75 exit(1);
76 }
77 f = fopen(argv[1], "r");
78 if (!f) {
79 fprintf(stderr, "can't open `%s'\n", argv[1]);
80 exit(1);
81 }
82
sewardjb5bf2e02004-10-25 13:06:17 +000083 /* Run with default params. However, we can't allow bb chasing
84 since that causes the front end to get segfaults when it tries
sewardj5bd4d162004-11-10 13:02:48 +000085 to read code outside the initial BB we hand it. So when calling
86 LibVEX_Translate, send in a chase-into predicate that always
87 returns False. */
sewardjb5bf2e02004-10-25 13:06:17 +000088 LibVEX_default_VexControl ( &vcon );
sewardjb4952402004-10-26 13:24:50 +000089 vcon.iropt_level = 2;
sewardjc279b3f2005-03-16 18:10:45 +000090 vcon.guest_max_insns = 50;
sewardjb5bf2e02004-10-25 13:06:17 +000091
sewardjced9fe52004-07-07 11:55:36 +000092 LibVEX_Init ( &failure_exit, &log_bytes,
sewardj1f40a0a2004-07-21 12:28:07 +000093 1, /* debug_paranoia */
sewardjabe017e2004-10-29 23:42:36 +000094 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +000095 &vcon );
sewardjced9fe52004-07-07 11:55:36 +000096
sewardjea64e142004-07-22 16:47:21 +000097
sewardjced9fe52004-07-07 11:55:36 +000098 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +000099
sewardjced9fe52004-07-07 11:55:36 +0000100 fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +0000101 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +0000102 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +0000103
104 if (n_bbs_done == TEST_N_BBS) break;
105 n_bbs_done++;
106
sewardjced9fe52004-07-07 11:55:36 +0000107 /* first line is: . bb-number bb-addr n-bytes */
108 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
109 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000110 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000111 assert(orig_nbytes >= 1);
112 assert(!feof(f));
113 fgets(linebuf, N_LINEBUF,f);
114 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000115
sewardjced9fe52004-07-07 11:55:36 +0000116 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000117 if (verbose)
sewardj07a54cc2005-02-04 21:18:55 +0000118 printf("============ Basic Block %d, Done %d, "
sewardj4459baa2004-09-10 20:00:46 +0000119 "Start %x, nbytes %2d ============",
sewardj07a54cc2005-02-04 21:18:55 +0000120 bb_number, n_bbs_done-1, orig_addr, orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000121
sewardjced9fe52004-07-07 11:55:36 +0000122 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
123 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000124 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
125 origbuf[i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000126 }
127
sewardj5117ce12006-01-27 21:20:15 +0000128 /* FIXME: put sensible values into the .hwcaps fields */
sewardj9e6491a2005-07-02 19:24:10 +0000129 LibVEX_default_VexArchInfo(&vai_x86);
sewardj5117ce12006-01-27 21:20:15 +0000130 vai_x86.hwcaps = 0;
sewardj9e6491a2005-07-02 19:24:10 +0000131
132 LibVEX_default_VexArchInfo(&vai_amd64);
sewardj5117ce12006-01-27 21:20:15 +0000133 vai_amd64.hwcaps = 0;
sewardj9e6491a2005-07-02 19:24:10 +0000134
135 LibVEX_default_VexArchInfo(&vai_ppc32);
sewardj5117ce12006-01-27 21:20:15 +0000136 vai_ppc32.hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000137 vai_ppc32.ppc_cache_line_szB = 128;
sewardj02ef7162005-06-30 12:50:50 +0000138
sewardjdd40fdf2006-12-24 02:20:24 +0000139 LibVEX_default_VexAbiInfo(&vbi);
sewardjaca070a2006-10-17 00:28:22 +0000140
sewardj17c7f952005-12-15 14:02:34 +0000141 /* ----- Set up args for LibVEX_Translate ----- */
sewardj9e6491a2005-07-02 19:24:10 +0000142#if 1 /* ppc32 -> ppc32 */
sewardj17c7f952005-12-15 14:02:34 +0000143 vta.arch_guest = VexArchPPC32;
144 vta.archinfo_guest = vai_ppc32;
145 vta.arch_host = VexArchPPC32;
146 vta.archinfo_host = vai_ppc32;
sewardj07a54cc2005-02-04 21:18:55 +0000147#endif
sewardjc279b3f2005-03-16 18:10:45 +0000148#if 0 /* amd64 -> amd64 */
sewardj17c7f952005-12-15 14:02:34 +0000149 vta.arch_guest = VexArchAMD64;
150 vta.archinfo_guest = vai_amd64;
151 vta.arch_host = VexArchAMD64;
152 vta.archinfo_host = vai_amd64;
sewardj07a54cc2005-02-04 21:18:55 +0000153#endif
sewardj9e6491a2005-07-02 19:24:10 +0000154#if 0 /* x86 -> x86 */
sewardj17c7f952005-12-15 14:02:34 +0000155 vta.arch_guest = VexArchX86;
156 vta.archinfo_guest = vai_x86;
157 vta.arch_host = VexArchX86;
158 vta.archinfo_host = vai_x86;
sewardjc279b3f2005-03-16 18:10:45 +0000159#endif
sewardjdd40fdf2006-12-24 02:20:24 +0000160 vta.abiinfo_both = vbi;
sewardj17c7f952005-12-15 14:02:34 +0000161 vta.guest_bytes = origbuf;
162 vta.guest_bytes_addr = (Addr64)orig_addr;
sewardjc716aea2006-01-17 01:48:46 +0000163 vta.callback_opaque = NULL;
sewardj17c7f952005-12-15 14:02:34 +0000164 vta.chase_into_ok = chase_into_not_ok;
165 vta.guest_extents = &vge;
166 vta.host_bytes = transbuf;
167 vta.host_bytes_size = N_TRANSBUF;
168 vta.host_bytes_used = &trans_used;
sewardj9e7448b2004-11-18 13:44:15 +0000169#if 1 /* no instrumentation */
sewardj17c7f952005-12-15 14:02:34 +0000170 vta.instrument1 = NULL;
171 vta.instrument2 = NULL;
sewardj9e7448b2004-11-18 13:44:15 +0000172#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000173#if 0 /* addrcheck */
sewardj17c7f952005-12-15 14:02:34 +0000174 vta.instrument1 = ac_instrument;
175 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000176#endif
sewardj9e7448b2004-11-18 13:44:15 +0000177#if 0 /* memcheck */
sewardj17c7f952005-12-15 14:02:34 +0000178 vta.instrument1 = mc_instrument;
179 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000180#endif
sewardj17c7f952005-12-15 14:02:34 +0000181 vta.do_self_check = False;
sewardjc716aea2006-01-17 01:48:46 +0000182 vta.preamble_function = NULL;
sewardj17c7f952005-12-15 14:02:34 +0000183 vta.traceflags = TEST_FLAGS;
184#if 1 /* x86, amd64 hosts */
185 vta.dispatch = (void*)0x12345678;
186#else /* ppc32, ppc64 hosts */
187 vta.dispatch = NULL;
188#endif
189
190 for (i = 0; i < TEST_N_ITERS; i++)
191 tres = LibVEX_Translate ( &vta );
sewardjabe017e2004-10-29 23:42:36 +0000192
sewardjd887b862005-01-17 18:34:34 +0000193 if (tres != VexTransOK)
sewardj4459baa2004-09-10 20:00:46 +0000194 printf("\ntres = %d\n", (Int)tres);
sewardjd887b862005-01-17 18:34:34 +0000195 assert(tres == VexTransOK);
sewardj72c72812005-01-19 11:49:45 +0000196 assert(vge.n_used == 1);
197 assert((UInt)(vge.len[0]) == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000198
sewardj4459baa2004-09-10 20:00:46 +0000199 sum = 0;
200 for (i = 0; i < trans_used; i++)
201 sum += (UInt)transbuf[i];
sewardjde8c9872005-03-25 13:48:55 +0000202 printf ( " %6.2f ... %u\n",
203 (double)trans_used / (double)vge.len[0], sum );
sewardjced9fe52004-07-07 11:55:36 +0000204 }
205
206 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000207 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000208 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000209
sewardjce605f92004-07-05 14:39:15 +0000210 return 0;
211}
sewardj9b1004e2004-10-30 22:25:40 +0000212
213//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000214//////////////////////////////////////////////////////////////////////
215//////////////////////////////////////////////////////////////////////
216//////////////////////////////////////////////////////////////////////
217//////////////////////////////////////////////////////////////////////
218//////////////////////////////////////////////////////////////////////
219//////////////////////////////////////////////////////////////////////
220//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000221
sewardj1ea1b612005-03-26 13:02:20 +0000222#if 0 /* UNUSED */
223
sewardj9b1004e2004-10-30 22:25:40 +0000224static
sewardjde8a5ae2004-11-06 14:20:54 +0000225__attribute((noreturn))
sewardjde8c9872005-03-25 13:48:55 +0000226void panic ( HChar* s )
sewardj9b1004e2004-10-30 22:25:40 +0000227{
228 printf("\npanic: %s\n", s);
229 failure_exit();
230}
231
232static
sewardj9578a8b2004-11-04 19:44:48 +0000233IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000234{
235/* Use this rather than eg. -1 because it's a UInt. */
236#define INVALID_DATA_SIZE 999999
237
238 Int i;
239 Int sz;
240 IRCallee* helper;
241 IRStmt* st;
242 IRExpr* data;
243 IRExpr* addr;
244 Bool needSz;
245
246 /* Set up BB */
247 IRBB* bb = emptyIRBB();
248 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
249 bb->next = dopyIRExpr(bb_in->next);
250 bb->jumpkind = bb_in->jumpkind;
251
252 /* No loads to consider in ->next. */
sewardj496a58d2005-03-20 18:44:44 +0000253 assert(isIRAtom(bb_in->next));
sewardj9b1004e2004-10-30 22:25:40 +0000254
255 for (i = 0; i < bb_in->stmts_used; i++) {
256 st = bb_in->stmts[i];
257 if (!st) continue;
258
259 switch (st->tag) {
260
261 case Ist_Tmp:
262 data = st->Ist.Tmp.data;
263 if (data->tag == Iex_LDle) {
264 addr = data->Iex.LDle.addr;
265 sz = sizeofIRType(data->Iex.LDle.ty);
266 needSz = False;
267 switch (sz) {
268 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000269 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000270 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000271 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000272 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000273 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000274 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000275 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000276 needSz = True; break;
277 }
278 if (needSz) {
279 addStmtToIRBB(
280 bb,
281 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000282 unsafeIRDirty_0_N( helper->regparms,
283 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000284 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
285 ));
286 } else {
287 addStmtToIRBB(
288 bb,
289 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000290 unsafeIRDirty_0_N( helper->regparms,
291 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000292 mkIRExprVec_1(addr) )
293 ));
294 }
295 }
296 break;
297
298 case Ist_STle:
299 data = st->Ist.STle.data;
300 addr = st->Ist.STle.addr;
sewardj496a58d2005-03-20 18:44:44 +0000301 assert(isIRAtom(data));
302 assert(isIRAtom(addr));
sewardj9b1004e2004-10-30 22:25:40 +0000303 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
304 needSz = False;
305 switch (sz) {
306 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000307 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000308 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000309 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000310 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000311 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000312 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000313 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000314 needSz = True; break;
315 }
316 if (needSz) {
317 addStmtToIRBB(
318 bb,
319 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000320 unsafeIRDirty_0_N( helper->regparms,
321 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000322 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
323 ));
324 } else {
325 addStmtToIRBB(
326 bb,
327 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000328 unsafeIRDirty_0_N( helper->regparms,
329 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000330 mkIRExprVec_1(addr) )
331 ));
332 }
333 break;
334
335 case Ist_Put:
sewardj496a58d2005-03-20 18:44:44 +0000336 assert(isIRAtom(st->Ist.Put.data));
sewardj9b1004e2004-10-30 22:25:40 +0000337 break;
338
339 case Ist_PutI:
sewardj496a58d2005-03-20 18:44:44 +0000340 assert(isIRAtom(st->Ist.PutI.ix));
341 assert(isIRAtom(st->Ist.PutI.data));
sewardj9b1004e2004-10-30 22:25:40 +0000342 break;
343
344 case Ist_Exit:
sewardj496a58d2005-03-20 18:44:44 +0000345 assert(isIRAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000346 break;
347
348 case Ist_Dirty:
349 /* If the call doesn't interact with memory, we ain't
350 interested. */
351 if (st->Ist.Dirty.details->mFx == Ifx_None)
352 break;
353 goto unhandled;
354
355 default:
356 unhandled:
357 printf("\n");
358 ppIRStmt(st);
359 printf("\n");
360 panic("addrcheck: unhandled IRStmt");
361 }
362
363 addStmtToIRBB( bb, dopyIRStmt(st));
364 }
365
366 return bb;
367}
cerionaee45242005-03-17 14:03:36 +0000368#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +0000369
370//////////////////////////////////////////////////////////////////////
371//////////////////////////////////////////////////////////////////////
372//////////////////////////////////////////////////////////////////////
373//////////////////////////////////////////////////////////////////////
374//////////////////////////////////////////////////////////////////////
375//////////////////////////////////////////////////////////////////////
376//////////////////////////////////////////////////////////////////////
377//////////////////////////////////////////////////////////////////////
378
sewardj1ea1b612005-03-26 13:02:20 +0000379#if 0 /* UNUSED */
380
sewardj69f9e3e2004-12-30 02:05:34 +0000381#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000382#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000383#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000384#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000385#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000386
cerionaee45242005-03-17 14:03:36 +0000387
sewardjde8c9872005-03-25 13:48:55 +0000388static void MC_helperc_complain_undef ( void );
389static void MC_helperc_LOADV8 ( void );
390static void MC_helperc_LOADV4 ( void );
391static void MC_helperc_LOADV2 ( void );
392static void MC_helperc_LOADV1 ( void );
sewardj1ea1b612005-03-26 13:02:20 +0000393static void MC_helperc_STOREV8( void );
394static void MC_helperc_STOREV4( void );
395static void MC_helperc_STOREV2( void );
396static void MC_helperc_STOREV1( void );
sewardjde8c9872005-03-25 13:48:55 +0000397static void MC_helperc_value_check0_fail( void );
398static void MC_helperc_value_check1_fail( void );
399static void MC_helperc_value_check4_fail( void );
400
401static void MC_helperc_complain_undef ( void ) { }
402static void MC_helperc_LOADV8 ( void ) { }
403static void MC_helperc_LOADV4 ( void ) { }
404static void MC_helperc_LOADV2 ( void ) { }
405static void MC_helperc_LOADV1 ( void ) { }
sewardj1ea1b612005-03-26 13:02:20 +0000406static void MC_helperc_STOREV8( void ) { }
407static void MC_helperc_STOREV4( void ) { }
408static void MC_helperc_STOREV2( void ) { }
409static void MC_helperc_STOREV1( void ) { }
sewardjde8c9872005-03-25 13:48:55 +0000410static void MC_helperc_value_check0_fail( void ) { }
411static void MC_helperc_value_check1_fail( void ) { }
412static void MC_helperc_value_check4_fail( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000413
414
sewardj3598ef92004-11-11 02:13:30 +0000415/*--------------------------------------------------------------------*/
416/*--- Instrument IR to perform memory checking operations. ---*/
417/*--- mc_translate.c ---*/
418/*--------------------------------------------------------------------*/
419
420/*
421 This file is part of MemCheck, a heavyweight Valgrind tool for
422 detecting memory errors.
423
sewardj2d258d82006-06-05 23:26:23 +0000424 Copyright (C) 2000-2006 Julian Seward
sewardj3598ef92004-11-11 02:13:30 +0000425 jseward@acm.org
426
427 This program is free software; you can redistribute it and/or
428 modify it under the terms of the GNU General Public License as
429 published by the Free Software Foundation; either version 2 of the
430 License, or (at your option) any later version.
431
432 This program is distributed in the hope that it will be useful, but
433 WITHOUT ANY WARRANTY; without even the implied warranty of
434 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
435 General Public License for more details.
436
437 You should have received a copy of the GNU General Public License
438 along with this program; if not, write to the Free Software
439 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
440 02111-1307, USA.
441
442 The GNU General Public License is contained in the file COPYING.
443*/
444
445//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000446
447
448/*------------------------------------------------------------*/
449/*--- Forward decls ---*/
450/*------------------------------------------------------------*/
451
452struct _MCEnv;
453
454static IRType shadowType ( IRType ty );
455static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
456
457
458/*------------------------------------------------------------*/
459/*--- Memcheck running state, and tmp management. ---*/
460/*------------------------------------------------------------*/
461
462/* Carries around state during memcheck instrumentation. */
463typedef
464 struct _MCEnv {
465 /* MODIFIED: the bb being constructed. IRStmts are added. */
466 IRBB* bb;
467
468 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
469 original temps to their current their current shadow temp.
470 Initially all entries are IRTemp_INVALID. Entries are added
471 lazily since many original temps are not used due to
472 optimisation prior to instrumentation. Note that floating
473 point original tmps are shadowed by integer tmps of the same
474 size, and Bit-typed original tmps are shadowed by the type
475 Ity_I8. See comment below. */
476 IRTemp* tmpMap;
477 Int n_originalTmps; /* for range checking */
478
479 /* READONLY: the guest layout. This indicates which parts of
480 the guest state should be regarded as 'always defined'. */
481 VexGuestLayout* layout;
482 /* READONLY: the host word type. Needed for constructing
483 arguments of type 'HWord' to be passed to helper functions.
484 Ity_I32 or Ity_I64 only. */
485 IRType hWordTy;
486 }
487 MCEnv;
488
489/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
490 demand), as they are encountered. This is for two reasons.
491
492 (1) (less important reason): Many original tmps are unused due to
493 initial IR optimisation, and we do not want to spaces in tables
494 tracking them.
495
496 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
497 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000498 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000499 It is necessary to support making multiple assignments to a shadow
500 -- specifically, after testing a shadow for definedness, it needs
501 to be made defined. But IR's SSA property disallows this.
502
503 (2) (more important reason): Therefore, when a shadow needs to get
504 a new value, a new temporary is created, the value is assigned to
505 that, and the tmpMap is updated to reflect the new binding.
506
507 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000508 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000509 there's a read-before-write error in the original tmps. The IR
510 sanity checker should catch all such anomalies, however.
511*/
512
513/* Find the tmp currently shadowing the given original tmp. If none
514 so far exists, allocate one. */
515static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
516{
sewardj69f9e3e2004-12-30 02:05:34 +0000517 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000518 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000519 mce->tmpMap[orig]
520 = newIRTemp(mce->bb->tyenv,
521 shadowType(mce->bb->tyenv->types[orig]));
522 }
523 return mce->tmpMap[orig];
524}
525
526/* Allocate a new shadow for the given original tmp. This means any
527 previous shadow is abandoned. This is needed because it is
528 necessary to give a new value to a shadow once it has been tested
529 for undefinedness, but unfortunately IR's SSA property disallows
530 this. Instead we must abandon the old shadow, allocate a new one
531 and use that instead. */
532static void newShadowTmp ( MCEnv* mce, IRTemp orig )
533{
sewardj69f9e3e2004-12-30 02:05:34 +0000534 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000535 mce->tmpMap[orig]
536 = newIRTemp(mce->bb->tyenv,
537 shadowType(mce->bb->tyenv->types[orig]));
538}
539
540
541/*------------------------------------------------------------*/
542/*--- IRAtoms -- a subset of IRExprs ---*/
543/*------------------------------------------------------------*/
544
545/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj496a58d2005-03-20 18:44:44 +0000546 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardjde8a5ae2004-11-06 14:20:54 +0000547 input, most of this code deals in atoms. Usefully, a value atom
548 always has a V-value which is also an atom: constants are shadowed
549 by constants, and temps are shadowed by the corresponding shadow
550 temporary. */
551
552typedef IRExpr IRAtom;
553
554/* (used for sanity checks only): is this an atom which looks
555 like it's from original code? */
556static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
557{
558 if (a1->tag == Iex_Const)
559 return True;
560 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
561 return True;
562 return False;
563}
564
565/* (used for sanity checks only): is this an atom which looks
566 like it's from shadow code? */
567static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
568{
569 if (a1->tag == Iex_Const)
570 return True;
571 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
572 return True;
573 return False;
574}
575
576/* (used for sanity checks only): check that both args are atoms and
577 are identically-kinded. */
578static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
579{
580 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
581 return True;
582 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
583 return True;
584 return False;
585}
586
587
588/*------------------------------------------------------------*/
589/*--- Type management ---*/
590/*------------------------------------------------------------*/
591
592/* Shadow state is always accessed using integer types. This returns
593 an integer type with the same size (as per sizeofIRType) as the
594 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000595 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000596
597static IRType shadowType ( IRType ty )
598{
599 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000600 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000601 case Ity_I8:
602 case Ity_I16:
603 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000604 case Ity_I64: return ty;
605 case Ity_F32: return Ity_I32;
606 case Ity_F64: return Ity_I64;
607 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000608 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000609 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000610 }
611}
612
613/* Produce a 'defined' value of the given shadow type. Should only be
614 supplied shadow types (Bit/I8/I16/I32/UI64). */
615static IRExpr* definedOfType ( IRType ty ) {
616 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000617 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
618 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
619 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
620 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
621 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
622 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
623 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000624 }
625}
626
627
628/*------------------------------------------------------------*/
629/*--- Constructing IR fragments ---*/
630/*------------------------------------------------------------*/
631
632/* assign value to tmp */
633#define assign(_bb,_tmp,_expr) \
634 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
635
636/* add stmt to a bb */
637#define stmt(_bb,_stmt) \
638 addStmtToIRBB((_bb), (_stmt))
639
640/* build various kinds of expressions */
641#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
642#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
643#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
644#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
645#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
646#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000647#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardjde8a5ae2004-11-06 14:20:54 +0000648#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
649
650/* bind the given expression to a new temporary, and return the
651 temporary. This effectively converts an arbitrary expression into
652 an atom. */
653static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
654 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
655 assign(mce->bb, t, e);
656 return mkexpr(t);
657}
658
659
660/*------------------------------------------------------------*/
661/*--- Constructing definedness primitive ops ---*/
662/*------------------------------------------------------------*/
663
664/* --------- Defined-if-either-defined --------- */
665
666static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000667 tl_assert(isShadowAtom(mce,a1));
668 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000669 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
670}
671
672static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000673 tl_assert(isShadowAtom(mce,a1));
674 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000675 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
676}
677
678static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000679 tl_assert(isShadowAtom(mce,a1));
680 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000681 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
682}
683
sewardj69f9e3e2004-12-30 02:05:34 +0000684static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
685 tl_assert(isShadowAtom(mce,a1));
686 tl_assert(isShadowAtom(mce,a2));
687 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
688}
689
sewardjf0c1c582005-02-07 23:47:38 +0000690static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000691 tl_assert(isShadowAtom(mce,a1));
692 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000693 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000694}
695
sewardjde8a5ae2004-11-06 14:20:54 +0000696/* --------- Undefined-if-either-undefined --------- */
697
698static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000699 tl_assert(isShadowAtom(mce,a1));
700 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000701 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
702}
703
704static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000705 tl_assert(isShadowAtom(mce,a1));
706 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000707 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
708}
709
710static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000711 tl_assert(isShadowAtom(mce,a1));
712 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000713 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
714}
715
716static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000717 tl_assert(isShadowAtom(mce,a1));
718 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000719 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
720}
721
sewardjf0c1c582005-02-07 23:47:38 +0000722static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000723 tl_assert(isShadowAtom(mce,a1));
724 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000725 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000726}
727
728static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000729 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000730 case Ity_I8: return mkUifU8(mce, a1, a2);
731 case Ity_I16: return mkUifU16(mce, a1, a2);
732 case Ity_I32: return mkUifU32(mce, a1, a2);
733 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardjf0c1c582005-02-07 23:47:38 +0000734 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000735 default:
736 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000737 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000738 }
739}
740
741/* --------- The Left-family of operations. --------- */
742
743static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000744 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000745 /* It's safe to duplicate a1 since it's only an atom */
746 return assignNew(mce, Ity_I8,
747 binop(Iop_Or8, a1,
748 assignNew(mce, Ity_I8,
749 /* unop(Iop_Neg8, a1)))); */
750 binop(Iop_Sub8, mkU8(0), a1) )));
751}
752
753static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000754 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000755 /* It's safe to duplicate a1 since it's only an atom */
756 return assignNew(mce, Ity_I16,
757 binop(Iop_Or16, a1,
758 assignNew(mce, Ity_I16,
759 /* unop(Iop_Neg16, a1)))); */
760 binop(Iop_Sub16, mkU16(0), a1) )));
761}
762
763static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000764 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000765 /* It's safe to duplicate a1 since it's only an atom */
766 return assignNew(mce, Ity_I32,
767 binop(Iop_Or32, a1,
768 assignNew(mce, Ity_I32,
769 /* unop(Iop_Neg32, a1)))); */
770 binop(Iop_Sub32, mkU32(0), a1) )));
771}
772
773/* --------- 'Improvement' functions for AND/OR. --------- */
774
775/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
776 defined (0); all other -> undefined (1).
777*/
778static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
779{
sewardj69f9e3e2004-12-30 02:05:34 +0000780 tl_assert(isOriginalAtom(mce, data));
781 tl_assert(isShadowAtom(mce, vbits));
782 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000783 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
784}
785
sewardj3598ef92004-11-11 02:13:30 +0000786static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
787{
sewardj69f9e3e2004-12-30 02:05:34 +0000788 tl_assert(isOriginalAtom(mce, data));
789 tl_assert(isShadowAtom(mce, vbits));
790 tl_assert(sameKindedAtoms(data, vbits));
sewardj3598ef92004-11-11 02:13:30 +0000791 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
792}
793
sewardjde8a5ae2004-11-06 14:20:54 +0000794static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
795{
sewardj69f9e3e2004-12-30 02:05:34 +0000796 tl_assert(isOriginalAtom(mce, data));
797 tl_assert(isShadowAtom(mce, vbits));
798 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000799 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
800}
801
sewardj69f9e3e2004-12-30 02:05:34 +0000802static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
803{
804 tl_assert(isOriginalAtom(mce, data));
805 tl_assert(isShadowAtom(mce, vbits));
806 tl_assert(sameKindedAtoms(data, vbits));
807 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
808}
809
sewardjf0c1c582005-02-07 23:47:38 +0000810static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000811{
812 tl_assert(isOriginalAtom(mce, data));
813 tl_assert(isShadowAtom(mce, vbits));
814 tl_assert(sameKindedAtoms(data, vbits));
sewardjf0c1c582005-02-07 23:47:38 +0000815 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj69f9e3e2004-12-30 02:05:34 +0000816}
817
sewardjde8a5ae2004-11-06 14:20:54 +0000818/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
819 defined (0); all other -> undefined (1).
820*/
821static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
822{
sewardj69f9e3e2004-12-30 02:05:34 +0000823 tl_assert(isOriginalAtom(mce, data));
824 tl_assert(isShadowAtom(mce, vbits));
825 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000826 return assignNew(
827 mce, Ity_I8,
828 binop(Iop_Or8,
829 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
830 vbits) );
831}
832
833static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
834{
sewardj69f9e3e2004-12-30 02:05:34 +0000835 tl_assert(isOriginalAtom(mce, data));
836 tl_assert(isShadowAtom(mce, vbits));
837 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000838 return assignNew(
839 mce, Ity_I16,
840 binop(Iop_Or16,
841 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
842 vbits) );
843}
844
845static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
846{
sewardj69f9e3e2004-12-30 02:05:34 +0000847 tl_assert(isOriginalAtom(mce, data));
848 tl_assert(isShadowAtom(mce, vbits));
849 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000850 return assignNew(
851 mce, Ity_I32,
852 binop(Iop_Or32,
853 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
854 vbits) );
855}
856
sewardj69f9e3e2004-12-30 02:05:34 +0000857static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
858{
859 tl_assert(isOriginalAtom(mce, data));
860 tl_assert(isShadowAtom(mce, vbits));
861 tl_assert(sameKindedAtoms(data, vbits));
862 return assignNew(
863 mce, Ity_I64,
864 binop(Iop_Or64,
865 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
866 vbits) );
867}
868
sewardjf0c1c582005-02-07 23:47:38 +0000869static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000870{
871 tl_assert(isOriginalAtom(mce, data));
872 tl_assert(isShadowAtom(mce, vbits));
873 tl_assert(sameKindedAtoms(data, vbits));
874 return assignNew(
875 mce, Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +0000876 binop(Iop_OrV128,
877 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj69f9e3e2004-12-30 02:05:34 +0000878 vbits) );
879}
880
sewardjde8a5ae2004-11-06 14:20:54 +0000881/* --------- Pessimising casts. --------- */
882
883static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
884{
sewardj8fc93742004-11-22 11:29:33 +0000885 IRType ty;
886 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000887 /* Note, dst_ty is a shadow type, not an original type. */
888 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000889 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000890 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
891 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000892 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000893 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000894 tmp1 = vbits;
895 break;
896 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000897 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000898 break;
899 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000900 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000901 break;
902 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000903 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000904 break;
905 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000906 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000907 break;
908 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000909 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000910 }
sewardj69f9e3e2004-12-30 02:05:34 +0000911 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000912 /* Now widen up to the dst type. */
913 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000914 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000915 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000916 case Ity_I8:
917 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000918 case Ity_I16:
919 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
920 case Ity_I32:
921 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
922 case Ity_I64:
923 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000924 case Ity_V128:
925 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardjf0c1c582005-02-07 23:47:38 +0000926 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000927 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000928 default:
929 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000930 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +0000931 }
932}
933
934
935/*------------------------------------------------------------*/
936/*--- Emit a test and complaint if something is undefined. ---*/
937/*------------------------------------------------------------*/
938
939/* Set the annotations on a dirty helper to indicate that the stack
940 pointer and instruction pointers might be read. This is the
941 behaviour of all 'emit-a-complaint' style functions we might
942 call. */
943
944static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
945 di->nFxState = 2;
946 di->fxState[0].fx = Ifx_Read;
947 di->fxState[0].offset = mce->layout->offset_SP;
948 di->fxState[0].size = mce->layout->sizeof_SP;
949 di->fxState[1].fx = Ifx_Read;
950 di->fxState[1].offset = mce->layout->offset_IP;
951 di->fxState[1].size = mce->layout->sizeof_IP;
952}
953
954
955/* Check the supplied **original** atom for undefinedness, and emit a
956 complaint if so. Once that happens, mark it as defined. This is
957 possible because the atom is either a tmp or literal. If it's a
958 tmp, it will be shadowed by a tmp, and so we can set the shadow to
959 be defined. In fact as mentioned above, we will have to allocate a
960 new tmp to carry the new 'defined' shadow value, and update the
961 original->tmp mapping accordingly; we cannot simply assign a new
962 value to an existing shadow tmp as this breaks SSAness -- resulting
963 in the post-instrumentation sanity checker spluttering in disapproval.
964*/
965static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
966{
sewardj8fc93742004-11-22 11:29:33 +0000967 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +0000968 IRType ty;
969 Int sz;
sewardj8fc93742004-11-22 11:29:33 +0000970 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +0000971 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +0000972
sewardjde8a5ae2004-11-06 14:20:54 +0000973 /* Since the original expression is atomic, there's no duplicated
974 work generated by making multiple V-expressions for it. So we
975 don't really care about the possibility that someone else may
976 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +0000977 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +0000978 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +0000979 tl_assert(isShadowAtom(mce, vatom));
980 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +0000981
sewardj8fc93742004-11-22 11:29:33 +0000982 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +0000983
984 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +0000985 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +0000986
sewardj8fc93742004-11-22 11:29:33 +0000987 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +0000988 /* cond will be 0 if all defined, and 1 if any not defined. */
989
sewardj3598ef92004-11-11 02:13:30 +0000990 switch (sz) {
991 case 0:
992 di = unsafeIRDirty_0_N( 0/*regparms*/,
993 "MC_(helperc_value_check0_fail)",
994 &MC_(helperc_value_check0_fail),
995 mkIRExprVec_0()
996 );
997 break;
998 case 1:
999 di = unsafeIRDirty_0_N( 0/*regparms*/,
1000 "MC_(helperc_value_check1_fail)",
1001 &MC_(helperc_value_check1_fail),
1002 mkIRExprVec_0()
1003 );
1004 break;
1005 case 4:
1006 di = unsafeIRDirty_0_N( 0/*regparms*/,
1007 "MC_(helperc_value_check4_fail)",
1008 &MC_(helperc_value_check4_fail),
1009 mkIRExprVec_0()
1010 );
1011 break;
1012 default:
1013 di = unsafeIRDirty_0_N( 1/*regparms*/,
1014 "MC_(helperc_complain_undef)",
1015 &MC_(helperc_complain_undef),
1016 mkIRExprVec_1( mkIRExpr_HWord( sz ))
1017 );
1018 break;
1019 }
sewardjde8a5ae2004-11-06 14:20:54 +00001020 di->guard = cond;
1021 setHelperAnns( mce, di );
1022 stmt( mce->bb, IRStmt_Dirty(di));
1023
1024 /* Set the shadow tmp to be defined. First, update the
1025 orig->shadow tmp mapping to reflect the fact that this shadow is
1026 getting a new value. */
sewardj496a58d2005-03-20 18:44:44 +00001027 tl_assert(isIRAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001028 /* sameKindedAtoms ... */
1029 if (vatom->tag == Iex_Tmp) {
sewardj69f9e3e2004-12-30 02:05:34 +00001030 tl_assert(atom->tag == Iex_Tmp);
sewardjde8a5ae2004-11-06 14:20:54 +00001031 newShadowTmp(mce, atom->Iex.Tmp.tmp);
1032 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
1033 definedOfType(ty));
1034 }
1035}
1036
1037
1038/*------------------------------------------------------------*/
1039/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
1040/*------------------------------------------------------------*/
1041
1042/* Examine the always-defined sections declared in layout to see if
1043 the (offset,size) section is within one. Note, is is an error to
1044 partially fall into such a region: (offset,size) should either be
1045 completely in such a region or completely not-in such a region.
1046*/
1047static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1048{
1049 Int minoffD, maxoffD, i;
1050 Int minoff = offset;
1051 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001052 tl_assert((minoff & ~0xFFFF) == 0);
1053 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001054
1055 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1056 minoffD = mce->layout->alwaysDefd[i].offset;
1057 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001058 tl_assert((minoffD & ~0xFFFF) == 0);
1059 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001060
1061 if (maxoff < minoffD || maxoffD < minoff)
1062 continue; /* no overlap */
1063 if (minoff >= minoffD && maxoff <= maxoffD)
1064 return True; /* completely contained in an always-defd section */
1065
sewardj69f9e3e2004-12-30 02:05:34 +00001066 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001067 }
1068 return False; /* could not find any containing section */
1069}
1070
1071
1072/* Generate into bb suitable actions to shadow this Put. If the state
1073 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001074 supplied V bits to the shadow state. We can pass in either an
1075 original atom or a V-atom, but not both. In the former case the
1076 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001077*/
1078static
sewardj3598ef92004-11-11 02:13:30 +00001079void do_shadow_PUT ( MCEnv* mce, Int offset,
1080 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001081{
sewardj8fc93742004-11-22 11:29:33 +00001082 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001083 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001084 tl_assert(!vatom);
1085 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001086 vatom = expr2vbits( mce, atom );
1087 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001088 tl_assert(vatom);
1089 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001090 }
1091
sewardj8fc93742004-11-22 11:29:33 +00001092 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001093 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001094 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1095 /* later: no ... */
1096 /* emit code to emit a complaint if any of the vbits are 1. */
1097 /* complainIfUndefined(mce, atom); */
1098 } else {
1099 /* Do a plain shadow Put. */
1100 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1101 }
1102}
1103
1104
1105/* Return an expression which contains the V bits corresponding to the
1106 given GETI (passed in in pieces).
1107*/
1108static
1109void do_shadow_PUTI ( MCEnv* mce,
1110 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
1111{
sewardj8fc93742004-11-22 11:29:33 +00001112 IRAtom* vatom;
1113 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001114 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001115
sewardj69f9e3e2004-12-30 02:05:34 +00001116 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001117 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001118 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001119 ty = descr->elemTy;
1120 tyS = shadowType(ty);
1121 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001122 tl_assert(ty != Ity_I1);
1123 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001124 complainIfUndefined(mce,ix);
1125 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1126 /* later: no ... */
1127 /* emit code to emit a complaint if any of the vbits are 1. */
1128 /* complainIfUndefined(mce, atom); */
1129 } else {
1130 /* Do a cloned version of the Put that refers to the shadow
1131 area. */
1132 IRArray* new_descr
1133 = mkIRArray( descr->base + mce->layout->total_sizeB,
1134 tyS, descr->nElems);
1135 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1136 }
1137}
1138
1139
1140/* Return an expression which contains the V bits corresponding to the
1141 given GET (passed in in pieces).
1142*/
1143static
1144IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1145{
1146 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001147 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001148 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1149 /* Always defined, return all zeroes of the relevant type */
1150 return definedOfType(tyS);
1151 } else {
1152 /* return a cloned version of the Get that refers to the shadow
1153 area. */
1154 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1155 }
1156}
1157
1158
1159/* Return an expression which contains the V bits corresponding to the
1160 given GETI (passed in in pieces).
1161*/
1162static
1163IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
1164{
1165 IRType ty = descr->elemTy;
1166 IRType tyS = shadowType(ty);
1167 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001168 tl_assert(ty != Ity_I1);
1169 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001170 complainIfUndefined(mce,ix);
1171 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1172 /* Always defined, return all zeroes of the relevant type */
1173 return definedOfType(tyS);
1174 } else {
1175 /* return a cloned version of the Get that refers to the shadow
1176 area. */
1177 IRArray* new_descr
1178 = mkIRArray( descr->base + mce->layout->total_sizeB,
1179 tyS, descr->nElems);
1180 return IRExpr_GetI( new_descr, ix, bias );
1181 }
1182}
1183
1184
1185/*------------------------------------------------------------*/
1186/*--- Generating approximations for unknown operations, ---*/
1187/*--- using lazy-propagate semantics ---*/
1188/*------------------------------------------------------------*/
1189
1190/* Lazy propagation of undefinedness from two values, resulting in the
1191 specified shadow type.
1192*/
1193static
1194IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1195{
1196 /* force everything via 32-bit intermediaries. */
1197 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001198 tl_assert(isShadowAtom(mce,va1));
1199 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001200 at = mkPCastTo(mce, Ity_I32, va1);
1201 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1202 at = mkPCastTo(mce, finalVty, at);
1203 return at;
1204}
1205
1206
1207/* Do the lazy propagation game from a null-terminated vector of
1208 atoms. This is presumably the arguments to a helper call, so the
1209 IRCallee info is also supplied in order that we can know which
1210 arguments should be ignored (via the .mcx_mask field).
1211*/
1212static
1213IRAtom* mkLazyN ( MCEnv* mce,
1214 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1215{
1216 Int i;
1217 IRAtom* here;
1218 IRAtom* curr = definedOfType(Ity_I32);
1219 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001220 tl_assert(i < 32);
1221 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001222 /* Only take notice of this arg if the callee's mc-exclusion
1223 mask does not say it is to be excluded. */
1224 if (cee->mcx_mask & (1<<i)) {
1225 /* the arg is to be excluded from definedness checking. Do
1226 nothing. */
1227 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1228 } else {
1229 /* calculate the arg's definedness, and pessimistically merge
1230 it in. */
1231 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1232 curr = mkUifU32(mce, here, curr);
1233 }
1234 }
1235 return mkPCastTo(mce, finalVtype, curr );
1236}
1237
1238
1239/*------------------------------------------------------------*/
1240/*--- Generating expensive sequences for exact carry-chain ---*/
1241/*--- propagation in add/sub and related operations. ---*/
1242/*------------------------------------------------------------*/
1243
1244static
1245IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1246 IRAtom* aa, IRAtom* bb )
1247{
sewardj69f9e3e2004-12-30 02:05:34 +00001248 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001249 IRType ty;
1250 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001251
sewardj69f9e3e2004-12-30 02:05:34 +00001252 tl_assert(isShadowAtom(mce,qaa));
1253 tl_assert(isShadowAtom(mce,qbb));
1254 tl_assert(isOriginalAtom(mce,aa));
1255 tl_assert(isOriginalAtom(mce,bb));
1256 tl_assert(sameKindedAtoms(qaa,aa));
1257 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001258
sewardj8fc93742004-11-22 11:29:33 +00001259 ty = Ity_I32;
1260 opAND = Iop_And32;
1261 opOR = Iop_Or32;
1262 opXOR = Iop_Xor32;
1263 opNOT = Iop_Not32;
1264 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001265
1266 // a_min = aa & ~qaa
1267 a_min = assignNew(mce,ty,
1268 binop(opAND, aa,
1269 assignNew(mce,ty, unop(opNOT, qaa))));
1270
1271 // b_min = bb & ~qbb
1272 b_min = assignNew(mce,ty,
1273 binop(opAND, bb,
1274 assignNew(mce,ty, unop(opNOT, qbb))));
1275
1276 // a_max = aa | qaa
1277 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1278
1279 // b_max = bb | qbb
1280 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1281
1282 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1283 return
1284 assignNew(mce,ty,
1285 binop( opOR,
1286 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1287 assignNew(mce,ty,
1288 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1289 assignNew(mce,ty, binop(opADD, a_max, b_max))
1290 )
1291 )
1292 )
1293 );
1294}
1295
1296
1297/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001298/*--- Helpers for dealing with vector primops. ---*/
1299/*------------------------------------------------------------*/
1300
1301/* Vector pessimisation -- pessimise within each lane individually. */
1302
1303static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1304{
1305 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1306}
1307
1308static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1309{
1310 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1311}
1312
1313static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1314{
1315 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1316}
1317
1318static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1319{
1320 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1321}
1322
1323
1324/* Here's a simple scheme capable of handling ops derived from SSE1
1325 code and while only generating ops that can be efficiently
1326 implemented in SSE1. */
1327
1328/* All-lanes versions are straightforward:
1329
sewardjf0c1c582005-02-07 23:47:38 +00001330 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj69f9e3e2004-12-30 02:05:34 +00001331
1332 unary32Fx4(x,y) ==> PCast32x4(x#)
1333
1334 Lowest-lane-only versions are more complex:
1335
sewardjf0c1c582005-02-07 23:47:38 +00001336 binary32F0x4(x,y) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001337 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001338 PCast32(V128to32(UifUV128(x#,y#)))
sewardj69f9e3e2004-12-30 02:05:34 +00001339 )
1340
1341 This is perhaps not so obvious. In particular, it's faster to
sewardjf0c1c582005-02-07 23:47:38 +00001342 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj69f9e3e2004-12-30 02:05:34 +00001343 obvious scheme of taking the bottom 32 bits of each operand
1344 and doing a 32-bit UifU. Basically since UifU is fast and
1345 chopping lanes off vector values is slow.
1346
1347 Finally:
1348
sewardjf0c1c582005-02-07 23:47:38 +00001349 unary32F0x4(x) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001350 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001351 PCast32(V128to32(x#))
sewardj69f9e3e2004-12-30 02:05:34 +00001352 )
1353
1354 Where:
1355
1356 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1357 PCast32x4(v#) = CmpNEZ32x4(v#)
1358*/
1359
1360static
1361IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1362{
1363 IRAtom* at;
1364 tl_assert(isShadowAtom(mce, vatomX));
1365 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001366 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001367 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1368 return at;
1369}
1370
1371static
1372IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1373{
1374 IRAtom* at;
1375 tl_assert(isShadowAtom(mce, vatomX));
1376 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1377 return at;
1378}
1379
1380static
1381IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1382{
1383 IRAtom* at;
1384 tl_assert(isShadowAtom(mce, vatomX));
1385 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001386 at = mkUifUV128(mce, vatomX, vatomY);
1387 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001388 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001389 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001390 return at;
1391}
1392
1393static
1394IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1395{
1396 IRAtom* at;
1397 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001398 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001399 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001400 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001401 return at;
1402}
1403
1404/* --- ... and ... 64Fx2 versions of the same ... --- */
1405
1406static
1407IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1408{
1409 IRAtom* at;
1410 tl_assert(isShadowAtom(mce, vatomX));
1411 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001412 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001413 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1414 return at;
1415}
1416
1417static
1418IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1419{
1420 IRAtom* at;
1421 tl_assert(isShadowAtom(mce, vatomX));
1422 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1423 return at;
1424}
1425
1426static
1427IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1428{
1429 IRAtom* at;
1430 tl_assert(isShadowAtom(mce, vatomX));
1431 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001432 at = mkUifUV128(mce, vatomX, vatomY);
1433 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001434 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001435 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001436 return at;
1437}
1438
1439static
1440IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1441{
1442 IRAtom* at;
1443 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001444 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001445 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001446 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001447 return at;
1448}
1449
1450/* --- --- Vector saturated narrowing --- --- */
1451
1452/* This is quite subtle. What to do is simple:
1453
1454 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1455
1456 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1457
1458 Why this is right is not so simple. Consider a lane in the args,
1459 vatom1 or 2, doesn't matter.
1460
1461 After the PCast, that lane is all 0s (defined) or all
1462 1s(undefined).
1463
1464 Both signed and unsigned saturating narrowing of all 0s produces
1465 all 0s, which is what we want.
1466
1467 The all-1s case is more complex. Unsigned narrowing interprets an
1468 all-1s input as the largest unsigned integer, and so produces all
1469 1s as a result since that is the largest unsigned value at the
1470 smaller width.
1471
1472 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1473 to -1, so we still wind up with all 1s at the smaller width.
1474
1475 So: In short, pessimise the args, then apply the original narrowing
1476 op.
1477*/
1478static
sewardjf0c1c582005-02-07 23:47:38 +00001479IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardj69f9e3e2004-12-30 02:05:34 +00001480 IRAtom* vatom1, IRAtom* vatom2)
1481{
1482 IRAtom *at1, *at2, *at3;
1483 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1484 switch (narrow_op) {
1485 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1486 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1487 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardjf0c1c582005-02-07 23:47:38 +00001488 default: VG_(tool_panic)("vectorNarrowV128");
sewardj69f9e3e2004-12-30 02:05:34 +00001489 }
1490 tl_assert(isShadowAtom(mce,vatom1));
1491 tl_assert(isShadowAtom(mce,vatom2));
1492 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1493 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1494 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1495 return at3;
1496}
1497
1498
1499/* --- --- Vector integer arithmetic --- --- */
1500
1501/* Simple ... UifU the args and per-lane pessimise the results. */
1502static
1503IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1504{
1505 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001506 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001507 at = mkPCast8x16(mce, at);
1508 return at;
1509}
1510
1511static
1512IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1513{
1514 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001515 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001516 at = mkPCast16x8(mce, at);
1517 return at;
1518}
1519
1520static
1521IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1522{
1523 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001524 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001525 at = mkPCast32x4(mce, at);
1526 return at;
1527}
1528
1529static
1530IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1531{
1532 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001533 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001534 at = mkPCast64x2(mce, at);
1535 return at;
1536}
1537
1538
1539/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001540/*--- Generate shadow values from all kinds of IRExprs. ---*/
1541/*------------------------------------------------------------*/
1542
1543static
1544IRAtom* expr2vbits_Binop ( MCEnv* mce,
1545 IROp op,
1546 IRAtom* atom1, IRAtom* atom2 )
1547{
1548 IRType and_or_ty;
1549 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1550 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1551 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1552
1553 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1554 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1555
sewardj69f9e3e2004-12-30 02:05:34 +00001556 tl_assert(isOriginalAtom(mce,atom1));
1557 tl_assert(isOriginalAtom(mce,atom2));
1558 tl_assert(isShadowAtom(mce,vatom1));
1559 tl_assert(isShadowAtom(mce,vatom2));
1560 tl_assert(sameKindedAtoms(atom1,vatom1));
1561 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001562 switch (op) {
1563
sewardjf0c1c582005-02-07 23:47:38 +00001564 /* V128-bit SIMD (SSE2-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001565
1566 case Iop_ShrN16x8:
1567 case Iop_ShrN32x4:
1568 case Iop_ShrN64x2:
1569 case Iop_SarN16x8:
1570 case Iop_SarN32x4:
1571 case Iop_ShlN16x8:
1572 case Iop_ShlN32x4:
1573 case Iop_ShlN64x2:
1574 /* Same scheme as with all other shifts. */
1575 complainIfUndefined(mce, atom2);
1576 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1577
1578 case Iop_QSub8Ux16:
1579 case Iop_QSub8Sx16:
1580 case Iop_Sub8x16:
1581 case Iop_Min8Ux16:
1582 case Iop_Max8Ux16:
1583 case Iop_CmpGT8Sx16:
1584 case Iop_CmpEQ8x16:
1585 case Iop_Avg8Ux16:
1586 case Iop_QAdd8Ux16:
1587 case Iop_QAdd8Sx16:
1588 case Iop_Add8x16:
1589 return binary8Ix16(mce, vatom1, vatom2);
1590
1591 case Iop_QSub16Ux8:
1592 case Iop_QSub16Sx8:
1593 case Iop_Sub16x8:
1594 case Iop_Mul16x8:
1595 case Iop_MulHi16Sx8:
1596 case Iop_MulHi16Ux8:
1597 case Iop_Min16Sx8:
1598 case Iop_Max16Sx8:
1599 case Iop_CmpGT16Sx8:
1600 case Iop_CmpEQ16x8:
1601 case Iop_Avg16Ux8:
1602 case Iop_QAdd16Ux8:
1603 case Iop_QAdd16Sx8:
1604 case Iop_Add16x8:
1605 return binary16Ix8(mce, vatom1, vatom2);
1606
1607 case Iop_Sub32x4:
1608 case Iop_CmpGT32Sx4:
1609 case Iop_CmpEQ32x4:
1610 case Iop_Add32x4:
1611 return binary32Ix4(mce, vatom1, vatom2);
1612
1613 case Iop_Sub64x2:
1614 case Iop_Add64x2:
1615 return binary64Ix2(mce, vatom1, vatom2);
1616
1617 case Iop_QNarrow32Sx4:
1618 case Iop_QNarrow16Sx8:
1619 case Iop_QNarrow16Ux8:
sewardjf0c1c582005-02-07 23:47:38 +00001620 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001621
1622 case Iop_Sub64Fx2:
1623 case Iop_Mul64Fx2:
1624 case Iop_Min64Fx2:
1625 case Iop_Max64Fx2:
1626 case Iop_Div64Fx2:
1627 case Iop_CmpLT64Fx2:
1628 case Iop_CmpLE64Fx2:
1629 case Iop_CmpEQ64Fx2:
1630 case Iop_Add64Fx2:
1631 return binary64Fx2(mce, vatom1, vatom2);
1632
1633 case Iop_Sub64F0x2:
1634 case Iop_Mul64F0x2:
1635 case Iop_Min64F0x2:
1636 case Iop_Max64F0x2:
1637 case Iop_Div64F0x2:
1638 case Iop_CmpLT64F0x2:
1639 case Iop_CmpLE64F0x2:
1640 case Iop_CmpEQ64F0x2:
1641 case Iop_Add64F0x2:
1642 return binary64F0x2(mce, vatom1, vatom2);
1643
sewardjf0c1c582005-02-07 23:47:38 +00001644 /* V128-bit SIMD (SSE1-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001645
1646 case Iop_Sub32Fx4:
1647 case Iop_Mul32Fx4:
1648 case Iop_Min32Fx4:
1649 case Iop_Max32Fx4:
1650 case Iop_Div32Fx4:
1651 case Iop_CmpLT32Fx4:
1652 case Iop_CmpLE32Fx4:
1653 case Iop_CmpEQ32Fx4:
1654 case Iop_Add32Fx4:
1655 return binary32Fx4(mce, vatom1, vatom2);
1656
1657 case Iop_Sub32F0x4:
1658 case Iop_Mul32F0x4:
1659 case Iop_Min32F0x4:
1660 case Iop_Max32F0x4:
1661 case Iop_Div32F0x4:
1662 case Iop_CmpLT32F0x4:
1663 case Iop_CmpLE32F0x4:
1664 case Iop_CmpEQ32F0x4:
1665 case Iop_Add32F0x4:
1666 return binary32F0x4(mce, vatom1, vatom2);
1667
sewardjf0c1c582005-02-07 23:47:38 +00001668 /* V128-bit data-steering */
1669 case Iop_SetV128lo32:
1670 case Iop_SetV128lo64:
1671 case Iop_64HLtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001672 case Iop_InterleaveLO64x2:
1673 case Iop_InterleaveLO32x4:
1674 case Iop_InterleaveLO16x8:
1675 case Iop_InterleaveLO8x16:
1676 case Iop_InterleaveHI64x2:
1677 case Iop_InterleaveHI32x4:
1678 case Iop_InterleaveHI16x8:
1679 case Iop_InterleaveHI8x16:
1680 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1681
1682 /* Scalar floating point */
1683
sewardj3598ef92004-11-11 02:13:30 +00001684 case Iop_RoundF64:
1685 case Iop_F64toI64:
sewardj69f9e3e2004-12-30 02:05:34 +00001686 case Iop_I64toF64:
1687 /* First arg is I32 (rounding mode), second is F64 or I64
1688 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001689 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1690
1691 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1692 /* Takes two F64 args. */
sewardjde8a5ae2004-11-06 14:20:54 +00001693 case Iop_F64toI32:
sewardj69f9e3e2004-12-30 02:05:34 +00001694 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001695 /* First arg is I32 (rounding mode), second is F64 (data). */
1696 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1697
1698 case Iop_F64toI16:
1699 /* First arg is I32 (rounding mode), second is F64 (data). */
1700 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1701
sewardj3598ef92004-11-11 02:13:30 +00001702 case Iop_ScaleF64:
1703 case Iop_Yl2xF64:
1704 case Iop_Yl2xp1F64:
1705 case Iop_PRemF64:
1706 case Iop_AtanF64:
1707 case Iop_AddF64:
1708 case Iop_DivF64:
1709 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001710 case Iop_MulF64:
1711 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1712
sewardj3598ef92004-11-11 02:13:30 +00001713 case Iop_CmpF64:
1714 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1715
sewardjde8a5ae2004-11-06 14:20:54 +00001716 /* non-FP after here */
1717
1718 case Iop_DivModU64to32:
1719 case Iop_DivModS64to32:
1720 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1721
sewardj3598ef92004-11-11 02:13:30 +00001722 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001723 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001724 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001725 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001726
1727 case Iop_MullS32:
1728 case Iop_MullU32: {
1729 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1730 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1731 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1732 }
1733
sewardj3598ef92004-11-11 02:13:30 +00001734 case Iop_MullS16:
1735 case Iop_MullU16: {
1736 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1737 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1738 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1739 }
1740
1741 case Iop_MullS8:
1742 case Iop_MullU8: {
1743 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1744 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1745 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1746 }
1747
sewardjde8a5ae2004-11-06 14:20:54 +00001748 case Iop_Add32:
1749# if 0
1750 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1751# endif
1752 case Iop_Sub32:
1753 case Iop_Mul32:
1754 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1755
sewardj3598ef92004-11-11 02:13:30 +00001756 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001757 case Iop_Add16:
1758 case Iop_Sub16:
1759 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1760
1761 case Iop_Sub8:
1762 case Iop_Add8:
1763 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1764
1765 case Iop_CmpLE32S: case Iop_CmpLE32U:
1766 case Iop_CmpLT32U: case Iop_CmpLT32S:
1767 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001768 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001769
sewardj3598ef92004-11-11 02:13:30 +00001770 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001771 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001772
1773 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001774 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001775
1776 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1777 /* Complain if the shift amount is undefined. Then simply
1778 shift the first arg's V bits by the real shift amount. */
1779 complainIfUndefined(mce, atom2);
1780 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1781
sewardj69f9e3e2004-12-30 02:05:34 +00001782 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001783 /* Same scheme as with 32-bit shifts. */
1784 complainIfUndefined(mce, atom2);
1785 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1786
sewardj3598ef92004-11-11 02:13:30 +00001787 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001788 /* Same scheme as with 32-bit shifts. */
1789 complainIfUndefined(mce, atom2);
1790 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1791
1792 case Iop_Shl64: case Iop_Shr64:
1793 /* Same scheme as with 32-bit shifts. */
1794 complainIfUndefined(mce, atom2);
1795 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1796
sewardjf0c1c582005-02-07 23:47:38 +00001797 case Iop_AndV128:
1798 uifu = mkUifUV128; difd = mkDifDV128;
1799 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001800 case Iop_And64:
1801 uifu = mkUifU64; difd = mkDifD64;
1802 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001803 case Iop_And32:
1804 uifu = mkUifU32; difd = mkDifD32;
1805 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001806 case Iop_And16:
1807 uifu = mkUifU16; difd = mkDifD16;
1808 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001809 case Iop_And8:
1810 uifu = mkUifU8; difd = mkDifD8;
1811 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1812
sewardjf0c1c582005-02-07 23:47:38 +00001813 case Iop_OrV128:
1814 uifu = mkUifUV128; difd = mkDifDV128;
1815 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001816 case Iop_Or64:
1817 uifu = mkUifU64; difd = mkDifD64;
1818 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001819 case Iop_Or32:
1820 uifu = mkUifU32; difd = mkDifD32;
1821 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1822 case Iop_Or16:
1823 uifu = mkUifU16; difd = mkDifD16;
1824 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1825 case Iop_Or8:
1826 uifu = mkUifU8; difd = mkDifD8;
1827 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1828
1829 do_And_Or:
1830 return
1831 assignNew(
1832 mce,
1833 and_or_ty,
1834 difd(mce, uifu(mce, vatom1, vatom2),
1835 difd(mce, improve(mce, atom1, vatom1),
1836 improve(mce, atom2, vatom2) ) ) );
1837
1838 case Iop_Xor8:
1839 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001840 case Iop_Xor16:
1841 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001842 case Iop_Xor32:
1843 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001844 case Iop_Xor64:
1845 return mkUifU64(mce, vatom1, vatom2);
sewardjf0c1c582005-02-07 23:47:38 +00001846 case Iop_XorV128:
1847 return mkUifUV128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001848
1849 default:
1850 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001851 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001852 }
1853}
1854
1855
1856static
1857IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1858{
1859 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001860 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001861 switch (op) {
1862
sewardj69f9e3e2004-12-30 02:05:34 +00001863 case Iop_Sqrt64Fx2:
1864 return unary64Fx2(mce, vatom);
1865
1866 case Iop_Sqrt64F0x2:
1867 return unary64F0x2(mce, vatom);
1868
1869 case Iop_Sqrt32Fx4:
1870 case Iop_RSqrt32Fx4:
1871 case Iop_Recip32Fx4:
1872 return unary32Fx4(mce, vatom);
1873
1874 case Iop_Sqrt32F0x4:
1875 case Iop_RSqrt32F0x4:
1876 case Iop_Recip32F0x4:
1877 return unary32F0x4(mce, vatom);
1878
sewardjf0c1c582005-02-07 23:47:38 +00001879 case Iop_32UtoV128:
1880 case Iop_64UtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001881 return assignNew(mce, Ity_V128, unop(op, vatom));
1882
sewardjde8a5ae2004-11-06 14:20:54 +00001883 case Iop_F32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001884 case Iop_I32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001885 case Iop_NegF64:
1886 case Iop_SinF64:
1887 case Iop_CosF64:
1888 case Iop_TanF64:
1889 case Iop_SqrtF64:
1890 case Iop_AbsF64:
1891 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001892 return mkPCastTo(mce, Ity_I64, vatom);
1893
sewardj3598ef92004-11-11 02:13:30 +00001894 case Iop_Clz32:
1895 case Iop_Ctz32:
1896 return mkPCastTo(mce, Ity_I32, vatom);
1897
1898 case Iop_32Sto64:
1899 case Iop_32Uto64:
sewardjf0c1c582005-02-07 23:47:38 +00001900 case Iop_V128to64:
1901 case Iop_V128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001902 return assignNew(mce, Ity_I64, unop(op, vatom));
1903
sewardjde8a5ae2004-11-06 14:20:54 +00001904 case Iop_64to32:
1905 case Iop_64HIto32:
1906 case Iop_1Uto32:
1907 case Iop_8Uto32:
1908 case Iop_16Uto32:
1909 case Iop_16Sto32:
1910 case Iop_8Sto32:
1911 return assignNew(mce, Ity_I32, unop(op, vatom));
1912
1913 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001914 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001915 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001916 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001917 return assignNew(mce, Ity_I16, unop(op, vatom));
1918
1919 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001920 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001921 case Iop_32to8:
1922 return assignNew(mce, Ity_I8, unop(op, vatom));
1923
1924 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001925 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001926
sewardj3598ef92004-11-11 02:13:30 +00001927 case Iop_ReinterpF64asI64:
1928 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001929 case Iop_ReinterpI32asF32:
sewardjf0c1c582005-02-07 23:47:38 +00001930 case Iop_NotV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001931 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00001932 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001933 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001934 case Iop_Not8:
1935 case Iop_Not1:
1936 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001937
sewardjde8a5ae2004-11-06 14:20:54 +00001938 default:
1939 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001940 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00001941 }
1942}
1943
1944
sewardj69f9e3e2004-12-30 02:05:34 +00001945/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00001946static
sewardj69f9e3e2004-12-30 02:05:34 +00001947IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001948{
1949 void* helper;
sewardjde8c9872005-03-25 13:48:55 +00001950 HChar* hname;
sewardjde8a5ae2004-11-06 14:20:54 +00001951 IRDirty* di;
1952 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00001953 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001954
sewardj69f9e3e2004-12-30 02:05:34 +00001955 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00001956
1957 /* First, emit a definedness test for the address. This also sets
1958 the address (shadow) to 'defined' following the test. */
1959 complainIfUndefined( mce, addr );
1960
1961 /* Now cook up a call to the relevant helper function, to read the
1962 data V bits from shadow memory. */
1963 ty = shadowType(ty);
1964 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001965 case Ity_I64: helper = &MC_(helperc_LOADV8);
1966 hname = "MC_(helperc_LOADV8)";
1967 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001968 case Ity_I32: helper = &MC_(helperc_LOADV4);
1969 hname = "MC_(helperc_LOADV4)";
1970 break;
1971 case Ity_I16: helper = &MC_(helperc_LOADV2);
1972 hname = "MC_(helperc_LOADV2)";
1973 break;
1974 case Ity_I8: helper = &MC_(helperc_LOADV1);
1975 hname = "MC_(helperc_LOADV1)";
1976 break;
1977 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001978 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00001979 }
1980
sewardj3598ef92004-11-11 02:13:30 +00001981 /* Generate the actual address into addrAct. */
1982 if (bias == 0) {
1983 addrAct = addr;
1984 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001985 IROp mkAdd;
1986 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00001987 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00001988 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
1989 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1990 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00001991 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1992 }
1993
sewardjde8a5ae2004-11-06 14:20:54 +00001994 /* We need to have a place to park the V bits we're just about to
1995 read. */
1996 datavbits = newIRTemp(mce->bb->tyenv, ty);
1997 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00001998 1/*regparms*/, hname, helper,
1999 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00002000 setHelperAnns( mce, di );
2001 stmt( mce->bb, IRStmt_Dirty(di) );
2002
2003 return mkexpr(datavbits);
2004}
2005
2006
2007static
sewardj69f9e3e2004-12-30 02:05:34 +00002008IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
2009{
2010 IRAtom *v64hi, *v64lo;
2011 switch (shadowType(ty)) {
2012 case Ity_I8:
2013 case Ity_I16:
2014 case Ity_I32:
2015 case Ity_I64:
2016 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
2017 case Ity_V128:
2018 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
2019 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
2020 return assignNew( mce,
2021 Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +00002022 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj69f9e3e2004-12-30 02:05:34 +00002023 default:
2024 VG_(tool_panic)("expr2vbits_LDle");
2025 }
2026}
2027
2028
2029static
sewardjde8a5ae2004-11-06 14:20:54 +00002030IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00002031 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00002032{
2033 IRAtom *vbitsC, *vbits0, *vbitsX;
2034 IRType ty;
2035 /* Given Mux0X(cond,expr0,exprX), generate
2036 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2037 That is, steer the V bits like the originals, but trash the
2038 result if the steering value is undefined. This gives
2039 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00002040 tl_assert(isOriginalAtom(mce, cond));
2041 tl_assert(isOriginalAtom(mce, expr0));
2042 tl_assert(isOriginalAtom(mce, exprX));
sewardjde8a5ae2004-11-06 14:20:54 +00002043
2044 vbitsC = expr2vbits(mce, cond);
2045 vbits0 = expr2vbits(mce, expr0);
2046 vbitsX = expr2vbits(mce, exprX);
2047 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2048
2049 return
2050 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2051 mkPCastTo(mce, ty, vbitsC) );
2052}
2053
2054/* --------- This is the main expression-handling function. --------- */
2055
2056static
2057IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2058{
2059 switch (e->tag) {
2060
2061 case Iex_Get:
2062 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2063
2064 case Iex_GetI:
2065 return shadow_GETI( mce, e->Iex.GetI.descr,
2066 e->Iex.GetI.ix, e->Iex.GetI.bias );
2067
2068 case Iex_Tmp:
2069 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
2070
2071 case Iex_Const:
2072 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2073
2074 case Iex_Binop:
2075 return expr2vbits_Binop(
2076 mce,
2077 e->Iex.Binop.op,
2078 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2079 );
2080
2081 case Iex_Unop:
2082 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2083
2084 case Iex_LDle:
sewardj3598ef92004-11-11 02:13:30 +00002085 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
2086 e->Iex.LDle.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002087
2088 case Iex_CCall:
2089 return mkLazyN( mce, e->Iex.CCall.args,
2090 e->Iex.CCall.retty,
2091 e->Iex.CCall.cee );
2092
2093 case Iex_Mux0X:
2094 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2095 e->Iex.Mux0X.exprX);
2096
2097 default:
2098 VG_(printf)("\n");
2099 ppIRExpr(e);
2100 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002101 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002102 }
2103}
2104
2105/*------------------------------------------------------------*/
2106/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2107/*------------------------------------------------------------*/
2108
2109/* Widen a value to the host word size. */
2110
2111static
2112IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2113{
sewardj69f9e3e2004-12-30 02:05:34 +00002114 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002115
sewardj8fc93742004-11-22 11:29:33 +00002116 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002117 tl_assert(isShadowAtom(mce,vatom));
2118
2119 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2120 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002121
sewardjde8a5ae2004-11-06 14:20:54 +00002122 if (tyH == Ity_I32) {
2123 switch (ty) {
2124 case Ity_I32: return vatom;
2125 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2126 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2127 default: goto unhandled;
2128 }
2129 } else {
2130 goto unhandled;
2131 }
2132 unhandled:
2133 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002134 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002135}
2136
2137
sewardj3598ef92004-11-11 02:13:30 +00002138/* Generate a shadow store. addr is always the original address atom.
2139 You can pass in either originals or V-bits for the data atom, but
2140 obviously not both. */
2141
sewardjde8a5ae2004-11-06 14:20:54 +00002142static
sewardj3598ef92004-11-11 02:13:30 +00002143void do_shadow_STle ( MCEnv* mce,
2144 IRAtom* addr, UInt bias,
2145 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002146{
sewardj69f9e3e2004-12-30 02:05:34 +00002147 IROp mkAdd;
2148 IRType ty, tyAddr;
2149 IRDirty *di, *diLo64, *diHi64;
2150 IRAtom *addrAct, *addrLo64, *addrHi64;
2151 IRAtom *vdataLo64, *vdataHi64;
2152 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002153 void* helper = NULL;
2154 Char* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002155
2156 tyAddr = mce->hWordTy;
2157 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2158 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2159
2160 di = diLo64 = diHi64 = NULL;
2161 eBias = eBias0 = eBias8 = NULL;
2162 addrAct = addrLo64 = addrHi64 = NULL;
2163 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002164
sewardj3598ef92004-11-11 02:13:30 +00002165 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002166 tl_assert(!vdata);
2167 tl_assert(isOriginalAtom(mce, data));
2168 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002169 vdata = expr2vbits( mce, data );
2170 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002171 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002172 }
sewardjde8a5ae2004-11-06 14:20:54 +00002173
sewardj69f9e3e2004-12-30 02:05:34 +00002174 tl_assert(isOriginalAtom(mce,addr));
2175 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002176
2177 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002178
2179 /* First, emit a definedness test for the address. This also sets
2180 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002181 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002182
sewardj69f9e3e2004-12-30 02:05:34 +00002183 /* Now decide which helper function to call to write the data V
2184 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002185 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002186 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002187 case Ity_I64: helper = &MC_(helperc_STOREV8);
2188 hname = "MC_(helperc_STOREV8)";
2189 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002190 case Ity_I32: helper = &MC_(helperc_STOREV4);
2191 hname = "MC_(helperc_STOREV4)";
2192 break;
2193 case Ity_I16: helper = &MC_(helperc_STOREV2);
2194 hname = "MC_(helperc_STOREV2)";
2195 break;
2196 case Ity_I8: helper = &MC_(helperc_STOREV1);
2197 hname = "MC_(helperc_STOREV1)";
2198 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002199 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002200 }
2201
sewardj69f9e3e2004-12-30 02:05:34 +00002202 if (ty == Ity_V128) {
2203
sewardjf0c1c582005-02-07 23:47:38 +00002204 /* V128-bit case */
sewardj69f9e3e2004-12-30 02:05:34 +00002205 /* See comment in next clause re 64-bit regparms */
2206 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2207 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
sewardjf0c1c582005-02-07 23:47:38 +00002208 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002209 diLo64 = unsafeIRDirty_0_N(
2210 1/*regparms*/, hname, helper,
2211 mkIRExprVec_2( addrLo64, vdataLo64 ));
2212
2213 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2214 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
sewardjf0c1c582005-02-07 23:47:38 +00002215 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002216 diHi64 = unsafeIRDirty_0_N(
2217 1/*regparms*/, hname, helper,
2218 mkIRExprVec_2( addrHi64, vdataHi64 ));
2219
2220 setHelperAnns( mce, diLo64 );
2221 setHelperAnns( mce, diHi64 );
2222 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2223 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2224
sewardj3598ef92004-11-11 02:13:30 +00002225 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002226
2227 /* 8/16/32/64-bit cases */
2228 /* Generate the actual address into addrAct. */
2229 if (bias == 0) {
2230 addrAct = addr;
2231 } else {
2232 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2233 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2234 }
2235
2236 if (ty == Ity_I64) {
2237 /* We can't do this with regparm 2 on 32-bit platforms, since
2238 the back ends aren't clever enough to handle 64-bit
2239 regparm args. Therefore be different. */
2240 di = unsafeIRDirty_0_N(
2241 1/*regparms*/, hname, helper,
2242 mkIRExprVec_2( addrAct, vdata ));
2243 } else {
2244 di = unsafeIRDirty_0_N(
2245 2/*regparms*/, hname, helper,
2246 mkIRExprVec_2( addrAct,
2247 zwidenToHostWord( mce, vdata )));
2248 }
2249 setHelperAnns( mce, di );
2250 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002251 }
2252
sewardjde8a5ae2004-11-06 14:20:54 +00002253}
2254
2255
sewardj3598ef92004-11-11 02:13:30 +00002256/* Do lazy pessimistic propagation through a dirty helper call, by
2257 looking at the annotations on it. This is the most complex part of
2258 Memcheck. */
2259
2260static IRType szToITy ( Int n )
2261{
2262 switch (n) {
2263 case 1: return Ity_I8;
2264 case 2: return Ity_I16;
2265 case 4: return Ity_I32;
2266 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002267 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002268 }
2269}
2270
2271static
2272void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2273{
sewardj69f9e3e2004-12-30 02:05:34 +00002274 Int i, n, offset, toDo, gSz, gOff;
2275 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002276 IRType tyAddr, tySrc, tyDst;
2277 IRTemp dst;
2278
2279 /* First check the guard. */
2280 complainIfUndefined(mce, d->guard);
2281
2282 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002283 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002284
2285 /* Inputs: unmasked args */
2286 for (i = 0; d->args[i]; i++) {
2287 if (d->cee->mcx_mask & (1<<i)) {
2288 /* ignore this arg */
2289 } else {
2290 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2291 curr = mkUifU32(mce, here, curr);
2292 }
2293 }
2294
2295 /* Inputs: guest state that we read. */
2296 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002297 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002298 if (d->fxState[i].fx == Ifx_Write)
2299 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002300
2301 /* Ignore any sections marked as 'always defined'. */
2302 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2303 if (0)
2304 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2305 d->fxState[i].offset, d->fxState[i].size );
2306 continue;
2307 }
2308
sewardj3598ef92004-11-11 02:13:30 +00002309 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002310 consider it. If larger than 8 bytes, deal with it in 8-byte
2311 chunks. */
2312 gSz = d->fxState[i].size;
2313 gOff = d->fxState[i].offset;
2314 tl_assert(gSz > 0);
2315 while (True) {
2316 if (gSz == 0) break;
2317 n = gSz <= 8 ? gSz : 8;
2318 /* update 'curr' with UifU of the state slice
2319 gOff .. gOff+n-1 */
2320 tySrc = szToITy( n );
2321 src = assignNew( mce, tySrc,
2322 shadow_GET(mce, gOff, tySrc ) );
2323 here = mkPCastTo( mce, Ity_I32, src );
2324 curr = mkUifU32(mce, here, curr);
2325 gSz -= n;
2326 gOff += n;
2327 }
2328
sewardj3598ef92004-11-11 02:13:30 +00002329 }
2330
2331 /* Inputs: memory. First set up some info needed regardless of
2332 whether we're doing reads or writes. */
2333 tyAddr = Ity_INVALID;
2334
2335 if (d->mFx != Ifx_None) {
2336 /* Because we may do multiple shadow loads/stores from the same
2337 base address, it's best to do a single test of its
2338 definedness right now. Post-instrumentation optimisation
2339 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002340 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002341 complainIfUndefined(mce, d->mAddr);
2342
2343 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002344 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2345 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002346 }
2347
2348 /* Deal with memory inputs (reads or modifies) */
2349 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2350 offset = 0;
2351 toDo = d->mSize;
2352 /* chew off 32-bit chunks */
2353 while (toDo >= 4) {
2354 here = mkPCastTo(
2355 mce, Ity_I32,
2356 expr2vbits_LDle ( mce, Ity_I32,
2357 d->mAddr, d->mSize - toDo )
2358 );
2359 curr = mkUifU32(mce, here, curr);
2360 toDo -= 4;
2361 }
2362 /* chew off 16-bit chunks */
2363 while (toDo >= 2) {
2364 here = mkPCastTo(
2365 mce, Ity_I32,
2366 expr2vbits_LDle ( mce, Ity_I16,
2367 d->mAddr, d->mSize - toDo )
2368 );
2369 curr = mkUifU32(mce, here, curr);
2370 toDo -= 2;
2371 }
sewardj69f9e3e2004-12-30 02:05:34 +00002372 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002373 }
2374
2375 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2376 all the inputs to the helper. Now we need to re-distribute the
2377 results to all destinations. */
2378
2379 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002380 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002381 dst = findShadowTmp(mce, d->tmp);
2382 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2383 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2384 }
2385
2386 /* Outputs: guest state that we write or modify. */
2387 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002388 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002389 if (d->fxState[i].fx == Ifx_Read)
2390 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002391 /* Ignore any sections marked as 'always defined'. */
2392 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2393 continue;
2394 /* This state element is written or modified. So we need to
2395 consider it. If larger than 8 bytes, deal with it in 8-byte
2396 chunks. */
2397 gSz = d->fxState[i].size;
2398 gOff = d->fxState[i].offset;
2399 tl_assert(gSz > 0);
2400 while (True) {
2401 if (gSz == 0) break;
2402 n = gSz <= 8 ? gSz : 8;
2403 /* Write suitably-casted 'curr' to the state slice
2404 gOff .. gOff+n-1 */
2405 tyDst = szToITy( n );
2406 do_shadow_PUT( mce, gOff,
2407 NULL, /* original atom */
2408 mkPCastTo( mce, tyDst, curr ) );
2409 gSz -= n;
2410 gOff += n;
2411 }
sewardj3598ef92004-11-11 02:13:30 +00002412 }
2413
2414 /* Outputs: memory that we write or modify. */
2415 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2416 offset = 0;
2417 toDo = d->mSize;
2418 /* chew off 32-bit chunks */
2419 while (toDo >= 4) {
2420 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2421 NULL, /* original data */
2422 mkPCastTo( mce, Ity_I32, curr ) );
2423 toDo -= 4;
2424 }
2425 /* chew off 16-bit chunks */
2426 while (toDo >= 2) {
2427 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2428 NULL, /* original data */
2429 mkPCastTo( mce, Ity_I16, curr ) );
2430 toDo -= 2;
2431 }
sewardj69f9e3e2004-12-30 02:05:34 +00002432 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002433 }
2434
2435}
2436
2437
sewardjde8a5ae2004-11-06 14:20:54 +00002438/*------------------------------------------------------------*/
2439/*--- Memcheck main ---*/
2440/*------------------------------------------------------------*/
2441
sewardj3598ef92004-11-11 02:13:30 +00002442static Bool isBogusAtom ( IRAtom* at )
2443{
2444 ULong n = 0;
2445 IRConst* con;
sewardj496a58d2005-03-20 18:44:44 +00002446 tl_assert(isIRAtom(at));
sewardj3598ef92004-11-11 02:13:30 +00002447 if (at->tag == Iex_Tmp)
2448 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002449 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002450 con = at->Iex.Const.con;
2451 switch (con->tag) {
2452 case Ico_U8: n = (ULong)con->Ico.U8; break;
2453 case Ico_U16: n = (ULong)con->Ico.U16; break;
2454 case Ico_U32: n = (ULong)con->Ico.U32; break;
2455 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002456 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002457 }
2458 /* VG_(printf)("%llx\n", n); */
2459 return (n == 0xFEFEFEFF
2460 || n == 0x80808080
2461 || n == 0x1010101
2462 || n == 1010100);
2463}
2464
2465static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2466{
2467 Int i;
2468 IRExpr* e;
2469 switch (st->tag) {
2470 case Ist_Tmp:
2471 e = st->Ist.Tmp.data;
2472 switch (e->tag) {
2473 case Iex_Get:
2474 case Iex_Tmp:
2475 return False;
2476 case Iex_Unop:
2477 return isBogusAtom(e->Iex.Unop.arg);
2478 case Iex_Binop:
2479 return isBogusAtom(e->Iex.Binop.arg1)
2480 || isBogusAtom(e->Iex.Binop.arg2);
2481 case Iex_Mux0X:
2482 return isBogusAtom(e->Iex.Mux0X.cond)
2483 || isBogusAtom(e->Iex.Mux0X.expr0)
2484 || isBogusAtom(e->Iex.Mux0X.exprX);
2485 case Iex_LDle:
2486 return isBogusAtom(e->Iex.LDle.addr);
2487 case Iex_CCall:
2488 for (i = 0; e->Iex.CCall.args[i]; i++)
2489 if (isBogusAtom(e->Iex.CCall.args[i]))
2490 return True;
2491 return False;
2492 default:
2493 goto unhandled;
2494 }
2495 case Ist_Put:
2496 return isBogusAtom(st->Ist.Put.data);
2497 case Ist_STle:
2498 return isBogusAtom(st->Ist.STle.addr)
2499 || isBogusAtom(st->Ist.STle.data);
2500 case Ist_Exit:
sewardj1ea1b612005-03-26 13:02:20 +00002501 return isBogusAtom(st->Ist.Exit.guard);
sewardj3598ef92004-11-11 02:13:30 +00002502 default:
2503 unhandled:
2504 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002505 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002506 }
2507}
sewardj3598ef92004-11-11 02:13:30 +00002508
sewardj1ea1b612005-03-26 13:02:20 +00002509IRBB* mc_instrument ( IRBB* bb_in, VexGuestLayout* layout,
2510 IRType gWordTy, IRType hWordTy )
sewardjde8a5ae2004-11-06 14:20:54 +00002511{
sewardj3598ef92004-11-11 02:13:30 +00002512 Bool verboze = False; //True;
2513
2514 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002515
2516 Int i, j, first_stmt;
2517 IRStmt* st;
2518 MCEnv mce;
2519
2520 /* Set up BB */
2521 IRBB* bb = emptyIRBB();
2522 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
2523 bb->next = dopyIRExpr(bb_in->next);
2524 bb->jumpkind = bb_in->jumpkind;
2525
2526 /* Set up the running environment. Only .bb is modified as we go
2527 along. */
2528 mce.bb = bb;
2529 mce.layout = layout;
2530 mce.n_originalTmps = bb->tyenv->types_used;
2531 mce.hWordTy = hWordTy;
2532 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2533 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002534 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002535
2536 /* Iterate over the stmts. */
2537
2538 for (i = 0; i < bb_in->stmts_used; i++) {
2539 st = bb_in->stmts[i];
2540 if (!st) continue;
2541
sewardj69f9e3e2004-12-30 02:05:34 +00002542 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002543
2544 /*
2545 if (!hasBogusLiterals) {
2546 hasBogusLiterals = checkForBogusLiterals(st);
2547 if (hasBogusLiterals) {
2548 VG_(printf)("bogus: ");
2549 ppIRStmt(st);
2550 VG_(printf)("\n");
2551 }
2552 }
2553 */
sewardjde8a5ae2004-11-06 14:20:54 +00002554 first_stmt = bb->stmts_used;
2555
2556 if (verboze) {
2557 ppIRStmt(st);
2558 VG_(printf)("\n\n");
2559 }
2560
2561 switch (st->tag) {
2562
2563 case Ist_Tmp:
2564 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
2565 expr2vbits( &mce, st->Ist.Tmp.data) );
2566 break;
2567
2568 case Ist_Put:
2569 do_shadow_PUT( &mce,
2570 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002571 st->Ist.Put.data,
2572 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002573 break;
2574
2575 case Ist_PutI:
2576 do_shadow_PUTI( &mce,
2577 st->Ist.PutI.descr,
2578 st->Ist.PutI.ix,
2579 st->Ist.PutI.bias,
2580 st->Ist.PutI.data );
2581 break;
2582
2583 case Ist_STle:
sewardj3598ef92004-11-11 02:13:30 +00002584 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
2585 st->Ist.STle.data,
2586 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002587 break;
2588
2589 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002590 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002591 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002592 break;
2593
2594 case Ist_Dirty:
2595 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002596 break;
2597
sewardj1ea1b612005-03-26 13:02:20 +00002598 case Ist_IMark:
2599 case Ist_NoOp:
2600 break;
2601
sewardjde8a5ae2004-11-06 14:20:54 +00002602 default:
2603 VG_(printf)("\n");
2604 ppIRStmt(st);
2605 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002606 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002607
2608 } /* switch (st->tag) */
2609
2610 if (verboze) {
2611 for (j = first_stmt; j < bb->stmts_used; j++) {
2612 VG_(printf)(" ");
2613 ppIRStmt(bb->stmts[j]);
2614 VG_(printf)("\n");
2615 }
2616 VG_(printf)("\n");
2617 }
2618
2619 addStmtToIRBB(bb, st);
2620
2621 }
2622
2623 /* Now we need to complain if the jump target is undefined. */
2624 first_stmt = bb->stmts_used;
2625
2626 if (verboze) {
2627 VG_(printf)("bb->next = ");
2628 ppIRExpr(bb->next);
2629 VG_(printf)("\n\n");
2630 }
2631
2632 complainIfUndefined( &mce, bb->next );
2633
2634 if (verboze) {
2635 for (j = first_stmt; j < bb->stmts_used; j++) {
2636 VG_(printf)(" ");
2637 ppIRStmt(bb->stmts[j]);
2638 VG_(printf)("\n");
2639 }
2640 VG_(printf)("\n");
2641 }
2642
2643 return bb;
2644}
cerionaee45242005-03-17 14:03:36 +00002645#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002646
2647/*--------------------------------------------------------------------*/
2648/*--- end mc_translate.c ---*/
2649/*--------------------------------------------------------------------*/