blob: 0680ae43c844ddf0d5608244ef92fe12c4d0ef0f [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;
sewardj17c7f952005-12-15 14:02:34 +000070 VexTranslateArgs vta;
sewardjced9fe52004-07-07 11:55:36 +000071
72 if (argc != 2) {
73 fprintf(stderr, "usage: vex file.org\n");
74 exit(1);
75 }
76 f = fopen(argv[1], "r");
77 if (!f) {
78 fprintf(stderr, "can't open `%s'\n", argv[1]);
79 exit(1);
80 }
81
sewardjb5bf2e02004-10-25 13:06:17 +000082 /* Run with default params. However, we can't allow bb chasing
83 since that causes the front end to get segfaults when it tries
sewardj5bd4d162004-11-10 13:02:48 +000084 to read code outside the initial BB we hand it. So when calling
85 LibVEX_Translate, send in a chase-into predicate that always
86 returns False. */
sewardjb5bf2e02004-10-25 13:06:17 +000087 LibVEX_default_VexControl ( &vcon );
sewardjb4952402004-10-26 13:24:50 +000088 vcon.iropt_level = 2;
sewardjc279b3f2005-03-16 18:10:45 +000089 vcon.guest_max_insns = 50;
sewardjb5bf2e02004-10-25 13:06:17 +000090
sewardjced9fe52004-07-07 11:55:36 +000091 LibVEX_Init ( &failure_exit, &log_bytes,
sewardj1f40a0a2004-07-21 12:28:07 +000092 1, /* debug_paranoia */
sewardjabe017e2004-10-29 23:42:36 +000093 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +000094 &vcon );
sewardjced9fe52004-07-07 11:55:36 +000095
sewardjea64e142004-07-22 16:47:21 +000096
sewardjced9fe52004-07-07 11:55:36 +000097 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +000098
sewardjced9fe52004-07-07 11:55:36 +000099 fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +0000100 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +0000101 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +0000102
103 if (n_bbs_done == TEST_N_BBS) break;
104 n_bbs_done++;
105
sewardjced9fe52004-07-07 11:55:36 +0000106 /* first line is: . bb-number bb-addr n-bytes */
107 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
108 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000109 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000110 assert(orig_nbytes >= 1);
111 assert(!feof(f));
112 fgets(linebuf, N_LINEBUF,f);
113 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000114
sewardjced9fe52004-07-07 11:55:36 +0000115 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000116 if (verbose)
sewardj07a54cc2005-02-04 21:18:55 +0000117 printf("============ Basic Block %d, Done %d, "
sewardj4459baa2004-09-10 20:00:46 +0000118 "Start %x, nbytes %2d ============",
sewardj07a54cc2005-02-04 21:18:55 +0000119 bb_number, n_bbs_done-1, orig_addr, orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000120
sewardjced9fe52004-07-07 11:55:36 +0000121 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
122 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000123 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
124 origbuf[i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000125 }
126
sewardj5117ce12006-01-27 21:20:15 +0000127 /* FIXME: put sensible values into the .hwcaps fields */
sewardj9e6491a2005-07-02 19:24:10 +0000128 LibVEX_default_VexArchInfo(&vai_x86);
sewardj5117ce12006-01-27 21:20:15 +0000129 vai_x86.hwcaps = 0;
sewardj9e6491a2005-07-02 19:24:10 +0000130
131 LibVEX_default_VexArchInfo(&vai_amd64);
sewardj5117ce12006-01-27 21:20:15 +0000132 vai_amd64.hwcaps = 0;
sewardj9e6491a2005-07-02 19:24:10 +0000133
134 LibVEX_default_VexArchInfo(&vai_ppc32);
sewardj5117ce12006-01-27 21:20:15 +0000135 vai_ppc32.hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000136 vai_ppc32.ppc_cache_line_szB = 128;
sewardj02ef7162005-06-30 12:50:50 +0000137
sewardj17c7f952005-12-15 14:02:34 +0000138 /* ----- Set up args for LibVEX_Translate ----- */
sewardj9e6491a2005-07-02 19:24:10 +0000139#if 1 /* ppc32 -> ppc32 */
sewardj17c7f952005-12-15 14:02:34 +0000140 vta.arch_guest = VexArchPPC32;
141 vta.archinfo_guest = vai_ppc32;
142 vta.arch_host = VexArchPPC32;
143 vta.archinfo_host = vai_ppc32;
sewardj07a54cc2005-02-04 21:18:55 +0000144#endif
sewardjc279b3f2005-03-16 18:10:45 +0000145#if 0 /* amd64 -> amd64 */
sewardj17c7f952005-12-15 14:02:34 +0000146 vta.arch_guest = VexArchAMD64;
147 vta.archinfo_guest = vai_amd64;
148 vta.arch_host = VexArchAMD64;
149 vta.archinfo_host = vai_amd64;
sewardj07a54cc2005-02-04 21:18:55 +0000150#endif
sewardj9e6491a2005-07-02 19:24:10 +0000151#if 0 /* x86 -> x86 */
sewardj17c7f952005-12-15 14:02:34 +0000152 vta.arch_guest = VexArchX86;
153 vta.archinfo_guest = vai_x86;
154 vta.arch_host = VexArchX86;
155 vta.archinfo_host = vai_x86;
sewardjc279b3f2005-03-16 18:10:45 +0000156#endif
sewardj17c7f952005-12-15 14:02:34 +0000157 vta.guest_bytes = origbuf;
158 vta.guest_bytes_addr = (Addr64)orig_addr;
sewardjc716aea2006-01-17 01:48:46 +0000159 vta.callback_opaque = NULL;
sewardj17c7f952005-12-15 14:02:34 +0000160 vta.chase_into_ok = chase_into_not_ok;
161 vta.guest_extents = &vge;
162 vta.host_bytes = transbuf;
163 vta.host_bytes_size = N_TRANSBUF;
164 vta.host_bytes_used = &trans_used;
sewardj9e7448b2004-11-18 13:44:15 +0000165#if 1 /* no instrumentation */
sewardj17c7f952005-12-15 14:02:34 +0000166 vta.instrument1 = NULL;
167 vta.instrument2 = NULL;
sewardj9e7448b2004-11-18 13:44:15 +0000168#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000169#if 0 /* addrcheck */
sewardj17c7f952005-12-15 14:02:34 +0000170 vta.instrument1 = ac_instrument;
171 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000172#endif
sewardj9e7448b2004-11-18 13:44:15 +0000173#if 0 /* memcheck */
sewardj17c7f952005-12-15 14:02:34 +0000174 vta.instrument1 = mc_instrument;
175 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000176#endif
sewardj17c7f952005-12-15 14:02:34 +0000177 vta.do_self_check = False;
sewardjc716aea2006-01-17 01:48:46 +0000178 vta.preamble_function = NULL;
sewardj17c7f952005-12-15 14:02:34 +0000179 vta.traceflags = TEST_FLAGS;
180#if 1 /* x86, amd64 hosts */
181 vta.dispatch = (void*)0x12345678;
182#else /* ppc32, ppc64 hosts */
183 vta.dispatch = NULL;
184#endif
185
186 for (i = 0; i < TEST_N_ITERS; i++)
187 tres = LibVEX_Translate ( &vta );
sewardjabe017e2004-10-29 23:42:36 +0000188
sewardjd887b862005-01-17 18:34:34 +0000189 if (tres != VexTransOK)
sewardj4459baa2004-09-10 20:00:46 +0000190 printf("\ntres = %d\n", (Int)tres);
sewardjd887b862005-01-17 18:34:34 +0000191 assert(tres == VexTransOK);
sewardj72c72812005-01-19 11:49:45 +0000192 assert(vge.n_used == 1);
193 assert((UInt)(vge.len[0]) == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000194
sewardj4459baa2004-09-10 20:00:46 +0000195 sum = 0;
196 for (i = 0; i < trans_used; i++)
197 sum += (UInt)transbuf[i];
sewardjde8c9872005-03-25 13:48:55 +0000198 printf ( " %6.2f ... %u\n",
199 (double)trans_used / (double)vge.len[0], sum );
sewardjced9fe52004-07-07 11:55:36 +0000200 }
201
202 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000203 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000204 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000205
sewardjce605f92004-07-05 14:39:15 +0000206 return 0;
207}
sewardj9b1004e2004-10-30 22:25:40 +0000208
209//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000210//////////////////////////////////////////////////////////////////////
211//////////////////////////////////////////////////////////////////////
212//////////////////////////////////////////////////////////////////////
213//////////////////////////////////////////////////////////////////////
214//////////////////////////////////////////////////////////////////////
215//////////////////////////////////////////////////////////////////////
216//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000217
sewardj1ea1b612005-03-26 13:02:20 +0000218#if 0 /* UNUSED */
219
sewardj9b1004e2004-10-30 22:25:40 +0000220static
sewardjde8a5ae2004-11-06 14:20:54 +0000221__attribute((noreturn))
sewardjde8c9872005-03-25 13:48:55 +0000222void panic ( HChar* s )
sewardj9b1004e2004-10-30 22:25:40 +0000223{
224 printf("\npanic: %s\n", s);
225 failure_exit();
226}
227
228static
sewardj9578a8b2004-11-04 19:44:48 +0000229IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000230{
231/* Use this rather than eg. -1 because it's a UInt. */
232#define INVALID_DATA_SIZE 999999
233
234 Int i;
235 Int sz;
236 IRCallee* helper;
237 IRStmt* st;
238 IRExpr* data;
239 IRExpr* addr;
240 Bool needSz;
241
242 /* Set up BB */
243 IRBB* bb = emptyIRBB();
244 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
245 bb->next = dopyIRExpr(bb_in->next);
246 bb->jumpkind = bb_in->jumpkind;
247
248 /* No loads to consider in ->next. */
sewardj496a58d2005-03-20 18:44:44 +0000249 assert(isIRAtom(bb_in->next));
sewardj9b1004e2004-10-30 22:25:40 +0000250
251 for (i = 0; i < bb_in->stmts_used; i++) {
252 st = bb_in->stmts[i];
253 if (!st) continue;
254
255 switch (st->tag) {
256
257 case Ist_Tmp:
258 data = st->Ist.Tmp.data;
259 if (data->tag == Iex_LDle) {
260 addr = data->Iex.LDle.addr;
261 sz = sizeofIRType(data->Iex.LDle.ty);
262 needSz = False;
263 switch (sz) {
264 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000265 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000266 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000267 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000268 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000269 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000270 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000271 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000272 needSz = True; break;
273 }
274 if (needSz) {
275 addStmtToIRBB(
276 bb,
277 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000278 unsafeIRDirty_0_N( helper->regparms,
279 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000280 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
281 ));
282 } else {
283 addStmtToIRBB(
284 bb,
285 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000286 unsafeIRDirty_0_N( helper->regparms,
287 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000288 mkIRExprVec_1(addr) )
289 ));
290 }
291 }
292 break;
293
294 case Ist_STle:
295 data = st->Ist.STle.data;
296 addr = st->Ist.STle.addr;
sewardj496a58d2005-03-20 18:44:44 +0000297 assert(isIRAtom(data));
298 assert(isIRAtom(addr));
sewardj9b1004e2004-10-30 22:25:40 +0000299 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
300 needSz = False;
301 switch (sz) {
302 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000303 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000304 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000305 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000306 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000307 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000308 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000309 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000310 needSz = True; break;
311 }
312 if (needSz) {
313 addStmtToIRBB(
314 bb,
315 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000316 unsafeIRDirty_0_N( helper->regparms,
317 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000318 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
319 ));
320 } else {
321 addStmtToIRBB(
322 bb,
323 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000324 unsafeIRDirty_0_N( helper->regparms,
325 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000326 mkIRExprVec_1(addr) )
327 ));
328 }
329 break;
330
331 case Ist_Put:
sewardj496a58d2005-03-20 18:44:44 +0000332 assert(isIRAtom(st->Ist.Put.data));
sewardj9b1004e2004-10-30 22:25:40 +0000333 break;
334
335 case Ist_PutI:
sewardj496a58d2005-03-20 18:44:44 +0000336 assert(isIRAtom(st->Ist.PutI.ix));
337 assert(isIRAtom(st->Ist.PutI.data));
sewardj9b1004e2004-10-30 22:25:40 +0000338 break;
339
340 case Ist_Exit:
sewardj496a58d2005-03-20 18:44:44 +0000341 assert(isIRAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000342 break;
343
344 case Ist_Dirty:
345 /* If the call doesn't interact with memory, we ain't
346 interested. */
347 if (st->Ist.Dirty.details->mFx == Ifx_None)
348 break;
349 goto unhandled;
350
351 default:
352 unhandled:
353 printf("\n");
354 ppIRStmt(st);
355 printf("\n");
356 panic("addrcheck: unhandled IRStmt");
357 }
358
359 addStmtToIRBB( bb, dopyIRStmt(st));
360 }
361
362 return bb;
363}
cerionaee45242005-03-17 14:03:36 +0000364#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +0000365
366//////////////////////////////////////////////////////////////////////
367//////////////////////////////////////////////////////////////////////
368//////////////////////////////////////////////////////////////////////
369//////////////////////////////////////////////////////////////////////
370//////////////////////////////////////////////////////////////////////
371//////////////////////////////////////////////////////////////////////
372//////////////////////////////////////////////////////////////////////
373//////////////////////////////////////////////////////////////////////
374
sewardj1ea1b612005-03-26 13:02:20 +0000375#if 0 /* UNUSED */
376
sewardj69f9e3e2004-12-30 02:05:34 +0000377#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000378#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000379#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000380#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000381#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000382
cerionaee45242005-03-17 14:03:36 +0000383
sewardjde8c9872005-03-25 13:48:55 +0000384static void MC_helperc_complain_undef ( void );
385static void MC_helperc_LOADV8 ( void );
386static void MC_helperc_LOADV4 ( void );
387static void MC_helperc_LOADV2 ( void );
388static void MC_helperc_LOADV1 ( void );
sewardj1ea1b612005-03-26 13:02:20 +0000389static void MC_helperc_STOREV8( void );
390static void MC_helperc_STOREV4( void );
391static void MC_helperc_STOREV2( void );
392static void MC_helperc_STOREV1( void );
sewardjde8c9872005-03-25 13:48:55 +0000393static void MC_helperc_value_check0_fail( void );
394static void MC_helperc_value_check1_fail( void );
395static void MC_helperc_value_check4_fail( void );
396
397static void MC_helperc_complain_undef ( void ) { }
398static void MC_helperc_LOADV8 ( void ) { }
399static void MC_helperc_LOADV4 ( void ) { }
400static void MC_helperc_LOADV2 ( void ) { }
401static void MC_helperc_LOADV1 ( void ) { }
sewardj1ea1b612005-03-26 13:02:20 +0000402static void MC_helperc_STOREV8( void ) { }
403static void MC_helperc_STOREV4( void ) { }
404static void MC_helperc_STOREV2( void ) { }
405static void MC_helperc_STOREV1( void ) { }
sewardjde8c9872005-03-25 13:48:55 +0000406static void MC_helperc_value_check0_fail( void ) { }
407static void MC_helperc_value_check1_fail( void ) { }
408static void MC_helperc_value_check4_fail( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000409
410
sewardj3598ef92004-11-11 02:13:30 +0000411/*--------------------------------------------------------------------*/
412/*--- Instrument IR to perform memory checking operations. ---*/
413/*--- mc_translate.c ---*/
414/*--------------------------------------------------------------------*/
415
416/*
417 This file is part of MemCheck, a heavyweight Valgrind tool for
418 detecting memory errors.
419
sewardj2d258d82006-06-05 23:26:23 +0000420 Copyright (C) 2000-2006 Julian Seward
sewardj3598ef92004-11-11 02:13:30 +0000421 jseward@acm.org
422
423 This program is free software; you can redistribute it and/or
424 modify it under the terms of the GNU General Public License as
425 published by the Free Software Foundation; either version 2 of the
426 License, or (at your option) any later version.
427
428 This program is distributed in the hope that it will be useful, but
429 WITHOUT ANY WARRANTY; without even the implied warranty of
430 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
431 General Public License for more details.
432
433 You should have received a copy of the GNU General Public License
434 along with this program; if not, write to the Free Software
435 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
436 02111-1307, USA.
437
438 The GNU General Public License is contained in the file COPYING.
439*/
440
441//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000442
443
444/*------------------------------------------------------------*/
445/*--- Forward decls ---*/
446/*------------------------------------------------------------*/
447
448struct _MCEnv;
449
450static IRType shadowType ( IRType ty );
451static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
452
453
454/*------------------------------------------------------------*/
455/*--- Memcheck running state, and tmp management. ---*/
456/*------------------------------------------------------------*/
457
458/* Carries around state during memcheck instrumentation. */
459typedef
460 struct _MCEnv {
461 /* MODIFIED: the bb being constructed. IRStmts are added. */
462 IRBB* bb;
463
464 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
465 original temps to their current their current shadow temp.
466 Initially all entries are IRTemp_INVALID. Entries are added
467 lazily since many original temps are not used due to
468 optimisation prior to instrumentation. Note that floating
469 point original tmps are shadowed by integer tmps of the same
470 size, and Bit-typed original tmps are shadowed by the type
471 Ity_I8. See comment below. */
472 IRTemp* tmpMap;
473 Int n_originalTmps; /* for range checking */
474
475 /* READONLY: the guest layout. This indicates which parts of
476 the guest state should be regarded as 'always defined'. */
477 VexGuestLayout* layout;
478 /* READONLY: the host word type. Needed for constructing
479 arguments of type 'HWord' to be passed to helper functions.
480 Ity_I32 or Ity_I64 only. */
481 IRType hWordTy;
482 }
483 MCEnv;
484
485/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
486 demand), as they are encountered. This is for two reasons.
487
488 (1) (less important reason): Many original tmps are unused due to
489 initial IR optimisation, and we do not want to spaces in tables
490 tracking them.
491
492 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
493 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000494 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000495 It is necessary to support making multiple assignments to a shadow
496 -- specifically, after testing a shadow for definedness, it needs
497 to be made defined. But IR's SSA property disallows this.
498
499 (2) (more important reason): Therefore, when a shadow needs to get
500 a new value, a new temporary is created, the value is assigned to
501 that, and the tmpMap is updated to reflect the new binding.
502
503 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000504 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000505 there's a read-before-write error in the original tmps. The IR
506 sanity checker should catch all such anomalies, however.
507*/
508
509/* Find the tmp currently shadowing the given original tmp. If none
510 so far exists, allocate one. */
511static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
512{
sewardj69f9e3e2004-12-30 02:05:34 +0000513 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000514 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000515 mce->tmpMap[orig]
516 = newIRTemp(mce->bb->tyenv,
517 shadowType(mce->bb->tyenv->types[orig]));
518 }
519 return mce->tmpMap[orig];
520}
521
522/* Allocate a new shadow for the given original tmp. This means any
523 previous shadow is abandoned. This is needed because it is
524 necessary to give a new value to a shadow once it has been tested
525 for undefinedness, but unfortunately IR's SSA property disallows
526 this. Instead we must abandon the old shadow, allocate a new one
527 and use that instead. */
528static void newShadowTmp ( MCEnv* mce, IRTemp orig )
529{
sewardj69f9e3e2004-12-30 02:05:34 +0000530 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000531 mce->tmpMap[orig]
532 = newIRTemp(mce->bb->tyenv,
533 shadowType(mce->bb->tyenv->types[orig]));
534}
535
536
537/*------------------------------------------------------------*/
538/*--- IRAtoms -- a subset of IRExprs ---*/
539/*------------------------------------------------------------*/
540
541/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj496a58d2005-03-20 18:44:44 +0000542 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardjde8a5ae2004-11-06 14:20:54 +0000543 input, most of this code deals in atoms. Usefully, a value atom
544 always has a V-value which is also an atom: constants are shadowed
545 by constants, and temps are shadowed by the corresponding shadow
546 temporary. */
547
548typedef IRExpr IRAtom;
549
550/* (used for sanity checks only): is this an atom which looks
551 like it's from original code? */
552static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
553{
554 if (a1->tag == Iex_Const)
555 return True;
556 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
557 return True;
558 return False;
559}
560
561/* (used for sanity checks only): is this an atom which looks
562 like it's from shadow code? */
563static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
564{
565 if (a1->tag == Iex_Const)
566 return True;
567 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
568 return True;
569 return False;
570}
571
572/* (used for sanity checks only): check that both args are atoms and
573 are identically-kinded. */
574static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
575{
576 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
577 return True;
578 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
579 return True;
580 return False;
581}
582
583
584/*------------------------------------------------------------*/
585/*--- Type management ---*/
586/*------------------------------------------------------------*/
587
588/* Shadow state is always accessed using integer types. This returns
589 an integer type with the same size (as per sizeofIRType) as the
590 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000591 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000592
593static IRType shadowType ( IRType ty )
594{
595 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000596 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000597 case Ity_I8:
598 case Ity_I16:
599 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000600 case Ity_I64: return ty;
601 case Ity_F32: return Ity_I32;
602 case Ity_F64: return Ity_I64;
603 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000604 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000605 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000606 }
607}
608
609/* Produce a 'defined' value of the given shadow type. Should only be
610 supplied shadow types (Bit/I8/I16/I32/UI64). */
611static IRExpr* definedOfType ( IRType ty ) {
612 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000613 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
614 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
615 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
616 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
617 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
618 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
619 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000620 }
621}
622
623
624/*------------------------------------------------------------*/
625/*--- Constructing IR fragments ---*/
626/*------------------------------------------------------------*/
627
628/* assign value to tmp */
629#define assign(_bb,_tmp,_expr) \
630 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
631
632/* add stmt to a bb */
633#define stmt(_bb,_stmt) \
634 addStmtToIRBB((_bb), (_stmt))
635
636/* build various kinds of expressions */
637#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
638#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
639#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
640#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
641#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
642#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000643#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardjde8a5ae2004-11-06 14:20:54 +0000644#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
645
646/* bind the given expression to a new temporary, and return the
647 temporary. This effectively converts an arbitrary expression into
648 an atom. */
649static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
650 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
651 assign(mce->bb, t, e);
652 return mkexpr(t);
653}
654
655
656/*------------------------------------------------------------*/
657/*--- Constructing definedness primitive ops ---*/
658/*------------------------------------------------------------*/
659
660/* --------- Defined-if-either-defined --------- */
661
662static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000663 tl_assert(isShadowAtom(mce,a1));
664 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000665 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
666}
667
668static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000669 tl_assert(isShadowAtom(mce,a1));
670 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000671 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
672}
673
674static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000675 tl_assert(isShadowAtom(mce,a1));
676 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000677 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
678}
679
sewardj69f9e3e2004-12-30 02:05:34 +0000680static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
681 tl_assert(isShadowAtom(mce,a1));
682 tl_assert(isShadowAtom(mce,a2));
683 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
684}
685
sewardjf0c1c582005-02-07 23:47:38 +0000686static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000687 tl_assert(isShadowAtom(mce,a1));
688 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000689 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000690}
691
sewardjde8a5ae2004-11-06 14:20:54 +0000692/* --------- Undefined-if-either-undefined --------- */
693
694static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000695 tl_assert(isShadowAtom(mce,a1));
696 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000697 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
698}
699
700static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000701 tl_assert(isShadowAtom(mce,a1));
702 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000703 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
704}
705
706static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000707 tl_assert(isShadowAtom(mce,a1));
708 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000709 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
710}
711
712static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000713 tl_assert(isShadowAtom(mce,a1));
714 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000715 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
716}
717
sewardjf0c1c582005-02-07 23:47:38 +0000718static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000719 tl_assert(isShadowAtom(mce,a1));
720 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000721 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000722}
723
724static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000725 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000726 case Ity_I8: return mkUifU8(mce, a1, a2);
727 case Ity_I16: return mkUifU16(mce, a1, a2);
728 case Ity_I32: return mkUifU32(mce, a1, a2);
729 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardjf0c1c582005-02-07 23:47:38 +0000730 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000731 default:
732 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000733 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000734 }
735}
736
737/* --------- The Left-family of operations. --------- */
738
739static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000740 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000741 /* It's safe to duplicate a1 since it's only an atom */
742 return assignNew(mce, Ity_I8,
743 binop(Iop_Or8, a1,
744 assignNew(mce, Ity_I8,
745 /* unop(Iop_Neg8, a1)))); */
746 binop(Iop_Sub8, mkU8(0), a1) )));
747}
748
749static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000750 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000751 /* It's safe to duplicate a1 since it's only an atom */
752 return assignNew(mce, Ity_I16,
753 binop(Iop_Or16, a1,
754 assignNew(mce, Ity_I16,
755 /* unop(Iop_Neg16, a1)))); */
756 binop(Iop_Sub16, mkU16(0), a1) )));
757}
758
759static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000760 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000761 /* It's safe to duplicate a1 since it's only an atom */
762 return assignNew(mce, Ity_I32,
763 binop(Iop_Or32, a1,
764 assignNew(mce, Ity_I32,
765 /* unop(Iop_Neg32, a1)))); */
766 binop(Iop_Sub32, mkU32(0), a1) )));
767}
768
769/* --------- 'Improvement' functions for AND/OR. --------- */
770
771/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
772 defined (0); all other -> undefined (1).
773*/
774static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
775{
sewardj69f9e3e2004-12-30 02:05:34 +0000776 tl_assert(isOriginalAtom(mce, data));
777 tl_assert(isShadowAtom(mce, vbits));
778 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000779 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
780}
781
sewardj3598ef92004-11-11 02:13:30 +0000782static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
783{
sewardj69f9e3e2004-12-30 02:05:34 +0000784 tl_assert(isOriginalAtom(mce, data));
785 tl_assert(isShadowAtom(mce, vbits));
786 tl_assert(sameKindedAtoms(data, vbits));
sewardj3598ef92004-11-11 02:13:30 +0000787 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
788}
789
sewardjde8a5ae2004-11-06 14:20:54 +0000790static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
791{
sewardj69f9e3e2004-12-30 02:05:34 +0000792 tl_assert(isOriginalAtom(mce, data));
793 tl_assert(isShadowAtom(mce, vbits));
794 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000795 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
796}
797
sewardj69f9e3e2004-12-30 02:05:34 +0000798static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
799{
800 tl_assert(isOriginalAtom(mce, data));
801 tl_assert(isShadowAtom(mce, vbits));
802 tl_assert(sameKindedAtoms(data, vbits));
803 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
804}
805
sewardjf0c1c582005-02-07 23:47:38 +0000806static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000807{
808 tl_assert(isOriginalAtom(mce, data));
809 tl_assert(isShadowAtom(mce, vbits));
810 tl_assert(sameKindedAtoms(data, vbits));
sewardjf0c1c582005-02-07 23:47:38 +0000811 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj69f9e3e2004-12-30 02:05:34 +0000812}
813
sewardjde8a5ae2004-11-06 14:20:54 +0000814/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
815 defined (0); all other -> undefined (1).
816*/
817static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
818{
sewardj69f9e3e2004-12-30 02:05:34 +0000819 tl_assert(isOriginalAtom(mce, data));
820 tl_assert(isShadowAtom(mce, vbits));
821 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000822 return assignNew(
823 mce, Ity_I8,
824 binop(Iop_Or8,
825 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
826 vbits) );
827}
828
829static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
830{
sewardj69f9e3e2004-12-30 02:05:34 +0000831 tl_assert(isOriginalAtom(mce, data));
832 tl_assert(isShadowAtom(mce, vbits));
833 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000834 return assignNew(
835 mce, Ity_I16,
836 binop(Iop_Or16,
837 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
838 vbits) );
839}
840
841static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
842{
sewardj69f9e3e2004-12-30 02:05:34 +0000843 tl_assert(isOriginalAtom(mce, data));
844 tl_assert(isShadowAtom(mce, vbits));
845 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000846 return assignNew(
847 mce, Ity_I32,
848 binop(Iop_Or32,
849 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
850 vbits) );
851}
852
sewardj69f9e3e2004-12-30 02:05:34 +0000853static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
854{
855 tl_assert(isOriginalAtom(mce, data));
856 tl_assert(isShadowAtom(mce, vbits));
857 tl_assert(sameKindedAtoms(data, vbits));
858 return assignNew(
859 mce, Ity_I64,
860 binop(Iop_Or64,
861 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
862 vbits) );
863}
864
sewardjf0c1c582005-02-07 23:47:38 +0000865static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000866{
867 tl_assert(isOriginalAtom(mce, data));
868 tl_assert(isShadowAtom(mce, vbits));
869 tl_assert(sameKindedAtoms(data, vbits));
870 return assignNew(
871 mce, Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +0000872 binop(Iop_OrV128,
873 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj69f9e3e2004-12-30 02:05:34 +0000874 vbits) );
875}
876
sewardjde8a5ae2004-11-06 14:20:54 +0000877/* --------- Pessimising casts. --------- */
878
879static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
880{
sewardj8fc93742004-11-22 11:29:33 +0000881 IRType ty;
882 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000883 /* Note, dst_ty is a shadow type, not an original type. */
884 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000885 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000886 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
887 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000888 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000889 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000890 tmp1 = vbits;
891 break;
892 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000893 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000894 break;
895 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000896 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000897 break;
898 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000899 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000900 break;
901 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000902 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000903 break;
904 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000905 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000906 }
sewardj69f9e3e2004-12-30 02:05:34 +0000907 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000908 /* Now widen up to the dst type. */
909 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000910 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000911 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000912 case Ity_I8:
913 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000914 case Ity_I16:
915 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
916 case Ity_I32:
917 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
918 case Ity_I64:
919 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000920 case Ity_V128:
921 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardjf0c1c582005-02-07 23:47:38 +0000922 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000923 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000924 default:
925 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000926 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +0000927 }
928}
929
930
931/*------------------------------------------------------------*/
932/*--- Emit a test and complaint if something is undefined. ---*/
933/*------------------------------------------------------------*/
934
935/* Set the annotations on a dirty helper to indicate that the stack
936 pointer and instruction pointers might be read. This is the
937 behaviour of all 'emit-a-complaint' style functions we might
938 call. */
939
940static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
941 di->nFxState = 2;
942 di->fxState[0].fx = Ifx_Read;
943 di->fxState[0].offset = mce->layout->offset_SP;
944 di->fxState[0].size = mce->layout->sizeof_SP;
945 di->fxState[1].fx = Ifx_Read;
946 di->fxState[1].offset = mce->layout->offset_IP;
947 di->fxState[1].size = mce->layout->sizeof_IP;
948}
949
950
951/* Check the supplied **original** atom for undefinedness, and emit a
952 complaint if so. Once that happens, mark it as defined. This is
953 possible because the atom is either a tmp or literal. If it's a
954 tmp, it will be shadowed by a tmp, and so we can set the shadow to
955 be defined. In fact as mentioned above, we will have to allocate a
956 new tmp to carry the new 'defined' shadow value, and update the
957 original->tmp mapping accordingly; we cannot simply assign a new
958 value to an existing shadow tmp as this breaks SSAness -- resulting
959 in the post-instrumentation sanity checker spluttering in disapproval.
960*/
961static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
962{
sewardj8fc93742004-11-22 11:29:33 +0000963 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +0000964 IRType ty;
965 Int sz;
sewardj8fc93742004-11-22 11:29:33 +0000966 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +0000967 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +0000968
sewardjde8a5ae2004-11-06 14:20:54 +0000969 /* Since the original expression is atomic, there's no duplicated
970 work generated by making multiple V-expressions for it. So we
971 don't really care about the possibility that someone else may
972 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +0000973 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +0000974 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +0000975 tl_assert(isShadowAtom(mce, vatom));
976 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +0000977
sewardj8fc93742004-11-22 11:29:33 +0000978 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +0000979
980 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +0000981 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +0000982
sewardj8fc93742004-11-22 11:29:33 +0000983 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +0000984 /* cond will be 0 if all defined, and 1 if any not defined. */
985
sewardj3598ef92004-11-11 02:13:30 +0000986 switch (sz) {
987 case 0:
988 di = unsafeIRDirty_0_N( 0/*regparms*/,
989 "MC_(helperc_value_check0_fail)",
990 &MC_(helperc_value_check0_fail),
991 mkIRExprVec_0()
992 );
993 break;
994 case 1:
995 di = unsafeIRDirty_0_N( 0/*regparms*/,
996 "MC_(helperc_value_check1_fail)",
997 &MC_(helperc_value_check1_fail),
998 mkIRExprVec_0()
999 );
1000 break;
1001 case 4:
1002 di = unsafeIRDirty_0_N( 0/*regparms*/,
1003 "MC_(helperc_value_check4_fail)",
1004 &MC_(helperc_value_check4_fail),
1005 mkIRExprVec_0()
1006 );
1007 break;
1008 default:
1009 di = unsafeIRDirty_0_N( 1/*regparms*/,
1010 "MC_(helperc_complain_undef)",
1011 &MC_(helperc_complain_undef),
1012 mkIRExprVec_1( mkIRExpr_HWord( sz ))
1013 );
1014 break;
1015 }
sewardjde8a5ae2004-11-06 14:20:54 +00001016 di->guard = cond;
1017 setHelperAnns( mce, di );
1018 stmt( mce->bb, IRStmt_Dirty(di));
1019
1020 /* Set the shadow tmp to be defined. First, update the
1021 orig->shadow tmp mapping to reflect the fact that this shadow is
1022 getting a new value. */
sewardj496a58d2005-03-20 18:44:44 +00001023 tl_assert(isIRAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001024 /* sameKindedAtoms ... */
1025 if (vatom->tag == Iex_Tmp) {
sewardj69f9e3e2004-12-30 02:05:34 +00001026 tl_assert(atom->tag == Iex_Tmp);
sewardjde8a5ae2004-11-06 14:20:54 +00001027 newShadowTmp(mce, atom->Iex.Tmp.tmp);
1028 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
1029 definedOfType(ty));
1030 }
1031}
1032
1033
1034/*------------------------------------------------------------*/
1035/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
1036/*------------------------------------------------------------*/
1037
1038/* Examine the always-defined sections declared in layout to see if
1039 the (offset,size) section is within one. Note, is is an error to
1040 partially fall into such a region: (offset,size) should either be
1041 completely in such a region or completely not-in such a region.
1042*/
1043static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1044{
1045 Int minoffD, maxoffD, i;
1046 Int minoff = offset;
1047 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001048 tl_assert((minoff & ~0xFFFF) == 0);
1049 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001050
1051 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1052 minoffD = mce->layout->alwaysDefd[i].offset;
1053 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001054 tl_assert((minoffD & ~0xFFFF) == 0);
1055 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001056
1057 if (maxoff < minoffD || maxoffD < minoff)
1058 continue; /* no overlap */
1059 if (minoff >= minoffD && maxoff <= maxoffD)
1060 return True; /* completely contained in an always-defd section */
1061
sewardj69f9e3e2004-12-30 02:05:34 +00001062 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001063 }
1064 return False; /* could not find any containing section */
1065}
1066
1067
1068/* Generate into bb suitable actions to shadow this Put. If the state
1069 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001070 supplied V bits to the shadow state. We can pass in either an
1071 original atom or a V-atom, but not both. In the former case the
1072 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001073*/
1074static
sewardj3598ef92004-11-11 02:13:30 +00001075void do_shadow_PUT ( MCEnv* mce, Int offset,
1076 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001077{
sewardj8fc93742004-11-22 11:29:33 +00001078 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001079 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001080 tl_assert(!vatom);
1081 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001082 vatom = expr2vbits( mce, atom );
1083 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001084 tl_assert(vatom);
1085 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001086 }
1087
sewardj8fc93742004-11-22 11:29:33 +00001088 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001089 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001090 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1091 /* later: no ... */
1092 /* emit code to emit a complaint if any of the vbits are 1. */
1093 /* complainIfUndefined(mce, atom); */
1094 } else {
1095 /* Do a plain shadow Put. */
1096 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1097 }
1098}
1099
1100
1101/* Return an expression which contains the V bits corresponding to the
1102 given GETI (passed in in pieces).
1103*/
1104static
1105void do_shadow_PUTI ( MCEnv* mce,
1106 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
1107{
sewardj8fc93742004-11-22 11:29:33 +00001108 IRAtom* vatom;
1109 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001110 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001111
sewardj69f9e3e2004-12-30 02:05:34 +00001112 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001113 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001114 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001115 ty = descr->elemTy;
1116 tyS = shadowType(ty);
1117 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001118 tl_assert(ty != Ity_I1);
1119 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001120 complainIfUndefined(mce,ix);
1121 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1122 /* later: no ... */
1123 /* emit code to emit a complaint if any of the vbits are 1. */
1124 /* complainIfUndefined(mce, atom); */
1125 } else {
1126 /* Do a cloned version of the Put that refers to the shadow
1127 area. */
1128 IRArray* new_descr
1129 = mkIRArray( descr->base + mce->layout->total_sizeB,
1130 tyS, descr->nElems);
1131 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1132 }
1133}
1134
1135
1136/* Return an expression which contains the V bits corresponding to the
1137 given GET (passed in in pieces).
1138*/
1139static
1140IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1141{
1142 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001143 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001144 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1145 /* Always defined, return all zeroes of the relevant type */
1146 return definedOfType(tyS);
1147 } else {
1148 /* return a cloned version of the Get that refers to the shadow
1149 area. */
1150 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1151 }
1152}
1153
1154
1155/* Return an expression which contains the V bits corresponding to the
1156 given GETI (passed in in pieces).
1157*/
1158static
1159IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
1160{
1161 IRType ty = descr->elemTy;
1162 IRType tyS = shadowType(ty);
1163 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001164 tl_assert(ty != Ity_I1);
1165 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001166 complainIfUndefined(mce,ix);
1167 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1168 /* Always defined, return all zeroes of the relevant type */
1169 return definedOfType(tyS);
1170 } else {
1171 /* return a cloned version of the Get that refers to the shadow
1172 area. */
1173 IRArray* new_descr
1174 = mkIRArray( descr->base + mce->layout->total_sizeB,
1175 tyS, descr->nElems);
1176 return IRExpr_GetI( new_descr, ix, bias );
1177 }
1178}
1179
1180
1181/*------------------------------------------------------------*/
1182/*--- Generating approximations for unknown operations, ---*/
1183/*--- using lazy-propagate semantics ---*/
1184/*------------------------------------------------------------*/
1185
1186/* Lazy propagation of undefinedness from two values, resulting in the
1187 specified shadow type.
1188*/
1189static
1190IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1191{
1192 /* force everything via 32-bit intermediaries. */
1193 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001194 tl_assert(isShadowAtom(mce,va1));
1195 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001196 at = mkPCastTo(mce, Ity_I32, va1);
1197 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1198 at = mkPCastTo(mce, finalVty, at);
1199 return at;
1200}
1201
1202
1203/* Do the lazy propagation game from a null-terminated vector of
1204 atoms. This is presumably the arguments to a helper call, so the
1205 IRCallee info is also supplied in order that we can know which
1206 arguments should be ignored (via the .mcx_mask field).
1207*/
1208static
1209IRAtom* mkLazyN ( MCEnv* mce,
1210 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1211{
1212 Int i;
1213 IRAtom* here;
1214 IRAtom* curr = definedOfType(Ity_I32);
1215 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001216 tl_assert(i < 32);
1217 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001218 /* Only take notice of this arg if the callee's mc-exclusion
1219 mask does not say it is to be excluded. */
1220 if (cee->mcx_mask & (1<<i)) {
1221 /* the arg is to be excluded from definedness checking. Do
1222 nothing. */
1223 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1224 } else {
1225 /* calculate the arg's definedness, and pessimistically merge
1226 it in. */
1227 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1228 curr = mkUifU32(mce, here, curr);
1229 }
1230 }
1231 return mkPCastTo(mce, finalVtype, curr );
1232}
1233
1234
1235/*------------------------------------------------------------*/
1236/*--- Generating expensive sequences for exact carry-chain ---*/
1237/*--- propagation in add/sub and related operations. ---*/
1238/*------------------------------------------------------------*/
1239
1240static
1241IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1242 IRAtom* aa, IRAtom* bb )
1243{
sewardj69f9e3e2004-12-30 02:05:34 +00001244 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001245 IRType ty;
1246 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001247
sewardj69f9e3e2004-12-30 02:05:34 +00001248 tl_assert(isShadowAtom(mce,qaa));
1249 tl_assert(isShadowAtom(mce,qbb));
1250 tl_assert(isOriginalAtom(mce,aa));
1251 tl_assert(isOriginalAtom(mce,bb));
1252 tl_assert(sameKindedAtoms(qaa,aa));
1253 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001254
sewardj8fc93742004-11-22 11:29:33 +00001255 ty = Ity_I32;
1256 opAND = Iop_And32;
1257 opOR = Iop_Or32;
1258 opXOR = Iop_Xor32;
1259 opNOT = Iop_Not32;
1260 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001261
1262 // a_min = aa & ~qaa
1263 a_min = assignNew(mce,ty,
1264 binop(opAND, aa,
1265 assignNew(mce,ty, unop(opNOT, qaa))));
1266
1267 // b_min = bb & ~qbb
1268 b_min = assignNew(mce,ty,
1269 binop(opAND, bb,
1270 assignNew(mce,ty, unop(opNOT, qbb))));
1271
1272 // a_max = aa | qaa
1273 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1274
1275 // b_max = bb | qbb
1276 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1277
1278 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1279 return
1280 assignNew(mce,ty,
1281 binop( opOR,
1282 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1283 assignNew(mce,ty,
1284 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1285 assignNew(mce,ty, binop(opADD, a_max, b_max))
1286 )
1287 )
1288 )
1289 );
1290}
1291
1292
1293/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001294/*--- Helpers for dealing with vector primops. ---*/
1295/*------------------------------------------------------------*/
1296
1297/* Vector pessimisation -- pessimise within each lane individually. */
1298
1299static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1300{
1301 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1302}
1303
1304static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1305{
1306 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1307}
1308
1309static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1310{
1311 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1312}
1313
1314static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1315{
1316 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1317}
1318
1319
1320/* Here's a simple scheme capable of handling ops derived from SSE1
1321 code and while only generating ops that can be efficiently
1322 implemented in SSE1. */
1323
1324/* All-lanes versions are straightforward:
1325
sewardjf0c1c582005-02-07 23:47:38 +00001326 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj69f9e3e2004-12-30 02:05:34 +00001327
1328 unary32Fx4(x,y) ==> PCast32x4(x#)
1329
1330 Lowest-lane-only versions are more complex:
1331
sewardjf0c1c582005-02-07 23:47:38 +00001332 binary32F0x4(x,y) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001333 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001334 PCast32(V128to32(UifUV128(x#,y#)))
sewardj69f9e3e2004-12-30 02:05:34 +00001335 )
1336
1337 This is perhaps not so obvious. In particular, it's faster to
sewardjf0c1c582005-02-07 23:47:38 +00001338 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj69f9e3e2004-12-30 02:05:34 +00001339 obvious scheme of taking the bottom 32 bits of each operand
1340 and doing a 32-bit UifU. Basically since UifU is fast and
1341 chopping lanes off vector values is slow.
1342
1343 Finally:
1344
sewardjf0c1c582005-02-07 23:47:38 +00001345 unary32F0x4(x) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001346 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001347 PCast32(V128to32(x#))
sewardj69f9e3e2004-12-30 02:05:34 +00001348 )
1349
1350 Where:
1351
1352 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1353 PCast32x4(v#) = CmpNEZ32x4(v#)
1354*/
1355
1356static
1357IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1358{
1359 IRAtom* at;
1360 tl_assert(isShadowAtom(mce, vatomX));
1361 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001362 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001363 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1364 return at;
1365}
1366
1367static
1368IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1369{
1370 IRAtom* at;
1371 tl_assert(isShadowAtom(mce, vatomX));
1372 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1373 return at;
1374}
1375
1376static
1377IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1378{
1379 IRAtom* at;
1380 tl_assert(isShadowAtom(mce, vatomX));
1381 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001382 at = mkUifUV128(mce, vatomX, vatomY);
1383 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001384 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001385 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001386 return at;
1387}
1388
1389static
1390IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1391{
1392 IRAtom* at;
1393 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001394 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001395 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001396 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001397 return at;
1398}
1399
1400/* --- ... and ... 64Fx2 versions of the same ... --- */
1401
1402static
1403IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1404{
1405 IRAtom* at;
1406 tl_assert(isShadowAtom(mce, vatomX));
1407 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001408 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001409 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1410 return at;
1411}
1412
1413static
1414IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1415{
1416 IRAtom* at;
1417 tl_assert(isShadowAtom(mce, vatomX));
1418 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1419 return at;
1420}
1421
1422static
1423IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1424{
1425 IRAtom* at;
1426 tl_assert(isShadowAtom(mce, vatomX));
1427 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001428 at = mkUifUV128(mce, vatomX, vatomY);
1429 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001430 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001431 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001432 return at;
1433}
1434
1435static
1436IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1437{
1438 IRAtom* at;
1439 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001440 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001441 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001442 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001443 return at;
1444}
1445
1446/* --- --- Vector saturated narrowing --- --- */
1447
1448/* This is quite subtle. What to do is simple:
1449
1450 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1451
1452 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1453
1454 Why this is right is not so simple. Consider a lane in the args,
1455 vatom1 or 2, doesn't matter.
1456
1457 After the PCast, that lane is all 0s (defined) or all
1458 1s(undefined).
1459
1460 Both signed and unsigned saturating narrowing of all 0s produces
1461 all 0s, which is what we want.
1462
1463 The all-1s case is more complex. Unsigned narrowing interprets an
1464 all-1s input as the largest unsigned integer, and so produces all
1465 1s as a result since that is the largest unsigned value at the
1466 smaller width.
1467
1468 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1469 to -1, so we still wind up with all 1s at the smaller width.
1470
1471 So: In short, pessimise the args, then apply the original narrowing
1472 op.
1473*/
1474static
sewardjf0c1c582005-02-07 23:47:38 +00001475IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardj69f9e3e2004-12-30 02:05:34 +00001476 IRAtom* vatom1, IRAtom* vatom2)
1477{
1478 IRAtom *at1, *at2, *at3;
1479 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1480 switch (narrow_op) {
1481 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1482 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1483 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardjf0c1c582005-02-07 23:47:38 +00001484 default: VG_(tool_panic)("vectorNarrowV128");
sewardj69f9e3e2004-12-30 02:05:34 +00001485 }
1486 tl_assert(isShadowAtom(mce,vatom1));
1487 tl_assert(isShadowAtom(mce,vatom2));
1488 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1489 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1490 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1491 return at3;
1492}
1493
1494
1495/* --- --- Vector integer arithmetic --- --- */
1496
1497/* Simple ... UifU the args and per-lane pessimise the results. */
1498static
1499IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1500{
1501 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001502 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001503 at = mkPCast8x16(mce, at);
1504 return at;
1505}
1506
1507static
1508IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1509{
1510 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001511 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001512 at = mkPCast16x8(mce, at);
1513 return at;
1514}
1515
1516static
1517IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1518{
1519 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001520 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001521 at = mkPCast32x4(mce, at);
1522 return at;
1523}
1524
1525static
1526IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1527{
1528 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001529 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001530 at = mkPCast64x2(mce, at);
1531 return at;
1532}
1533
1534
1535/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001536/*--- Generate shadow values from all kinds of IRExprs. ---*/
1537/*------------------------------------------------------------*/
1538
1539static
1540IRAtom* expr2vbits_Binop ( MCEnv* mce,
1541 IROp op,
1542 IRAtom* atom1, IRAtom* atom2 )
1543{
1544 IRType and_or_ty;
1545 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1546 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1547 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1548
1549 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1550 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1551
sewardj69f9e3e2004-12-30 02:05:34 +00001552 tl_assert(isOriginalAtom(mce,atom1));
1553 tl_assert(isOriginalAtom(mce,atom2));
1554 tl_assert(isShadowAtom(mce,vatom1));
1555 tl_assert(isShadowAtom(mce,vatom2));
1556 tl_assert(sameKindedAtoms(atom1,vatom1));
1557 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001558 switch (op) {
1559
sewardjf0c1c582005-02-07 23:47:38 +00001560 /* V128-bit SIMD (SSE2-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001561
1562 case Iop_ShrN16x8:
1563 case Iop_ShrN32x4:
1564 case Iop_ShrN64x2:
1565 case Iop_SarN16x8:
1566 case Iop_SarN32x4:
1567 case Iop_ShlN16x8:
1568 case Iop_ShlN32x4:
1569 case Iop_ShlN64x2:
1570 /* Same scheme as with all other shifts. */
1571 complainIfUndefined(mce, atom2);
1572 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1573
1574 case Iop_QSub8Ux16:
1575 case Iop_QSub8Sx16:
1576 case Iop_Sub8x16:
1577 case Iop_Min8Ux16:
1578 case Iop_Max8Ux16:
1579 case Iop_CmpGT8Sx16:
1580 case Iop_CmpEQ8x16:
1581 case Iop_Avg8Ux16:
1582 case Iop_QAdd8Ux16:
1583 case Iop_QAdd8Sx16:
1584 case Iop_Add8x16:
1585 return binary8Ix16(mce, vatom1, vatom2);
1586
1587 case Iop_QSub16Ux8:
1588 case Iop_QSub16Sx8:
1589 case Iop_Sub16x8:
1590 case Iop_Mul16x8:
1591 case Iop_MulHi16Sx8:
1592 case Iop_MulHi16Ux8:
1593 case Iop_Min16Sx8:
1594 case Iop_Max16Sx8:
1595 case Iop_CmpGT16Sx8:
1596 case Iop_CmpEQ16x8:
1597 case Iop_Avg16Ux8:
1598 case Iop_QAdd16Ux8:
1599 case Iop_QAdd16Sx8:
1600 case Iop_Add16x8:
1601 return binary16Ix8(mce, vatom1, vatom2);
1602
1603 case Iop_Sub32x4:
1604 case Iop_CmpGT32Sx4:
1605 case Iop_CmpEQ32x4:
1606 case Iop_Add32x4:
1607 return binary32Ix4(mce, vatom1, vatom2);
1608
1609 case Iop_Sub64x2:
1610 case Iop_Add64x2:
1611 return binary64Ix2(mce, vatom1, vatom2);
1612
1613 case Iop_QNarrow32Sx4:
1614 case Iop_QNarrow16Sx8:
1615 case Iop_QNarrow16Ux8:
sewardjf0c1c582005-02-07 23:47:38 +00001616 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001617
1618 case Iop_Sub64Fx2:
1619 case Iop_Mul64Fx2:
1620 case Iop_Min64Fx2:
1621 case Iop_Max64Fx2:
1622 case Iop_Div64Fx2:
1623 case Iop_CmpLT64Fx2:
1624 case Iop_CmpLE64Fx2:
1625 case Iop_CmpEQ64Fx2:
1626 case Iop_Add64Fx2:
1627 return binary64Fx2(mce, vatom1, vatom2);
1628
1629 case Iop_Sub64F0x2:
1630 case Iop_Mul64F0x2:
1631 case Iop_Min64F0x2:
1632 case Iop_Max64F0x2:
1633 case Iop_Div64F0x2:
1634 case Iop_CmpLT64F0x2:
1635 case Iop_CmpLE64F0x2:
1636 case Iop_CmpEQ64F0x2:
1637 case Iop_Add64F0x2:
1638 return binary64F0x2(mce, vatom1, vatom2);
1639
sewardjf0c1c582005-02-07 23:47:38 +00001640 /* V128-bit SIMD (SSE1-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001641
1642 case Iop_Sub32Fx4:
1643 case Iop_Mul32Fx4:
1644 case Iop_Min32Fx4:
1645 case Iop_Max32Fx4:
1646 case Iop_Div32Fx4:
1647 case Iop_CmpLT32Fx4:
1648 case Iop_CmpLE32Fx4:
1649 case Iop_CmpEQ32Fx4:
1650 case Iop_Add32Fx4:
1651 return binary32Fx4(mce, vatom1, vatom2);
1652
1653 case Iop_Sub32F0x4:
1654 case Iop_Mul32F0x4:
1655 case Iop_Min32F0x4:
1656 case Iop_Max32F0x4:
1657 case Iop_Div32F0x4:
1658 case Iop_CmpLT32F0x4:
1659 case Iop_CmpLE32F0x4:
1660 case Iop_CmpEQ32F0x4:
1661 case Iop_Add32F0x4:
1662 return binary32F0x4(mce, vatom1, vatom2);
1663
sewardjf0c1c582005-02-07 23:47:38 +00001664 /* V128-bit data-steering */
1665 case Iop_SetV128lo32:
1666 case Iop_SetV128lo64:
1667 case Iop_64HLtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001668 case Iop_InterleaveLO64x2:
1669 case Iop_InterleaveLO32x4:
1670 case Iop_InterleaveLO16x8:
1671 case Iop_InterleaveLO8x16:
1672 case Iop_InterleaveHI64x2:
1673 case Iop_InterleaveHI32x4:
1674 case Iop_InterleaveHI16x8:
1675 case Iop_InterleaveHI8x16:
1676 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1677
1678 /* Scalar floating point */
1679
sewardj3598ef92004-11-11 02:13:30 +00001680 case Iop_RoundF64:
1681 case Iop_F64toI64:
sewardj69f9e3e2004-12-30 02:05:34 +00001682 case Iop_I64toF64:
1683 /* First arg is I32 (rounding mode), second is F64 or I64
1684 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001685 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1686
1687 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1688 /* Takes two F64 args. */
sewardjde8a5ae2004-11-06 14:20:54 +00001689 case Iop_F64toI32:
sewardj69f9e3e2004-12-30 02:05:34 +00001690 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001691 /* First arg is I32 (rounding mode), second is F64 (data). */
1692 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1693
1694 case Iop_F64toI16:
1695 /* First arg is I32 (rounding mode), second is F64 (data). */
1696 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1697
sewardj3598ef92004-11-11 02:13:30 +00001698 case Iop_ScaleF64:
1699 case Iop_Yl2xF64:
1700 case Iop_Yl2xp1F64:
1701 case Iop_PRemF64:
1702 case Iop_AtanF64:
1703 case Iop_AddF64:
1704 case Iop_DivF64:
1705 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001706 case Iop_MulF64:
1707 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1708
sewardj3598ef92004-11-11 02:13:30 +00001709 case Iop_CmpF64:
1710 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1711
sewardjde8a5ae2004-11-06 14:20:54 +00001712 /* non-FP after here */
1713
1714 case Iop_DivModU64to32:
1715 case Iop_DivModS64to32:
1716 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1717
sewardj3598ef92004-11-11 02:13:30 +00001718 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001719 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001720 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001721 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001722
1723 case Iop_MullS32:
1724 case Iop_MullU32: {
1725 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1726 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1727 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1728 }
1729
sewardj3598ef92004-11-11 02:13:30 +00001730 case Iop_MullS16:
1731 case Iop_MullU16: {
1732 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1733 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1734 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1735 }
1736
1737 case Iop_MullS8:
1738 case Iop_MullU8: {
1739 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1740 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1741 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1742 }
1743
sewardjde8a5ae2004-11-06 14:20:54 +00001744 case Iop_Add32:
1745# if 0
1746 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1747# endif
1748 case Iop_Sub32:
1749 case Iop_Mul32:
1750 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1751
sewardj3598ef92004-11-11 02:13:30 +00001752 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001753 case Iop_Add16:
1754 case Iop_Sub16:
1755 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1756
1757 case Iop_Sub8:
1758 case Iop_Add8:
1759 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1760
1761 case Iop_CmpLE32S: case Iop_CmpLE32U:
1762 case Iop_CmpLT32U: case Iop_CmpLT32S:
1763 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001764 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001765
sewardj3598ef92004-11-11 02:13:30 +00001766 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001767 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001768
1769 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001770 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001771
1772 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1773 /* Complain if the shift amount is undefined. Then simply
1774 shift the first arg's V bits by the real shift amount. */
1775 complainIfUndefined(mce, atom2);
1776 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1777
sewardj69f9e3e2004-12-30 02:05:34 +00001778 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001779 /* Same scheme as with 32-bit shifts. */
1780 complainIfUndefined(mce, atom2);
1781 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1782
sewardj3598ef92004-11-11 02:13:30 +00001783 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001784 /* Same scheme as with 32-bit shifts. */
1785 complainIfUndefined(mce, atom2);
1786 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1787
1788 case Iop_Shl64: case Iop_Shr64:
1789 /* Same scheme as with 32-bit shifts. */
1790 complainIfUndefined(mce, atom2);
1791 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1792
sewardjf0c1c582005-02-07 23:47:38 +00001793 case Iop_AndV128:
1794 uifu = mkUifUV128; difd = mkDifDV128;
1795 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001796 case Iop_And64:
1797 uifu = mkUifU64; difd = mkDifD64;
1798 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001799 case Iop_And32:
1800 uifu = mkUifU32; difd = mkDifD32;
1801 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001802 case Iop_And16:
1803 uifu = mkUifU16; difd = mkDifD16;
1804 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001805 case Iop_And8:
1806 uifu = mkUifU8; difd = mkDifD8;
1807 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1808
sewardjf0c1c582005-02-07 23:47:38 +00001809 case Iop_OrV128:
1810 uifu = mkUifUV128; difd = mkDifDV128;
1811 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001812 case Iop_Or64:
1813 uifu = mkUifU64; difd = mkDifD64;
1814 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001815 case Iop_Or32:
1816 uifu = mkUifU32; difd = mkDifD32;
1817 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1818 case Iop_Or16:
1819 uifu = mkUifU16; difd = mkDifD16;
1820 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1821 case Iop_Or8:
1822 uifu = mkUifU8; difd = mkDifD8;
1823 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1824
1825 do_And_Or:
1826 return
1827 assignNew(
1828 mce,
1829 and_or_ty,
1830 difd(mce, uifu(mce, vatom1, vatom2),
1831 difd(mce, improve(mce, atom1, vatom1),
1832 improve(mce, atom2, vatom2) ) ) );
1833
1834 case Iop_Xor8:
1835 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001836 case Iop_Xor16:
1837 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001838 case Iop_Xor32:
1839 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001840 case Iop_Xor64:
1841 return mkUifU64(mce, vatom1, vatom2);
sewardjf0c1c582005-02-07 23:47:38 +00001842 case Iop_XorV128:
1843 return mkUifUV128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001844
1845 default:
1846 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001847 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001848 }
1849}
1850
1851
1852static
1853IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1854{
1855 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001856 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001857 switch (op) {
1858
sewardj69f9e3e2004-12-30 02:05:34 +00001859 case Iop_Sqrt64Fx2:
1860 return unary64Fx2(mce, vatom);
1861
1862 case Iop_Sqrt64F0x2:
1863 return unary64F0x2(mce, vatom);
1864
1865 case Iop_Sqrt32Fx4:
1866 case Iop_RSqrt32Fx4:
1867 case Iop_Recip32Fx4:
1868 return unary32Fx4(mce, vatom);
1869
1870 case Iop_Sqrt32F0x4:
1871 case Iop_RSqrt32F0x4:
1872 case Iop_Recip32F0x4:
1873 return unary32F0x4(mce, vatom);
1874
sewardjf0c1c582005-02-07 23:47:38 +00001875 case Iop_32UtoV128:
1876 case Iop_64UtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001877 return assignNew(mce, Ity_V128, unop(op, vatom));
1878
sewardjde8a5ae2004-11-06 14:20:54 +00001879 case Iop_F32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001880 case Iop_I32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001881 case Iop_NegF64:
1882 case Iop_SinF64:
1883 case Iop_CosF64:
1884 case Iop_TanF64:
1885 case Iop_SqrtF64:
1886 case Iop_AbsF64:
1887 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001888 return mkPCastTo(mce, Ity_I64, vatom);
1889
sewardj3598ef92004-11-11 02:13:30 +00001890 case Iop_Clz32:
1891 case Iop_Ctz32:
1892 return mkPCastTo(mce, Ity_I32, vatom);
1893
1894 case Iop_32Sto64:
1895 case Iop_32Uto64:
sewardjf0c1c582005-02-07 23:47:38 +00001896 case Iop_V128to64:
1897 case Iop_V128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001898 return assignNew(mce, Ity_I64, unop(op, vatom));
1899
sewardjde8a5ae2004-11-06 14:20:54 +00001900 case Iop_64to32:
1901 case Iop_64HIto32:
1902 case Iop_1Uto32:
1903 case Iop_8Uto32:
1904 case Iop_16Uto32:
1905 case Iop_16Sto32:
1906 case Iop_8Sto32:
1907 return assignNew(mce, Ity_I32, unop(op, vatom));
1908
1909 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001910 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001911 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001912 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001913 return assignNew(mce, Ity_I16, unop(op, vatom));
1914
1915 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001916 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001917 case Iop_32to8:
1918 return assignNew(mce, Ity_I8, unop(op, vatom));
1919
1920 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001921 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001922
sewardj3598ef92004-11-11 02:13:30 +00001923 case Iop_ReinterpF64asI64:
1924 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001925 case Iop_ReinterpI32asF32:
sewardjf0c1c582005-02-07 23:47:38 +00001926 case Iop_NotV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001927 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00001928 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001929 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001930 case Iop_Not8:
1931 case Iop_Not1:
1932 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001933
sewardjde8a5ae2004-11-06 14:20:54 +00001934 default:
1935 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001936 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00001937 }
1938}
1939
1940
sewardj69f9e3e2004-12-30 02:05:34 +00001941/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00001942static
sewardj69f9e3e2004-12-30 02:05:34 +00001943IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001944{
1945 void* helper;
sewardjde8c9872005-03-25 13:48:55 +00001946 HChar* hname;
sewardjde8a5ae2004-11-06 14:20:54 +00001947 IRDirty* di;
1948 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00001949 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001950
sewardj69f9e3e2004-12-30 02:05:34 +00001951 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00001952
1953 /* First, emit a definedness test for the address. This also sets
1954 the address (shadow) to 'defined' following the test. */
1955 complainIfUndefined( mce, addr );
1956
1957 /* Now cook up a call to the relevant helper function, to read the
1958 data V bits from shadow memory. */
1959 ty = shadowType(ty);
1960 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001961 case Ity_I64: helper = &MC_(helperc_LOADV8);
1962 hname = "MC_(helperc_LOADV8)";
1963 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001964 case Ity_I32: helper = &MC_(helperc_LOADV4);
1965 hname = "MC_(helperc_LOADV4)";
1966 break;
1967 case Ity_I16: helper = &MC_(helperc_LOADV2);
1968 hname = "MC_(helperc_LOADV2)";
1969 break;
1970 case Ity_I8: helper = &MC_(helperc_LOADV1);
1971 hname = "MC_(helperc_LOADV1)";
1972 break;
1973 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001974 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00001975 }
1976
sewardj3598ef92004-11-11 02:13:30 +00001977 /* Generate the actual address into addrAct. */
1978 if (bias == 0) {
1979 addrAct = addr;
1980 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001981 IROp mkAdd;
1982 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00001983 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00001984 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
1985 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1986 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00001987 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1988 }
1989
sewardjde8a5ae2004-11-06 14:20:54 +00001990 /* We need to have a place to park the V bits we're just about to
1991 read. */
1992 datavbits = newIRTemp(mce->bb->tyenv, ty);
1993 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00001994 1/*regparms*/, hname, helper,
1995 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00001996 setHelperAnns( mce, di );
1997 stmt( mce->bb, IRStmt_Dirty(di) );
1998
1999 return mkexpr(datavbits);
2000}
2001
2002
2003static
sewardj69f9e3e2004-12-30 02:05:34 +00002004IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
2005{
2006 IRAtom *v64hi, *v64lo;
2007 switch (shadowType(ty)) {
2008 case Ity_I8:
2009 case Ity_I16:
2010 case Ity_I32:
2011 case Ity_I64:
2012 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
2013 case Ity_V128:
2014 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
2015 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
2016 return assignNew( mce,
2017 Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +00002018 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj69f9e3e2004-12-30 02:05:34 +00002019 default:
2020 VG_(tool_panic)("expr2vbits_LDle");
2021 }
2022}
2023
2024
2025static
sewardjde8a5ae2004-11-06 14:20:54 +00002026IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00002027 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00002028{
2029 IRAtom *vbitsC, *vbits0, *vbitsX;
2030 IRType ty;
2031 /* Given Mux0X(cond,expr0,exprX), generate
2032 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2033 That is, steer the V bits like the originals, but trash the
2034 result if the steering value is undefined. This gives
2035 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00002036 tl_assert(isOriginalAtom(mce, cond));
2037 tl_assert(isOriginalAtom(mce, expr0));
2038 tl_assert(isOriginalAtom(mce, exprX));
sewardjde8a5ae2004-11-06 14:20:54 +00002039
2040 vbitsC = expr2vbits(mce, cond);
2041 vbits0 = expr2vbits(mce, expr0);
2042 vbitsX = expr2vbits(mce, exprX);
2043 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2044
2045 return
2046 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2047 mkPCastTo(mce, ty, vbitsC) );
2048}
2049
2050/* --------- This is the main expression-handling function. --------- */
2051
2052static
2053IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2054{
2055 switch (e->tag) {
2056
2057 case Iex_Get:
2058 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2059
2060 case Iex_GetI:
2061 return shadow_GETI( mce, e->Iex.GetI.descr,
2062 e->Iex.GetI.ix, e->Iex.GetI.bias );
2063
2064 case Iex_Tmp:
2065 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
2066
2067 case Iex_Const:
2068 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2069
2070 case Iex_Binop:
2071 return expr2vbits_Binop(
2072 mce,
2073 e->Iex.Binop.op,
2074 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2075 );
2076
2077 case Iex_Unop:
2078 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2079
2080 case Iex_LDle:
sewardj3598ef92004-11-11 02:13:30 +00002081 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
2082 e->Iex.LDle.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002083
2084 case Iex_CCall:
2085 return mkLazyN( mce, e->Iex.CCall.args,
2086 e->Iex.CCall.retty,
2087 e->Iex.CCall.cee );
2088
2089 case Iex_Mux0X:
2090 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2091 e->Iex.Mux0X.exprX);
2092
2093 default:
2094 VG_(printf)("\n");
2095 ppIRExpr(e);
2096 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002097 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002098 }
2099}
2100
2101/*------------------------------------------------------------*/
2102/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2103/*------------------------------------------------------------*/
2104
2105/* Widen a value to the host word size. */
2106
2107static
2108IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2109{
sewardj69f9e3e2004-12-30 02:05:34 +00002110 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002111
sewardj8fc93742004-11-22 11:29:33 +00002112 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002113 tl_assert(isShadowAtom(mce,vatom));
2114
2115 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2116 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002117
sewardjde8a5ae2004-11-06 14:20:54 +00002118 if (tyH == Ity_I32) {
2119 switch (ty) {
2120 case Ity_I32: return vatom;
2121 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2122 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2123 default: goto unhandled;
2124 }
2125 } else {
2126 goto unhandled;
2127 }
2128 unhandled:
2129 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002130 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002131}
2132
2133
sewardj3598ef92004-11-11 02:13:30 +00002134/* Generate a shadow store. addr is always the original address atom.
2135 You can pass in either originals or V-bits for the data atom, but
2136 obviously not both. */
2137
sewardjde8a5ae2004-11-06 14:20:54 +00002138static
sewardj3598ef92004-11-11 02:13:30 +00002139void do_shadow_STle ( MCEnv* mce,
2140 IRAtom* addr, UInt bias,
2141 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002142{
sewardj69f9e3e2004-12-30 02:05:34 +00002143 IROp mkAdd;
2144 IRType ty, tyAddr;
2145 IRDirty *di, *diLo64, *diHi64;
2146 IRAtom *addrAct, *addrLo64, *addrHi64;
2147 IRAtom *vdataLo64, *vdataHi64;
2148 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002149 void* helper = NULL;
2150 Char* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002151
2152 tyAddr = mce->hWordTy;
2153 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2154 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2155
2156 di = diLo64 = diHi64 = NULL;
2157 eBias = eBias0 = eBias8 = NULL;
2158 addrAct = addrLo64 = addrHi64 = NULL;
2159 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002160
sewardj3598ef92004-11-11 02:13:30 +00002161 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002162 tl_assert(!vdata);
2163 tl_assert(isOriginalAtom(mce, data));
2164 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002165 vdata = expr2vbits( mce, data );
2166 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002167 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002168 }
sewardjde8a5ae2004-11-06 14:20:54 +00002169
sewardj69f9e3e2004-12-30 02:05:34 +00002170 tl_assert(isOriginalAtom(mce,addr));
2171 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002172
2173 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002174
2175 /* First, emit a definedness test for the address. This also sets
2176 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002177 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002178
sewardj69f9e3e2004-12-30 02:05:34 +00002179 /* Now decide which helper function to call to write the data V
2180 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002181 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002182 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002183 case Ity_I64: helper = &MC_(helperc_STOREV8);
2184 hname = "MC_(helperc_STOREV8)";
2185 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002186 case Ity_I32: helper = &MC_(helperc_STOREV4);
2187 hname = "MC_(helperc_STOREV4)";
2188 break;
2189 case Ity_I16: helper = &MC_(helperc_STOREV2);
2190 hname = "MC_(helperc_STOREV2)";
2191 break;
2192 case Ity_I8: helper = &MC_(helperc_STOREV1);
2193 hname = "MC_(helperc_STOREV1)";
2194 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002195 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002196 }
2197
sewardj69f9e3e2004-12-30 02:05:34 +00002198 if (ty == Ity_V128) {
2199
sewardjf0c1c582005-02-07 23:47:38 +00002200 /* V128-bit case */
sewardj69f9e3e2004-12-30 02:05:34 +00002201 /* See comment in next clause re 64-bit regparms */
2202 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2203 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
sewardjf0c1c582005-02-07 23:47:38 +00002204 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002205 diLo64 = unsafeIRDirty_0_N(
2206 1/*regparms*/, hname, helper,
2207 mkIRExprVec_2( addrLo64, vdataLo64 ));
2208
2209 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2210 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
sewardjf0c1c582005-02-07 23:47:38 +00002211 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002212 diHi64 = unsafeIRDirty_0_N(
2213 1/*regparms*/, hname, helper,
2214 mkIRExprVec_2( addrHi64, vdataHi64 ));
2215
2216 setHelperAnns( mce, diLo64 );
2217 setHelperAnns( mce, diHi64 );
2218 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2219 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2220
sewardj3598ef92004-11-11 02:13:30 +00002221 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002222
2223 /* 8/16/32/64-bit cases */
2224 /* Generate the actual address into addrAct. */
2225 if (bias == 0) {
2226 addrAct = addr;
2227 } else {
2228 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2229 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2230 }
2231
2232 if (ty == Ity_I64) {
2233 /* We can't do this with regparm 2 on 32-bit platforms, since
2234 the back ends aren't clever enough to handle 64-bit
2235 regparm args. Therefore be different. */
2236 di = unsafeIRDirty_0_N(
2237 1/*regparms*/, hname, helper,
2238 mkIRExprVec_2( addrAct, vdata ));
2239 } else {
2240 di = unsafeIRDirty_0_N(
2241 2/*regparms*/, hname, helper,
2242 mkIRExprVec_2( addrAct,
2243 zwidenToHostWord( mce, vdata )));
2244 }
2245 setHelperAnns( mce, di );
2246 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002247 }
2248
sewardjde8a5ae2004-11-06 14:20:54 +00002249}
2250
2251
sewardj3598ef92004-11-11 02:13:30 +00002252/* Do lazy pessimistic propagation through a dirty helper call, by
2253 looking at the annotations on it. This is the most complex part of
2254 Memcheck. */
2255
2256static IRType szToITy ( Int n )
2257{
2258 switch (n) {
2259 case 1: return Ity_I8;
2260 case 2: return Ity_I16;
2261 case 4: return Ity_I32;
2262 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002263 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002264 }
2265}
2266
2267static
2268void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2269{
sewardj69f9e3e2004-12-30 02:05:34 +00002270 Int i, n, offset, toDo, gSz, gOff;
2271 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002272 IRType tyAddr, tySrc, tyDst;
2273 IRTemp dst;
2274
2275 /* First check the guard. */
2276 complainIfUndefined(mce, d->guard);
2277
2278 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002279 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002280
2281 /* Inputs: unmasked args */
2282 for (i = 0; d->args[i]; i++) {
2283 if (d->cee->mcx_mask & (1<<i)) {
2284 /* ignore this arg */
2285 } else {
2286 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2287 curr = mkUifU32(mce, here, curr);
2288 }
2289 }
2290
2291 /* Inputs: guest state that we read. */
2292 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002293 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002294 if (d->fxState[i].fx == Ifx_Write)
2295 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002296
2297 /* Ignore any sections marked as 'always defined'. */
2298 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2299 if (0)
2300 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2301 d->fxState[i].offset, d->fxState[i].size );
2302 continue;
2303 }
2304
sewardj3598ef92004-11-11 02:13:30 +00002305 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002306 consider it. If larger than 8 bytes, deal with it in 8-byte
2307 chunks. */
2308 gSz = d->fxState[i].size;
2309 gOff = d->fxState[i].offset;
2310 tl_assert(gSz > 0);
2311 while (True) {
2312 if (gSz == 0) break;
2313 n = gSz <= 8 ? gSz : 8;
2314 /* update 'curr' with UifU of the state slice
2315 gOff .. gOff+n-1 */
2316 tySrc = szToITy( n );
2317 src = assignNew( mce, tySrc,
2318 shadow_GET(mce, gOff, tySrc ) );
2319 here = mkPCastTo( mce, Ity_I32, src );
2320 curr = mkUifU32(mce, here, curr);
2321 gSz -= n;
2322 gOff += n;
2323 }
2324
sewardj3598ef92004-11-11 02:13:30 +00002325 }
2326
2327 /* Inputs: memory. First set up some info needed regardless of
2328 whether we're doing reads or writes. */
2329 tyAddr = Ity_INVALID;
2330
2331 if (d->mFx != Ifx_None) {
2332 /* Because we may do multiple shadow loads/stores from the same
2333 base address, it's best to do a single test of its
2334 definedness right now. Post-instrumentation optimisation
2335 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002336 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002337 complainIfUndefined(mce, d->mAddr);
2338
2339 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002340 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2341 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002342 }
2343
2344 /* Deal with memory inputs (reads or modifies) */
2345 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2346 offset = 0;
2347 toDo = d->mSize;
2348 /* chew off 32-bit chunks */
2349 while (toDo >= 4) {
2350 here = mkPCastTo(
2351 mce, Ity_I32,
2352 expr2vbits_LDle ( mce, Ity_I32,
2353 d->mAddr, d->mSize - toDo )
2354 );
2355 curr = mkUifU32(mce, here, curr);
2356 toDo -= 4;
2357 }
2358 /* chew off 16-bit chunks */
2359 while (toDo >= 2) {
2360 here = mkPCastTo(
2361 mce, Ity_I32,
2362 expr2vbits_LDle ( mce, Ity_I16,
2363 d->mAddr, d->mSize - toDo )
2364 );
2365 curr = mkUifU32(mce, here, curr);
2366 toDo -= 2;
2367 }
sewardj69f9e3e2004-12-30 02:05:34 +00002368 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002369 }
2370
2371 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2372 all the inputs to the helper. Now we need to re-distribute the
2373 results to all destinations. */
2374
2375 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002376 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002377 dst = findShadowTmp(mce, d->tmp);
2378 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2379 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2380 }
2381
2382 /* Outputs: guest state that we write or modify. */
2383 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002384 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002385 if (d->fxState[i].fx == Ifx_Read)
2386 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002387 /* Ignore any sections marked as 'always defined'. */
2388 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2389 continue;
2390 /* This state element is written or modified. So we need to
2391 consider it. If larger than 8 bytes, deal with it in 8-byte
2392 chunks. */
2393 gSz = d->fxState[i].size;
2394 gOff = d->fxState[i].offset;
2395 tl_assert(gSz > 0);
2396 while (True) {
2397 if (gSz == 0) break;
2398 n = gSz <= 8 ? gSz : 8;
2399 /* Write suitably-casted 'curr' to the state slice
2400 gOff .. gOff+n-1 */
2401 tyDst = szToITy( n );
2402 do_shadow_PUT( mce, gOff,
2403 NULL, /* original atom */
2404 mkPCastTo( mce, tyDst, curr ) );
2405 gSz -= n;
2406 gOff += n;
2407 }
sewardj3598ef92004-11-11 02:13:30 +00002408 }
2409
2410 /* Outputs: memory that we write or modify. */
2411 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2412 offset = 0;
2413 toDo = d->mSize;
2414 /* chew off 32-bit chunks */
2415 while (toDo >= 4) {
2416 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2417 NULL, /* original data */
2418 mkPCastTo( mce, Ity_I32, curr ) );
2419 toDo -= 4;
2420 }
2421 /* chew off 16-bit chunks */
2422 while (toDo >= 2) {
2423 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2424 NULL, /* original data */
2425 mkPCastTo( mce, Ity_I16, curr ) );
2426 toDo -= 2;
2427 }
sewardj69f9e3e2004-12-30 02:05:34 +00002428 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002429 }
2430
2431}
2432
2433
sewardjde8a5ae2004-11-06 14:20:54 +00002434/*------------------------------------------------------------*/
2435/*--- Memcheck main ---*/
2436/*------------------------------------------------------------*/
2437
sewardj3598ef92004-11-11 02:13:30 +00002438static Bool isBogusAtom ( IRAtom* at )
2439{
2440 ULong n = 0;
2441 IRConst* con;
sewardj496a58d2005-03-20 18:44:44 +00002442 tl_assert(isIRAtom(at));
sewardj3598ef92004-11-11 02:13:30 +00002443 if (at->tag == Iex_Tmp)
2444 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002445 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002446 con = at->Iex.Const.con;
2447 switch (con->tag) {
2448 case Ico_U8: n = (ULong)con->Ico.U8; break;
2449 case Ico_U16: n = (ULong)con->Ico.U16; break;
2450 case Ico_U32: n = (ULong)con->Ico.U32; break;
2451 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002452 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002453 }
2454 /* VG_(printf)("%llx\n", n); */
2455 return (n == 0xFEFEFEFF
2456 || n == 0x80808080
2457 || n == 0x1010101
2458 || n == 1010100);
2459}
2460
2461static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2462{
2463 Int i;
2464 IRExpr* e;
2465 switch (st->tag) {
2466 case Ist_Tmp:
2467 e = st->Ist.Tmp.data;
2468 switch (e->tag) {
2469 case Iex_Get:
2470 case Iex_Tmp:
2471 return False;
2472 case Iex_Unop:
2473 return isBogusAtom(e->Iex.Unop.arg);
2474 case Iex_Binop:
2475 return isBogusAtom(e->Iex.Binop.arg1)
2476 || isBogusAtom(e->Iex.Binop.arg2);
2477 case Iex_Mux0X:
2478 return isBogusAtom(e->Iex.Mux0X.cond)
2479 || isBogusAtom(e->Iex.Mux0X.expr0)
2480 || isBogusAtom(e->Iex.Mux0X.exprX);
2481 case Iex_LDle:
2482 return isBogusAtom(e->Iex.LDle.addr);
2483 case Iex_CCall:
2484 for (i = 0; e->Iex.CCall.args[i]; i++)
2485 if (isBogusAtom(e->Iex.CCall.args[i]))
2486 return True;
2487 return False;
2488 default:
2489 goto unhandled;
2490 }
2491 case Ist_Put:
2492 return isBogusAtom(st->Ist.Put.data);
2493 case Ist_STle:
2494 return isBogusAtom(st->Ist.STle.addr)
2495 || isBogusAtom(st->Ist.STle.data);
2496 case Ist_Exit:
sewardj1ea1b612005-03-26 13:02:20 +00002497 return isBogusAtom(st->Ist.Exit.guard);
sewardj3598ef92004-11-11 02:13:30 +00002498 default:
2499 unhandled:
2500 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002501 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002502 }
2503}
sewardj3598ef92004-11-11 02:13:30 +00002504
sewardj1ea1b612005-03-26 13:02:20 +00002505IRBB* mc_instrument ( IRBB* bb_in, VexGuestLayout* layout,
2506 IRType gWordTy, IRType hWordTy )
sewardjde8a5ae2004-11-06 14:20:54 +00002507{
sewardj3598ef92004-11-11 02:13:30 +00002508 Bool verboze = False; //True;
2509
2510 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002511
2512 Int i, j, first_stmt;
2513 IRStmt* st;
2514 MCEnv mce;
2515
2516 /* Set up BB */
2517 IRBB* bb = emptyIRBB();
2518 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
2519 bb->next = dopyIRExpr(bb_in->next);
2520 bb->jumpkind = bb_in->jumpkind;
2521
2522 /* Set up the running environment. Only .bb is modified as we go
2523 along. */
2524 mce.bb = bb;
2525 mce.layout = layout;
2526 mce.n_originalTmps = bb->tyenv->types_used;
2527 mce.hWordTy = hWordTy;
2528 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2529 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002530 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002531
2532 /* Iterate over the stmts. */
2533
2534 for (i = 0; i < bb_in->stmts_used; i++) {
2535 st = bb_in->stmts[i];
2536 if (!st) continue;
2537
sewardj69f9e3e2004-12-30 02:05:34 +00002538 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002539
2540 /*
2541 if (!hasBogusLiterals) {
2542 hasBogusLiterals = checkForBogusLiterals(st);
2543 if (hasBogusLiterals) {
2544 VG_(printf)("bogus: ");
2545 ppIRStmt(st);
2546 VG_(printf)("\n");
2547 }
2548 }
2549 */
sewardjde8a5ae2004-11-06 14:20:54 +00002550 first_stmt = bb->stmts_used;
2551
2552 if (verboze) {
2553 ppIRStmt(st);
2554 VG_(printf)("\n\n");
2555 }
2556
2557 switch (st->tag) {
2558
2559 case Ist_Tmp:
2560 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
2561 expr2vbits( &mce, st->Ist.Tmp.data) );
2562 break;
2563
2564 case Ist_Put:
2565 do_shadow_PUT( &mce,
2566 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002567 st->Ist.Put.data,
2568 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002569 break;
2570
2571 case Ist_PutI:
2572 do_shadow_PUTI( &mce,
2573 st->Ist.PutI.descr,
2574 st->Ist.PutI.ix,
2575 st->Ist.PutI.bias,
2576 st->Ist.PutI.data );
2577 break;
2578
2579 case Ist_STle:
sewardj3598ef92004-11-11 02:13:30 +00002580 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
2581 st->Ist.STle.data,
2582 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002583 break;
2584
2585 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002586 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002587 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002588 break;
2589
2590 case Ist_Dirty:
2591 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002592 break;
2593
sewardj1ea1b612005-03-26 13:02:20 +00002594 case Ist_IMark:
2595 case Ist_NoOp:
2596 break;
2597
sewardjde8a5ae2004-11-06 14:20:54 +00002598 default:
2599 VG_(printf)("\n");
2600 ppIRStmt(st);
2601 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002602 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002603
2604 } /* switch (st->tag) */
2605
2606 if (verboze) {
2607 for (j = first_stmt; j < bb->stmts_used; j++) {
2608 VG_(printf)(" ");
2609 ppIRStmt(bb->stmts[j]);
2610 VG_(printf)("\n");
2611 }
2612 VG_(printf)("\n");
2613 }
2614
2615 addStmtToIRBB(bb, st);
2616
2617 }
2618
2619 /* Now we need to complain if the jump target is undefined. */
2620 first_stmt = bb->stmts_used;
2621
2622 if (verboze) {
2623 VG_(printf)("bb->next = ");
2624 ppIRExpr(bb->next);
2625 VG_(printf)("\n\n");
2626 }
2627
2628 complainIfUndefined( &mce, bb->next );
2629
2630 if (verboze) {
2631 for (j = first_stmt; j < bb->stmts_used; j++) {
2632 VG_(printf)(" ");
2633 ppIRStmt(bb->stmts[j]);
2634 VG_(printf)("\n");
2635 }
2636 VG_(printf)("\n");
2637 }
2638
2639 return bb;
2640}
cerionaee45242005-03-17 14:03:36 +00002641#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002642
2643/*--------------------------------------------------------------------*/
2644/*--- end mc_translate.c ---*/
2645/*--------------------------------------------------------------------*/