blob: 854dbbf9c99d8c549fc0511930810271c0e8a2b1 [file] [log] [blame]
sewardjc97096c2004-06-30 09:28:04 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
4/*--- This file (test_main.c) is ---*/
5/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
6/*--- ---*/
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
sewardj5bd4d162004-11-10 13:02:48 +000056static Bool chase_into_not_ok ( 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;
sewardj02ef7162005-06-30 12:50:50 +000069 VexArchInfo vai;
sewardjced9fe52004-07-07 11:55:36 +000070
71 if (argc != 2) {
72 fprintf(stderr, "usage: vex file.org\n");
73 exit(1);
74 }
75 f = fopen(argv[1], "r");
76 if (!f) {
77 fprintf(stderr, "can't open `%s'\n", argv[1]);
78 exit(1);
79 }
80
sewardjb5bf2e02004-10-25 13:06:17 +000081 /* Run with default params. However, we can't allow bb chasing
82 since that causes the front end to get segfaults when it tries
sewardj5bd4d162004-11-10 13:02:48 +000083 to read code outside the initial BB we hand it. So when calling
84 LibVEX_Translate, send in a chase-into predicate that always
85 returns False. */
sewardjb5bf2e02004-10-25 13:06:17 +000086 LibVEX_default_VexControl ( &vcon );
sewardjb4952402004-10-26 13:24:50 +000087 vcon.iropt_level = 2;
sewardjc279b3f2005-03-16 18:10:45 +000088 vcon.guest_max_insns = 50;
sewardjb5bf2e02004-10-25 13:06:17 +000089
sewardjced9fe52004-07-07 11:55:36 +000090 LibVEX_Init ( &failure_exit, &log_bytes,
sewardj1f40a0a2004-07-21 12:28:07 +000091 1, /* debug_paranoia */
sewardjabe017e2004-10-29 23:42:36 +000092 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +000093 &vcon );
sewardjced9fe52004-07-07 11:55:36 +000094
sewardjea64e142004-07-22 16:47:21 +000095
sewardjced9fe52004-07-07 11:55:36 +000096 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +000097
sewardjced9fe52004-07-07 11:55:36 +000098 fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +000099 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +0000100 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +0000101
102 if (n_bbs_done == TEST_N_BBS) break;
103 n_bbs_done++;
104
sewardjced9fe52004-07-07 11:55:36 +0000105 /* first line is: . bb-number bb-addr n-bytes */
106 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
107 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000108 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000109 assert(orig_nbytes >= 1);
110 assert(!feof(f));
111 fgets(linebuf, N_LINEBUF,f);
112 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000113
sewardjced9fe52004-07-07 11:55:36 +0000114 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000115 if (verbose)
sewardj07a54cc2005-02-04 21:18:55 +0000116 printf("============ Basic Block %d, Done %d, "
sewardj4459baa2004-09-10 20:00:46 +0000117 "Start %x, nbytes %2d ============",
sewardj07a54cc2005-02-04 21:18:55 +0000118 bb_number, n_bbs_done-1, orig_addr, orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000119
sewardjced9fe52004-07-07 11:55:36 +0000120 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
121 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000122 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
123 origbuf[i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000124 }
125
sewardj02ef7162005-06-30 12:50:50 +0000126 LibVEX_default_VexArchInfo(&vai);
127 vai.subarch = VexSubArchX86_sse1;
128
sewardjabe017e2004-10-29 23:42:36 +0000129 for (i = 0; i < TEST_N_ITERS; i++)
130 tres
131 = LibVEX_Translate (
cerionaee45242005-03-17 14:03:36 +0000132#if 0 /* ppc32 -> ppc32 */
133 VexArchPPC32, VexSubArchPPC32_noAV,
134 VexArchPPC32, VexSubArchPPC32_noAV,
135#endif
sewardj07a54cc2005-02-04 21:18:55 +0000136#if 0 /* ppc32 -> x86 */
137 VexArchPPC32, VexSubArchPPC32_noAV,
sewardjc3263ee2004-12-29 17:48:22 +0000138 VexArchX86, VexSubArchX86_sse2,
sewardj07a54cc2005-02-04 21:18:55 +0000139#endif
sewardjc279b3f2005-03-16 18:10:45 +0000140#if 0 /* amd64 -> amd64 */
sewardj07a54cc2005-02-04 21:18:55 +0000141 VexArchAMD64, VexSubArch_NONE,
142 VexArchAMD64, VexSubArch_NONE,
143#endif
sewardjc279b3f2005-03-16 18:10:45 +0000144#if 1 /* x86 -> x86 */
sewardj02ef7162005-06-30 12:50:50 +0000145 VexArchX86, &vai,
146 VexArchX86, &vai,
sewardjc279b3f2005-03-16 18:10:45 +0000147#endif
sewardj07a54cc2005-02-04 21:18:55 +0000148
sewardj5bd4d162004-11-10 13:02:48 +0000149 origbuf, (Addr64)orig_addr, chase_into_not_ok,
sewardj72c72812005-01-19 11:49:45 +0000150 &vge,
sewardjabe017e2004-10-29 23:42:36 +0000151 transbuf, N_TRANSBUF, &trans_used,
sewardj9e7448b2004-11-18 13:44:15 +0000152#if 1 /* no instrumentation */
153 NULL, /* instrument1 */
154 NULL, /* instrument2 */
155 False, /* cleanup after instrument */
156#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000157#if 0 /* addrcheck */
158 ac_instrument, /* instrument1 */
159 NULL, /* instrument2 */
160 False, /* cleanup after instrument */
161#endif
sewardj9e7448b2004-11-18 13:44:15 +0000162#if 0 /* memcheck */
sewardjde8a5ae2004-11-06 14:20:54 +0000163 mc_instrument, /* instrument1 */
164 NULL, /* instrument2 */
sewardj69f9e3e2004-12-30 02:05:34 +0000165 True, /* cleanup after instrument */
sewardjde8a5ae2004-11-06 14:20:54 +0000166#endif
sewardjabe017e2004-10-29 23:42:36 +0000167 NULL, /* access checker */
168 TEST_FLAGS
169 );
170
sewardjd887b862005-01-17 18:34:34 +0000171 if (tres != VexTransOK)
sewardj4459baa2004-09-10 20:00:46 +0000172 printf("\ntres = %d\n", (Int)tres);
sewardjd887b862005-01-17 18:34:34 +0000173 assert(tres == VexTransOK);
sewardj72c72812005-01-19 11:49:45 +0000174 assert(vge.n_used == 1);
175 assert((UInt)(vge.len[0]) == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000176
sewardj4459baa2004-09-10 20:00:46 +0000177 sum = 0;
178 for (i = 0; i < trans_used; i++)
179 sum += (UInt)transbuf[i];
sewardjde8c9872005-03-25 13:48:55 +0000180 printf ( " %6.2f ... %u\n",
181 (double)trans_used / (double)vge.len[0], sum );
sewardjced9fe52004-07-07 11:55:36 +0000182 }
183
184 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000185 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000186 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000187
sewardjce605f92004-07-05 14:39:15 +0000188 return 0;
189}
sewardj9b1004e2004-10-30 22:25:40 +0000190
191//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000192//////////////////////////////////////////////////////////////////////
193//////////////////////////////////////////////////////////////////////
194//////////////////////////////////////////////////////////////////////
195//////////////////////////////////////////////////////////////////////
196//////////////////////////////////////////////////////////////////////
197//////////////////////////////////////////////////////////////////////
198//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000199
sewardj1ea1b612005-03-26 13:02:20 +0000200#if 0 /* UNUSED */
201
sewardj9b1004e2004-10-30 22:25:40 +0000202static
sewardjde8a5ae2004-11-06 14:20:54 +0000203__attribute((noreturn))
sewardjde8c9872005-03-25 13:48:55 +0000204void panic ( HChar* s )
sewardj9b1004e2004-10-30 22:25:40 +0000205{
206 printf("\npanic: %s\n", s);
207 failure_exit();
208}
209
210static
sewardj9578a8b2004-11-04 19:44:48 +0000211IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000212{
213/* Use this rather than eg. -1 because it's a UInt. */
214#define INVALID_DATA_SIZE 999999
215
216 Int i;
217 Int sz;
218 IRCallee* helper;
219 IRStmt* st;
220 IRExpr* data;
221 IRExpr* addr;
222 Bool needSz;
223
224 /* Set up BB */
225 IRBB* bb = emptyIRBB();
226 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
227 bb->next = dopyIRExpr(bb_in->next);
228 bb->jumpkind = bb_in->jumpkind;
229
230 /* No loads to consider in ->next. */
sewardj496a58d2005-03-20 18:44:44 +0000231 assert(isIRAtom(bb_in->next));
sewardj9b1004e2004-10-30 22:25:40 +0000232
233 for (i = 0; i < bb_in->stmts_used; i++) {
234 st = bb_in->stmts[i];
235 if (!st) continue;
236
237 switch (st->tag) {
238
239 case Ist_Tmp:
240 data = st->Ist.Tmp.data;
241 if (data->tag == Iex_LDle) {
242 addr = data->Iex.LDle.addr;
243 sz = sizeofIRType(data->Iex.LDle.ty);
244 needSz = False;
245 switch (sz) {
246 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000247 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000248 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000249 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000250 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000251 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000252 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000253 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000254 needSz = True; break;
255 }
256 if (needSz) {
257 addStmtToIRBB(
258 bb,
259 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000260 unsafeIRDirty_0_N( helper->regparms,
261 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000262 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
263 ));
264 } else {
265 addStmtToIRBB(
266 bb,
267 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000268 unsafeIRDirty_0_N( helper->regparms,
269 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000270 mkIRExprVec_1(addr) )
271 ));
272 }
273 }
274 break;
275
276 case Ist_STle:
277 data = st->Ist.STle.data;
278 addr = st->Ist.STle.addr;
sewardj496a58d2005-03-20 18:44:44 +0000279 assert(isIRAtom(data));
280 assert(isIRAtom(addr));
sewardj9b1004e2004-10-30 22:25:40 +0000281 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
282 needSz = False;
283 switch (sz) {
284 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000285 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000286 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000287 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000288 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000289 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000290 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000291 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000292 needSz = True; break;
293 }
294 if (needSz) {
295 addStmtToIRBB(
296 bb,
297 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000298 unsafeIRDirty_0_N( helper->regparms,
299 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000300 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
301 ));
302 } else {
303 addStmtToIRBB(
304 bb,
305 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000306 unsafeIRDirty_0_N( helper->regparms,
307 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000308 mkIRExprVec_1(addr) )
309 ));
310 }
311 break;
312
313 case Ist_Put:
sewardj496a58d2005-03-20 18:44:44 +0000314 assert(isIRAtom(st->Ist.Put.data));
sewardj9b1004e2004-10-30 22:25:40 +0000315 break;
316
317 case Ist_PutI:
sewardj496a58d2005-03-20 18:44:44 +0000318 assert(isIRAtom(st->Ist.PutI.ix));
319 assert(isIRAtom(st->Ist.PutI.data));
sewardj9b1004e2004-10-30 22:25:40 +0000320 break;
321
322 case Ist_Exit:
sewardj496a58d2005-03-20 18:44:44 +0000323 assert(isIRAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000324 break;
325
326 case Ist_Dirty:
327 /* If the call doesn't interact with memory, we ain't
328 interested. */
329 if (st->Ist.Dirty.details->mFx == Ifx_None)
330 break;
331 goto unhandled;
332
333 default:
334 unhandled:
335 printf("\n");
336 ppIRStmt(st);
337 printf("\n");
338 panic("addrcheck: unhandled IRStmt");
339 }
340
341 addStmtToIRBB( bb, dopyIRStmt(st));
342 }
343
344 return bb;
345}
cerionaee45242005-03-17 14:03:36 +0000346#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +0000347
348//////////////////////////////////////////////////////////////////////
349//////////////////////////////////////////////////////////////////////
350//////////////////////////////////////////////////////////////////////
351//////////////////////////////////////////////////////////////////////
352//////////////////////////////////////////////////////////////////////
353//////////////////////////////////////////////////////////////////////
354//////////////////////////////////////////////////////////////////////
355//////////////////////////////////////////////////////////////////////
356
sewardj1ea1b612005-03-26 13:02:20 +0000357#if 0 /* UNUSED */
358
sewardj69f9e3e2004-12-30 02:05:34 +0000359#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000360#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000361#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000362#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000363#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000364
cerionaee45242005-03-17 14:03:36 +0000365
sewardjde8c9872005-03-25 13:48:55 +0000366static void MC_helperc_complain_undef ( void );
367static void MC_helperc_LOADV8 ( void );
368static void MC_helperc_LOADV4 ( void );
369static void MC_helperc_LOADV2 ( void );
370static void MC_helperc_LOADV1 ( void );
sewardj1ea1b612005-03-26 13:02:20 +0000371static void MC_helperc_STOREV8( void );
372static void MC_helperc_STOREV4( void );
373static void MC_helperc_STOREV2( void );
374static void MC_helperc_STOREV1( void );
sewardjde8c9872005-03-25 13:48:55 +0000375static void MC_helperc_value_check0_fail( void );
376static void MC_helperc_value_check1_fail( void );
377static void MC_helperc_value_check4_fail( void );
378
379static void MC_helperc_complain_undef ( void ) { }
380static void MC_helperc_LOADV8 ( void ) { }
381static void MC_helperc_LOADV4 ( void ) { }
382static void MC_helperc_LOADV2 ( void ) { }
383static void MC_helperc_LOADV1 ( void ) { }
sewardj1ea1b612005-03-26 13:02:20 +0000384static void MC_helperc_STOREV8( void ) { }
385static void MC_helperc_STOREV4( void ) { }
386static void MC_helperc_STOREV2( void ) { }
387static void MC_helperc_STOREV1( void ) { }
sewardjde8c9872005-03-25 13:48:55 +0000388static void MC_helperc_value_check0_fail( void ) { }
389static void MC_helperc_value_check1_fail( void ) { }
390static void MC_helperc_value_check4_fail( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000391
392
sewardj3598ef92004-11-11 02:13:30 +0000393/*--------------------------------------------------------------------*/
394/*--- Instrument IR to perform memory checking operations. ---*/
395/*--- mc_translate.c ---*/
396/*--------------------------------------------------------------------*/
397
398/*
399 This file is part of MemCheck, a heavyweight Valgrind tool for
400 detecting memory errors.
401
402 Copyright (C) 2000-2004 Julian Seward
403 jseward@acm.org
404
405 This program is free software; you can redistribute it and/or
406 modify it under the terms of the GNU General Public License as
407 published by the Free Software Foundation; either version 2 of the
408 License, or (at your option) any later version.
409
410 This program is distributed in the hope that it will be useful, but
411 WITHOUT ANY WARRANTY; without even the implied warranty of
412 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
413 General Public License for more details.
414
415 You should have received a copy of the GNU General Public License
416 along with this program; if not, write to the Free Software
417 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
418 02111-1307, USA.
419
420 The GNU General Public License is contained in the file COPYING.
421*/
422
423//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000424
425
426/*------------------------------------------------------------*/
427/*--- Forward decls ---*/
428/*------------------------------------------------------------*/
429
430struct _MCEnv;
431
432static IRType shadowType ( IRType ty );
433static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
434
435
436/*------------------------------------------------------------*/
437/*--- Memcheck running state, and tmp management. ---*/
438/*------------------------------------------------------------*/
439
440/* Carries around state during memcheck instrumentation. */
441typedef
442 struct _MCEnv {
443 /* MODIFIED: the bb being constructed. IRStmts are added. */
444 IRBB* bb;
445
446 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
447 original temps to their current their current shadow temp.
448 Initially all entries are IRTemp_INVALID. Entries are added
449 lazily since many original temps are not used due to
450 optimisation prior to instrumentation. Note that floating
451 point original tmps are shadowed by integer tmps of the same
452 size, and Bit-typed original tmps are shadowed by the type
453 Ity_I8. See comment below. */
454 IRTemp* tmpMap;
455 Int n_originalTmps; /* for range checking */
456
457 /* READONLY: the guest layout. This indicates which parts of
458 the guest state should be regarded as 'always defined'. */
459 VexGuestLayout* layout;
460 /* READONLY: the host word type. Needed for constructing
461 arguments of type 'HWord' to be passed to helper functions.
462 Ity_I32 or Ity_I64 only. */
463 IRType hWordTy;
464 }
465 MCEnv;
466
467/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
468 demand), as they are encountered. This is for two reasons.
469
470 (1) (less important reason): Many original tmps are unused due to
471 initial IR optimisation, and we do not want to spaces in tables
472 tracking them.
473
474 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
475 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000476 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000477 It is necessary to support making multiple assignments to a shadow
478 -- specifically, after testing a shadow for definedness, it needs
479 to be made defined. But IR's SSA property disallows this.
480
481 (2) (more important reason): Therefore, when a shadow needs to get
482 a new value, a new temporary is created, the value is assigned to
483 that, and the tmpMap is updated to reflect the new binding.
484
485 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000486 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000487 there's a read-before-write error in the original tmps. The IR
488 sanity checker should catch all such anomalies, however.
489*/
490
491/* Find the tmp currently shadowing the given original tmp. If none
492 so far exists, allocate one. */
493static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
494{
sewardj69f9e3e2004-12-30 02:05:34 +0000495 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000496 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000497 mce->tmpMap[orig]
498 = newIRTemp(mce->bb->tyenv,
499 shadowType(mce->bb->tyenv->types[orig]));
500 }
501 return mce->tmpMap[orig];
502}
503
504/* Allocate a new shadow for the given original tmp. This means any
505 previous shadow is abandoned. This is needed because it is
506 necessary to give a new value to a shadow once it has been tested
507 for undefinedness, but unfortunately IR's SSA property disallows
508 this. Instead we must abandon the old shadow, allocate a new one
509 and use that instead. */
510static void newShadowTmp ( MCEnv* mce, IRTemp orig )
511{
sewardj69f9e3e2004-12-30 02:05:34 +0000512 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000513 mce->tmpMap[orig]
514 = newIRTemp(mce->bb->tyenv,
515 shadowType(mce->bb->tyenv->types[orig]));
516}
517
518
519/*------------------------------------------------------------*/
520/*--- IRAtoms -- a subset of IRExprs ---*/
521/*------------------------------------------------------------*/
522
523/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj496a58d2005-03-20 18:44:44 +0000524 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardjde8a5ae2004-11-06 14:20:54 +0000525 input, most of this code deals in atoms. Usefully, a value atom
526 always has a V-value which is also an atom: constants are shadowed
527 by constants, and temps are shadowed by the corresponding shadow
528 temporary. */
529
530typedef IRExpr IRAtom;
531
532/* (used for sanity checks only): is this an atom which looks
533 like it's from original code? */
534static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
535{
536 if (a1->tag == Iex_Const)
537 return True;
538 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
539 return True;
540 return False;
541}
542
543/* (used for sanity checks only): is this an atom which looks
544 like it's from shadow code? */
545static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
546{
547 if (a1->tag == Iex_Const)
548 return True;
549 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
550 return True;
551 return False;
552}
553
554/* (used for sanity checks only): check that both args are atoms and
555 are identically-kinded. */
556static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
557{
558 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
559 return True;
560 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
561 return True;
562 return False;
563}
564
565
566/*------------------------------------------------------------*/
567/*--- Type management ---*/
568/*------------------------------------------------------------*/
569
570/* Shadow state is always accessed using integer types. This returns
571 an integer type with the same size (as per sizeofIRType) as the
572 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000573 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000574
575static IRType shadowType ( IRType ty )
576{
577 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000578 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000579 case Ity_I8:
580 case Ity_I16:
581 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000582 case Ity_I64: return ty;
583 case Ity_F32: return Ity_I32;
584 case Ity_F64: return Ity_I64;
585 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000586 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000587 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000588 }
589}
590
591/* Produce a 'defined' value of the given shadow type. Should only be
592 supplied shadow types (Bit/I8/I16/I32/UI64). */
593static IRExpr* definedOfType ( IRType ty ) {
594 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000595 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
596 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
597 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
598 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
599 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
600 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
601 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000602 }
603}
604
605
606/*------------------------------------------------------------*/
607/*--- Constructing IR fragments ---*/
608/*------------------------------------------------------------*/
609
610/* assign value to tmp */
611#define assign(_bb,_tmp,_expr) \
612 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
613
614/* add stmt to a bb */
615#define stmt(_bb,_stmt) \
616 addStmtToIRBB((_bb), (_stmt))
617
618/* build various kinds of expressions */
619#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
620#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
621#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
622#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
623#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
624#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000625#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardjde8a5ae2004-11-06 14:20:54 +0000626#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
627
628/* bind the given expression to a new temporary, and return the
629 temporary. This effectively converts an arbitrary expression into
630 an atom. */
631static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
632 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
633 assign(mce->bb, t, e);
634 return mkexpr(t);
635}
636
637
638/*------------------------------------------------------------*/
639/*--- Constructing definedness primitive ops ---*/
640/*------------------------------------------------------------*/
641
642/* --------- Defined-if-either-defined --------- */
643
644static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000645 tl_assert(isShadowAtom(mce,a1));
646 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000647 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
648}
649
650static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000651 tl_assert(isShadowAtom(mce,a1));
652 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000653 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
654}
655
656static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000657 tl_assert(isShadowAtom(mce,a1));
658 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000659 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
660}
661
sewardj69f9e3e2004-12-30 02:05:34 +0000662static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
663 tl_assert(isShadowAtom(mce,a1));
664 tl_assert(isShadowAtom(mce,a2));
665 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
666}
667
sewardjf0c1c582005-02-07 23:47:38 +0000668static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000669 tl_assert(isShadowAtom(mce,a1));
670 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000671 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000672}
673
sewardjde8a5ae2004-11-06 14:20:54 +0000674/* --------- Undefined-if-either-undefined --------- */
675
676static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000677 tl_assert(isShadowAtom(mce,a1));
678 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000679 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
680}
681
682static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000683 tl_assert(isShadowAtom(mce,a1));
684 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000685 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
686}
687
688static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000689 tl_assert(isShadowAtom(mce,a1));
690 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000691 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
692}
693
694static IRAtom* mkUifU64 ( 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_I64, binop(Iop_Or64, a1, a2));
698}
699
sewardjf0c1c582005-02-07 23:47:38 +0000700static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000701 tl_assert(isShadowAtom(mce,a1));
702 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000703 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000704}
705
706static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000707 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000708 case Ity_I8: return mkUifU8(mce, a1, a2);
709 case Ity_I16: return mkUifU16(mce, a1, a2);
710 case Ity_I32: return mkUifU32(mce, a1, a2);
711 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardjf0c1c582005-02-07 23:47:38 +0000712 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000713 default:
714 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000715 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000716 }
717}
718
719/* --------- The Left-family of operations. --------- */
720
721static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000722 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000723 /* It's safe to duplicate a1 since it's only an atom */
724 return assignNew(mce, Ity_I8,
725 binop(Iop_Or8, a1,
726 assignNew(mce, Ity_I8,
727 /* unop(Iop_Neg8, a1)))); */
728 binop(Iop_Sub8, mkU8(0), a1) )));
729}
730
731static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000732 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000733 /* It's safe to duplicate a1 since it's only an atom */
734 return assignNew(mce, Ity_I16,
735 binop(Iop_Or16, a1,
736 assignNew(mce, Ity_I16,
737 /* unop(Iop_Neg16, a1)))); */
738 binop(Iop_Sub16, mkU16(0), a1) )));
739}
740
741static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000742 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000743 /* It's safe to duplicate a1 since it's only an atom */
744 return assignNew(mce, Ity_I32,
745 binop(Iop_Or32, a1,
746 assignNew(mce, Ity_I32,
747 /* unop(Iop_Neg32, a1)))); */
748 binop(Iop_Sub32, mkU32(0), a1) )));
749}
750
751/* --------- 'Improvement' functions for AND/OR. --------- */
752
753/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
754 defined (0); all other -> undefined (1).
755*/
756static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
757{
sewardj69f9e3e2004-12-30 02:05:34 +0000758 tl_assert(isOriginalAtom(mce, data));
759 tl_assert(isShadowAtom(mce, vbits));
760 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000761 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
762}
763
sewardj3598ef92004-11-11 02:13:30 +0000764static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
765{
sewardj69f9e3e2004-12-30 02:05:34 +0000766 tl_assert(isOriginalAtom(mce, data));
767 tl_assert(isShadowAtom(mce, vbits));
768 tl_assert(sameKindedAtoms(data, vbits));
sewardj3598ef92004-11-11 02:13:30 +0000769 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
770}
771
sewardjde8a5ae2004-11-06 14:20:54 +0000772static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
773{
sewardj69f9e3e2004-12-30 02:05:34 +0000774 tl_assert(isOriginalAtom(mce, data));
775 tl_assert(isShadowAtom(mce, vbits));
776 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000777 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
778}
779
sewardj69f9e3e2004-12-30 02:05:34 +0000780static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
781{
782 tl_assert(isOriginalAtom(mce, data));
783 tl_assert(isShadowAtom(mce, vbits));
784 tl_assert(sameKindedAtoms(data, vbits));
785 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
786}
787
sewardjf0c1c582005-02-07 23:47:38 +0000788static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000789{
790 tl_assert(isOriginalAtom(mce, data));
791 tl_assert(isShadowAtom(mce, vbits));
792 tl_assert(sameKindedAtoms(data, vbits));
sewardjf0c1c582005-02-07 23:47:38 +0000793 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj69f9e3e2004-12-30 02:05:34 +0000794}
795
sewardjde8a5ae2004-11-06 14:20:54 +0000796/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
797 defined (0); all other -> undefined (1).
798*/
799static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
800{
sewardj69f9e3e2004-12-30 02:05:34 +0000801 tl_assert(isOriginalAtom(mce, data));
802 tl_assert(isShadowAtom(mce, vbits));
803 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000804 return assignNew(
805 mce, Ity_I8,
806 binop(Iop_Or8,
807 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
808 vbits) );
809}
810
811static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
812{
sewardj69f9e3e2004-12-30 02:05:34 +0000813 tl_assert(isOriginalAtom(mce, data));
814 tl_assert(isShadowAtom(mce, vbits));
815 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000816 return assignNew(
817 mce, Ity_I16,
818 binop(Iop_Or16,
819 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
820 vbits) );
821}
822
823static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
824{
sewardj69f9e3e2004-12-30 02:05:34 +0000825 tl_assert(isOriginalAtom(mce, data));
826 tl_assert(isShadowAtom(mce, vbits));
827 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000828 return assignNew(
829 mce, Ity_I32,
830 binop(Iop_Or32,
831 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
832 vbits) );
833}
834
sewardj69f9e3e2004-12-30 02:05:34 +0000835static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
836{
837 tl_assert(isOriginalAtom(mce, data));
838 tl_assert(isShadowAtom(mce, vbits));
839 tl_assert(sameKindedAtoms(data, vbits));
840 return assignNew(
841 mce, Ity_I64,
842 binop(Iop_Or64,
843 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
844 vbits) );
845}
846
sewardjf0c1c582005-02-07 23:47:38 +0000847static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000848{
849 tl_assert(isOriginalAtom(mce, data));
850 tl_assert(isShadowAtom(mce, vbits));
851 tl_assert(sameKindedAtoms(data, vbits));
852 return assignNew(
853 mce, Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +0000854 binop(Iop_OrV128,
855 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj69f9e3e2004-12-30 02:05:34 +0000856 vbits) );
857}
858
sewardjde8a5ae2004-11-06 14:20:54 +0000859/* --------- Pessimising casts. --------- */
860
861static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
862{
sewardj8fc93742004-11-22 11:29:33 +0000863 IRType ty;
864 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000865 /* Note, dst_ty is a shadow type, not an original type. */
866 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000867 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000868 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
869 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000870 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000871 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000872 tmp1 = vbits;
873 break;
874 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000875 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000876 break;
877 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000878 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000879 break;
880 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000881 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000882 break;
883 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000884 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000885 break;
886 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000887 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000888 }
sewardj69f9e3e2004-12-30 02:05:34 +0000889 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000890 /* Now widen up to the dst type. */
891 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000892 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000893 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000894 case Ity_I8:
895 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000896 case Ity_I16:
897 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
898 case Ity_I32:
899 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
900 case Ity_I64:
901 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000902 case Ity_V128:
903 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardjf0c1c582005-02-07 23:47:38 +0000904 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000905 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000906 default:
907 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000908 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +0000909 }
910}
911
912
913/*------------------------------------------------------------*/
914/*--- Emit a test and complaint if something is undefined. ---*/
915/*------------------------------------------------------------*/
916
917/* Set the annotations on a dirty helper to indicate that the stack
918 pointer and instruction pointers might be read. This is the
919 behaviour of all 'emit-a-complaint' style functions we might
920 call. */
921
922static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
923 di->nFxState = 2;
924 di->fxState[0].fx = Ifx_Read;
925 di->fxState[0].offset = mce->layout->offset_SP;
926 di->fxState[0].size = mce->layout->sizeof_SP;
927 di->fxState[1].fx = Ifx_Read;
928 di->fxState[1].offset = mce->layout->offset_IP;
929 di->fxState[1].size = mce->layout->sizeof_IP;
930}
931
932
933/* Check the supplied **original** atom for undefinedness, and emit a
934 complaint if so. Once that happens, mark it as defined. This is
935 possible because the atom is either a tmp or literal. If it's a
936 tmp, it will be shadowed by a tmp, and so we can set the shadow to
937 be defined. In fact as mentioned above, we will have to allocate a
938 new tmp to carry the new 'defined' shadow value, and update the
939 original->tmp mapping accordingly; we cannot simply assign a new
940 value to an existing shadow tmp as this breaks SSAness -- resulting
941 in the post-instrumentation sanity checker spluttering in disapproval.
942*/
943static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
944{
sewardj8fc93742004-11-22 11:29:33 +0000945 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +0000946 IRType ty;
947 Int sz;
sewardj8fc93742004-11-22 11:29:33 +0000948 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +0000949 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +0000950
sewardjde8a5ae2004-11-06 14:20:54 +0000951 /* Since the original expression is atomic, there's no duplicated
952 work generated by making multiple V-expressions for it. So we
953 don't really care about the possibility that someone else may
954 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +0000955 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +0000956 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +0000957 tl_assert(isShadowAtom(mce, vatom));
958 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +0000959
sewardj8fc93742004-11-22 11:29:33 +0000960 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +0000961
962 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +0000963 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +0000964
sewardj8fc93742004-11-22 11:29:33 +0000965 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +0000966 /* cond will be 0 if all defined, and 1 if any not defined. */
967
sewardj3598ef92004-11-11 02:13:30 +0000968 switch (sz) {
969 case 0:
970 di = unsafeIRDirty_0_N( 0/*regparms*/,
971 "MC_(helperc_value_check0_fail)",
972 &MC_(helperc_value_check0_fail),
973 mkIRExprVec_0()
974 );
975 break;
976 case 1:
977 di = unsafeIRDirty_0_N( 0/*regparms*/,
978 "MC_(helperc_value_check1_fail)",
979 &MC_(helperc_value_check1_fail),
980 mkIRExprVec_0()
981 );
982 break;
983 case 4:
984 di = unsafeIRDirty_0_N( 0/*regparms*/,
985 "MC_(helperc_value_check4_fail)",
986 &MC_(helperc_value_check4_fail),
987 mkIRExprVec_0()
988 );
989 break;
990 default:
991 di = unsafeIRDirty_0_N( 1/*regparms*/,
992 "MC_(helperc_complain_undef)",
993 &MC_(helperc_complain_undef),
994 mkIRExprVec_1( mkIRExpr_HWord( sz ))
995 );
996 break;
997 }
sewardjde8a5ae2004-11-06 14:20:54 +0000998 di->guard = cond;
999 setHelperAnns( mce, di );
1000 stmt( mce->bb, IRStmt_Dirty(di));
1001
1002 /* Set the shadow tmp to be defined. First, update the
1003 orig->shadow tmp mapping to reflect the fact that this shadow is
1004 getting a new value. */
sewardj496a58d2005-03-20 18:44:44 +00001005 tl_assert(isIRAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001006 /* sameKindedAtoms ... */
1007 if (vatom->tag == Iex_Tmp) {
sewardj69f9e3e2004-12-30 02:05:34 +00001008 tl_assert(atom->tag == Iex_Tmp);
sewardjde8a5ae2004-11-06 14:20:54 +00001009 newShadowTmp(mce, atom->Iex.Tmp.tmp);
1010 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
1011 definedOfType(ty));
1012 }
1013}
1014
1015
1016/*------------------------------------------------------------*/
1017/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
1018/*------------------------------------------------------------*/
1019
1020/* Examine the always-defined sections declared in layout to see if
1021 the (offset,size) section is within one. Note, is is an error to
1022 partially fall into such a region: (offset,size) should either be
1023 completely in such a region or completely not-in such a region.
1024*/
1025static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1026{
1027 Int minoffD, maxoffD, i;
1028 Int minoff = offset;
1029 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001030 tl_assert((minoff & ~0xFFFF) == 0);
1031 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001032
1033 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1034 minoffD = mce->layout->alwaysDefd[i].offset;
1035 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001036 tl_assert((minoffD & ~0xFFFF) == 0);
1037 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001038
1039 if (maxoff < minoffD || maxoffD < minoff)
1040 continue; /* no overlap */
1041 if (minoff >= minoffD && maxoff <= maxoffD)
1042 return True; /* completely contained in an always-defd section */
1043
sewardj69f9e3e2004-12-30 02:05:34 +00001044 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001045 }
1046 return False; /* could not find any containing section */
1047}
1048
1049
1050/* Generate into bb suitable actions to shadow this Put. If the state
1051 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001052 supplied V bits to the shadow state. We can pass in either an
1053 original atom or a V-atom, but not both. In the former case the
1054 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001055*/
1056static
sewardj3598ef92004-11-11 02:13:30 +00001057void do_shadow_PUT ( MCEnv* mce, Int offset,
1058 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001059{
sewardj8fc93742004-11-22 11:29:33 +00001060 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001061 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001062 tl_assert(!vatom);
1063 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001064 vatom = expr2vbits( mce, atom );
1065 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001066 tl_assert(vatom);
1067 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001068 }
1069
sewardj8fc93742004-11-22 11:29:33 +00001070 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001071 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001072 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1073 /* later: no ... */
1074 /* emit code to emit a complaint if any of the vbits are 1. */
1075 /* complainIfUndefined(mce, atom); */
1076 } else {
1077 /* Do a plain shadow Put. */
1078 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1079 }
1080}
1081
1082
1083/* Return an expression which contains the V bits corresponding to the
1084 given GETI (passed in in pieces).
1085*/
1086static
1087void do_shadow_PUTI ( MCEnv* mce,
1088 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
1089{
sewardj8fc93742004-11-22 11:29:33 +00001090 IRAtom* vatom;
1091 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001092 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001093
sewardj69f9e3e2004-12-30 02:05:34 +00001094 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001095 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001096 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001097 ty = descr->elemTy;
1098 tyS = shadowType(ty);
1099 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001100 tl_assert(ty != Ity_I1);
1101 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001102 complainIfUndefined(mce,ix);
1103 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1104 /* later: no ... */
1105 /* emit code to emit a complaint if any of the vbits are 1. */
1106 /* complainIfUndefined(mce, atom); */
1107 } else {
1108 /* Do a cloned version of the Put that refers to the shadow
1109 area. */
1110 IRArray* new_descr
1111 = mkIRArray( descr->base + mce->layout->total_sizeB,
1112 tyS, descr->nElems);
1113 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1114 }
1115}
1116
1117
1118/* Return an expression which contains the V bits corresponding to the
1119 given GET (passed in in pieces).
1120*/
1121static
1122IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1123{
1124 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001125 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001126 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1127 /* Always defined, return all zeroes of the relevant type */
1128 return definedOfType(tyS);
1129 } else {
1130 /* return a cloned version of the Get that refers to the shadow
1131 area. */
1132 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1133 }
1134}
1135
1136
1137/* Return an expression which contains the V bits corresponding to the
1138 given GETI (passed in in pieces).
1139*/
1140static
1141IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
1142{
1143 IRType ty = descr->elemTy;
1144 IRType tyS = shadowType(ty);
1145 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001146 tl_assert(ty != Ity_I1);
1147 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001148 complainIfUndefined(mce,ix);
1149 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1150 /* Always defined, return all zeroes of the relevant type */
1151 return definedOfType(tyS);
1152 } else {
1153 /* return a cloned version of the Get that refers to the shadow
1154 area. */
1155 IRArray* new_descr
1156 = mkIRArray( descr->base + mce->layout->total_sizeB,
1157 tyS, descr->nElems);
1158 return IRExpr_GetI( new_descr, ix, bias );
1159 }
1160}
1161
1162
1163/*------------------------------------------------------------*/
1164/*--- Generating approximations for unknown operations, ---*/
1165/*--- using lazy-propagate semantics ---*/
1166/*------------------------------------------------------------*/
1167
1168/* Lazy propagation of undefinedness from two values, resulting in the
1169 specified shadow type.
1170*/
1171static
1172IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1173{
1174 /* force everything via 32-bit intermediaries. */
1175 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001176 tl_assert(isShadowAtom(mce,va1));
1177 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001178 at = mkPCastTo(mce, Ity_I32, va1);
1179 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1180 at = mkPCastTo(mce, finalVty, at);
1181 return at;
1182}
1183
1184
1185/* Do the lazy propagation game from a null-terminated vector of
1186 atoms. This is presumably the arguments to a helper call, so the
1187 IRCallee info is also supplied in order that we can know which
1188 arguments should be ignored (via the .mcx_mask field).
1189*/
1190static
1191IRAtom* mkLazyN ( MCEnv* mce,
1192 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1193{
1194 Int i;
1195 IRAtom* here;
1196 IRAtom* curr = definedOfType(Ity_I32);
1197 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001198 tl_assert(i < 32);
1199 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001200 /* Only take notice of this arg if the callee's mc-exclusion
1201 mask does not say it is to be excluded. */
1202 if (cee->mcx_mask & (1<<i)) {
1203 /* the arg is to be excluded from definedness checking. Do
1204 nothing. */
1205 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1206 } else {
1207 /* calculate the arg's definedness, and pessimistically merge
1208 it in. */
1209 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1210 curr = mkUifU32(mce, here, curr);
1211 }
1212 }
1213 return mkPCastTo(mce, finalVtype, curr );
1214}
1215
1216
1217/*------------------------------------------------------------*/
1218/*--- Generating expensive sequences for exact carry-chain ---*/
1219/*--- propagation in add/sub and related operations. ---*/
1220/*------------------------------------------------------------*/
1221
1222static
1223IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1224 IRAtom* aa, IRAtom* bb )
1225{
sewardj69f9e3e2004-12-30 02:05:34 +00001226 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001227 IRType ty;
1228 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001229
sewardj69f9e3e2004-12-30 02:05:34 +00001230 tl_assert(isShadowAtom(mce,qaa));
1231 tl_assert(isShadowAtom(mce,qbb));
1232 tl_assert(isOriginalAtom(mce,aa));
1233 tl_assert(isOriginalAtom(mce,bb));
1234 tl_assert(sameKindedAtoms(qaa,aa));
1235 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001236
sewardj8fc93742004-11-22 11:29:33 +00001237 ty = Ity_I32;
1238 opAND = Iop_And32;
1239 opOR = Iop_Or32;
1240 opXOR = Iop_Xor32;
1241 opNOT = Iop_Not32;
1242 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001243
1244 // a_min = aa & ~qaa
1245 a_min = assignNew(mce,ty,
1246 binop(opAND, aa,
1247 assignNew(mce,ty, unop(opNOT, qaa))));
1248
1249 // b_min = bb & ~qbb
1250 b_min = assignNew(mce,ty,
1251 binop(opAND, bb,
1252 assignNew(mce,ty, unop(opNOT, qbb))));
1253
1254 // a_max = aa | qaa
1255 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1256
1257 // b_max = bb | qbb
1258 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1259
1260 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1261 return
1262 assignNew(mce,ty,
1263 binop( opOR,
1264 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1265 assignNew(mce,ty,
1266 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1267 assignNew(mce,ty, binop(opADD, a_max, b_max))
1268 )
1269 )
1270 )
1271 );
1272}
1273
1274
1275/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001276/*--- Helpers for dealing with vector primops. ---*/
1277/*------------------------------------------------------------*/
1278
1279/* Vector pessimisation -- pessimise within each lane individually. */
1280
1281static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1282{
1283 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1284}
1285
1286static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1287{
1288 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1289}
1290
1291static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1292{
1293 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1294}
1295
1296static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1297{
1298 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1299}
1300
1301
1302/* Here's a simple scheme capable of handling ops derived from SSE1
1303 code and while only generating ops that can be efficiently
1304 implemented in SSE1. */
1305
1306/* All-lanes versions are straightforward:
1307
sewardjf0c1c582005-02-07 23:47:38 +00001308 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj69f9e3e2004-12-30 02:05:34 +00001309
1310 unary32Fx4(x,y) ==> PCast32x4(x#)
1311
1312 Lowest-lane-only versions are more complex:
1313
sewardjf0c1c582005-02-07 23:47:38 +00001314 binary32F0x4(x,y) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001315 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001316 PCast32(V128to32(UifUV128(x#,y#)))
sewardj69f9e3e2004-12-30 02:05:34 +00001317 )
1318
1319 This is perhaps not so obvious. In particular, it's faster to
sewardjf0c1c582005-02-07 23:47:38 +00001320 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj69f9e3e2004-12-30 02:05:34 +00001321 obvious scheme of taking the bottom 32 bits of each operand
1322 and doing a 32-bit UifU. Basically since UifU is fast and
1323 chopping lanes off vector values is slow.
1324
1325 Finally:
1326
sewardjf0c1c582005-02-07 23:47:38 +00001327 unary32F0x4(x) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001328 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001329 PCast32(V128to32(x#))
sewardj69f9e3e2004-12-30 02:05:34 +00001330 )
1331
1332 Where:
1333
1334 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1335 PCast32x4(v#) = CmpNEZ32x4(v#)
1336*/
1337
1338static
1339IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1340{
1341 IRAtom* at;
1342 tl_assert(isShadowAtom(mce, vatomX));
1343 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001344 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001345 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1346 return at;
1347}
1348
1349static
1350IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1351{
1352 IRAtom* at;
1353 tl_assert(isShadowAtom(mce, vatomX));
1354 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1355 return at;
1356}
1357
1358static
1359IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1360{
1361 IRAtom* at;
1362 tl_assert(isShadowAtom(mce, vatomX));
1363 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001364 at = mkUifUV128(mce, vatomX, vatomY);
1365 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001366 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001367 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001368 return at;
1369}
1370
1371static
1372IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1373{
1374 IRAtom* at;
1375 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001376 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001377 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001378 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001379 return at;
1380}
1381
1382/* --- ... and ... 64Fx2 versions of the same ... --- */
1383
1384static
1385IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1386{
1387 IRAtom* at;
1388 tl_assert(isShadowAtom(mce, vatomX));
1389 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001390 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001391 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1392 return at;
1393}
1394
1395static
1396IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1397{
1398 IRAtom* at;
1399 tl_assert(isShadowAtom(mce, vatomX));
1400 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1401 return at;
1402}
1403
1404static
1405IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1406{
1407 IRAtom* at;
1408 tl_assert(isShadowAtom(mce, vatomX));
1409 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001410 at = mkUifUV128(mce, vatomX, vatomY);
1411 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001412 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001413 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001414 return at;
1415}
1416
1417static
1418IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1419{
1420 IRAtom* at;
1421 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001422 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001423 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001424 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001425 return at;
1426}
1427
1428/* --- --- Vector saturated narrowing --- --- */
1429
1430/* This is quite subtle. What to do is simple:
1431
1432 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1433
1434 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1435
1436 Why this is right is not so simple. Consider a lane in the args,
1437 vatom1 or 2, doesn't matter.
1438
1439 After the PCast, that lane is all 0s (defined) or all
1440 1s(undefined).
1441
1442 Both signed and unsigned saturating narrowing of all 0s produces
1443 all 0s, which is what we want.
1444
1445 The all-1s case is more complex. Unsigned narrowing interprets an
1446 all-1s input as the largest unsigned integer, and so produces all
1447 1s as a result since that is the largest unsigned value at the
1448 smaller width.
1449
1450 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1451 to -1, so we still wind up with all 1s at the smaller width.
1452
1453 So: In short, pessimise the args, then apply the original narrowing
1454 op.
1455*/
1456static
sewardjf0c1c582005-02-07 23:47:38 +00001457IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardj69f9e3e2004-12-30 02:05:34 +00001458 IRAtom* vatom1, IRAtom* vatom2)
1459{
1460 IRAtom *at1, *at2, *at3;
1461 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1462 switch (narrow_op) {
1463 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1464 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1465 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardjf0c1c582005-02-07 23:47:38 +00001466 default: VG_(tool_panic)("vectorNarrowV128");
sewardj69f9e3e2004-12-30 02:05:34 +00001467 }
1468 tl_assert(isShadowAtom(mce,vatom1));
1469 tl_assert(isShadowAtom(mce,vatom2));
1470 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1471 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1472 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1473 return at3;
1474}
1475
1476
1477/* --- --- Vector integer arithmetic --- --- */
1478
1479/* Simple ... UifU the args and per-lane pessimise the results. */
1480static
1481IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1482{
1483 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001484 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001485 at = mkPCast8x16(mce, at);
1486 return at;
1487}
1488
1489static
1490IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1491{
1492 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001493 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001494 at = mkPCast16x8(mce, at);
1495 return at;
1496}
1497
1498static
1499IRAtom* binary32Ix4 ( 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 = mkPCast32x4(mce, at);
1504 return at;
1505}
1506
1507static
1508IRAtom* binary64Ix2 ( 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 = mkPCast64x2(mce, at);
1513 return at;
1514}
1515
1516
1517/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001518/*--- Generate shadow values from all kinds of IRExprs. ---*/
1519/*------------------------------------------------------------*/
1520
1521static
1522IRAtom* expr2vbits_Binop ( MCEnv* mce,
1523 IROp op,
1524 IRAtom* atom1, IRAtom* atom2 )
1525{
1526 IRType and_or_ty;
1527 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1528 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1529 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1530
1531 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1532 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1533
sewardj69f9e3e2004-12-30 02:05:34 +00001534 tl_assert(isOriginalAtom(mce,atom1));
1535 tl_assert(isOriginalAtom(mce,atom2));
1536 tl_assert(isShadowAtom(mce,vatom1));
1537 tl_assert(isShadowAtom(mce,vatom2));
1538 tl_assert(sameKindedAtoms(atom1,vatom1));
1539 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001540 switch (op) {
1541
sewardjf0c1c582005-02-07 23:47:38 +00001542 /* V128-bit SIMD (SSE2-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001543
1544 case Iop_ShrN16x8:
1545 case Iop_ShrN32x4:
1546 case Iop_ShrN64x2:
1547 case Iop_SarN16x8:
1548 case Iop_SarN32x4:
1549 case Iop_ShlN16x8:
1550 case Iop_ShlN32x4:
1551 case Iop_ShlN64x2:
1552 /* Same scheme as with all other shifts. */
1553 complainIfUndefined(mce, atom2);
1554 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1555
1556 case Iop_QSub8Ux16:
1557 case Iop_QSub8Sx16:
1558 case Iop_Sub8x16:
1559 case Iop_Min8Ux16:
1560 case Iop_Max8Ux16:
1561 case Iop_CmpGT8Sx16:
1562 case Iop_CmpEQ8x16:
1563 case Iop_Avg8Ux16:
1564 case Iop_QAdd8Ux16:
1565 case Iop_QAdd8Sx16:
1566 case Iop_Add8x16:
1567 return binary8Ix16(mce, vatom1, vatom2);
1568
1569 case Iop_QSub16Ux8:
1570 case Iop_QSub16Sx8:
1571 case Iop_Sub16x8:
1572 case Iop_Mul16x8:
1573 case Iop_MulHi16Sx8:
1574 case Iop_MulHi16Ux8:
1575 case Iop_Min16Sx8:
1576 case Iop_Max16Sx8:
1577 case Iop_CmpGT16Sx8:
1578 case Iop_CmpEQ16x8:
1579 case Iop_Avg16Ux8:
1580 case Iop_QAdd16Ux8:
1581 case Iop_QAdd16Sx8:
1582 case Iop_Add16x8:
1583 return binary16Ix8(mce, vatom1, vatom2);
1584
1585 case Iop_Sub32x4:
1586 case Iop_CmpGT32Sx4:
1587 case Iop_CmpEQ32x4:
1588 case Iop_Add32x4:
1589 return binary32Ix4(mce, vatom1, vatom2);
1590
1591 case Iop_Sub64x2:
1592 case Iop_Add64x2:
1593 return binary64Ix2(mce, vatom1, vatom2);
1594
1595 case Iop_QNarrow32Sx4:
1596 case Iop_QNarrow16Sx8:
1597 case Iop_QNarrow16Ux8:
sewardjf0c1c582005-02-07 23:47:38 +00001598 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001599
1600 case Iop_Sub64Fx2:
1601 case Iop_Mul64Fx2:
1602 case Iop_Min64Fx2:
1603 case Iop_Max64Fx2:
1604 case Iop_Div64Fx2:
1605 case Iop_CmpLT64Fx2:
1606 case Iop_CmpLE64Fx2:
1607 case Iop_CmpEQ64Fx2:
1608 case Iop_Add64Fx2:
1609 return binary64Fx2(mce, vatom1, vatom2);
1610
1611 case Iop_Sub64F0x2:
1612 case Iop_Mul64F0x2:
1613 case Iop_Min64F0x2:
1614 case Iop_Max64F0x2:
1615 case Iop_Div64F0x2:
1616 case Iop_CmpLT64F0x2:
1617 case Iop_CmpLE64F0x2:
1618 case Iop_CmpEQ64F0x2:
1619 case Iop_Add64F0x2:
1620 return binary64F0x2(mce, vatom1, vatom2);
1621
sewardjf0c1c582005-02-07 23:47:38 +00001622 /* V128-bit SIMD (SSE1-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001623
1624 case Iop_Sub32Fx4:
1625 case Iop_Mul32Fx4:
1626 case Iop_Min32Fx4:
1627 case Iop_Max32Fx4:
1628 case Iop_Div32Fx4:
1629 case Iop_CmpLT32Fx4:
1630 case Iop_CmpLE32Fx4:
1631 case Iop_CmpEQ32Fx4:
1632 case Iop_Add32Fx4:
1633 return binary32Fx4(mce, vatom1, vatom2);
1634
1635 case Iop_Sub32F0x4:
1636 case Iop_Mul32F0x4:
1637 case Iop_Min32F0x4:
1638 case Iop_Max32F0x4:
1639 case Iop_Div32F0x4:
1640 case Iop_CmpLT32F0x4:
1641 case Iop_CmpLE32F0x4:
1642 case Iop_CmpEQ32F0x4:
1643 case Iop_Add32F0x4:
1644 return binary32F0x4(mce, vatom1, vatom2);
1645
sewardjf0c1c582005-02-07 23:47:38 +00001646 /* V128-bit data-steering */
1647 case Iop_SetV128lo32:
1648 case Iop_SetV128lo64:
1649 case Iop_64HLtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001650 case Iop_InterleaveLO64x2:
1651 case Iop_InterleaveLO32x4:
1652 case Iop_InterleaveLO16x8:
1653 case Iop_InterleaveLO8x16:
1654 case Iop_InterleaveHI64x2:
1655 case Iop_InterleaveHI32x4:
1656 case Iop_InterleaveHI16x8:
1657 case Iop_InterleaveHI8x16:
1658 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1659
1660 /* Scalar floating point */
1661
sewardj3598ef92004-11-11 02:13:30 +00001662 case Iop_RoundF64:
1663 case Iop_F64toI64:
sewardj69f9e3e2004-12-30 02:05:34 +00001664 case Iop_I64toF64:
1665 /* First arg is I32 (rounding mode), second is F64 or I64
1666 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001667 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1668
1669 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1670 /* Takes two F64 args. */
sewardjde8a5ae2004-11-06 14:20:54 +00001671 case Iop_F64toI32:
sewardj69f9e3e2004-12-30 02:05:34 +00001672 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001673 /* First arg is I32 (rounding mode), second is F64 (data). */
1674 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1675
1676 case Iop_F64toI16:
1677 /* First arg is I32 (rounding mode), second is F64 (data). */
1678 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1679
sewardj3598ef92004-11-11 02:13:30 +00001680 case Iop_ScaleF64:
1681 case Iop_Yl2xF64:
1682 case Iop_Yl2xp1F64:
1683 case Iop_PRemF64:
1684 case Iop_AtanF64:
1685 case Iop_AddF64:
1686 case Iop_DivF64:
1687 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001688 case Iop_MulF64:
1689 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1690
sewardj3598ef92004-11-11 02:13:30 +00001691 case Iop_CmpF64:
1692 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1693
sewardjde8a5ae2004-11-06 14:20:54 +00001694 /* non-FP after here */
1695
1696 case Iop_DivModU64to32:
1697 case Iop_DivModS64to32:
1698 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1699
sewardj3598ef92004-11-11 02:13:30 +00001700 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001701 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001702 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001703 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001704
1705 case Iop_MullS32:
1706 case Iop_MullU32: {
1707 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1708 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1709 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1710 }
1711
sewardj3598ef92004-11-11 02:13:30 +00001712 case Iop_MullS16:
1713 case Iop_MullU16: {
1714 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1715 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1716 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1717 }
1718
1719 case Iop_MullS8:
1720 case Iop_MullU8: {
1721 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1722 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1723 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1724 }
1725
sewardjde8a5ae2004-11-06 14:20:54 +00001726 case Iop_Add32:
1727# if 0
1728 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1729# endif
1730 case Iop_Sub32:
1731 case Iop_Mul32:
1732 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1733
sewardj3598ef92004-11-11 02:13:30 +00001734 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001735 case Iop_Add16:
1736 case Iop_Sub16:
1737 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1738
1739 case Iop_Sub8:
1740 case Iop_Add8:
1741 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1742
1743 case Iop_CmpLE32S: case Iop_CmpLE32U:
1744 case Iop_CmpLT32U: case Iop_CmpLT32S:
1745 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001746 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001747
sewardj3598ef92004-11-11 02:13:30 +00001748 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001749 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001750
1751 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001752 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001753
1754 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1755 /* Complain if the shift amount is undefined. Then simply
1756 shift the first arg's V bits by the real shift amount. */
1757 complainIfUndefined(mce, atom2);
1758 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1759
sewardj69f9e3e2004-12-30 02:05:34 +00001760 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001761 /* Same scheme as with 32-bit shifts. */
1762 complainIfUndefined(mce, atom2);
1763 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1764
sewardj3598ef92004-11-11 02:13:30 +00001765 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001766 /* Same scheme as with 32-bit shifts. */
1767 complainIfUndefined(mce, atom2);
1768 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1769
1770 case Iop_Shl64: case Iop_Shr64:
1771 /* Same scheme as with 32-bit shifts. */
1772 complainIfUndefined(mce, atom2);
1773 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1774
sewardjf0c1c582005-02-07 23:47:38 +00001775 case Iop_AndV128:
1776 uifu = mkUifUV128; difd = mkDifDV128;
1777 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001778 case Iop_And64:
1779 uifu = mkUifU64; difd = mkDifD64;
1780 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001781 case Iop_And32:
1782 uifu = mkUifU32; difd = mkDifD32;
1783 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001784 case Iop_And16:
1785 uifu = mkUifU16; difd = mkDifD16;
1786 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001787 case Iop_And8:
1788 uifu = mkUifU8; difd = mkDifD8;
1789 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1790
sewardjf0c1c582005-02-07 23:47:38 +00001791 case Iop_OrV128:
1792 uifu = mkUifUV128; difd = mkDifDV128;
1793 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001794 case Iop_Or64:
1795 uifu = mkUifU64; difd = mkDifD64;
1796 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001797 case Iop_Or32:
1798 uifu = mkUifU32; difd = mkDifD32;
1799 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1800 case Iop_Or16:
1801 uifu = mkUifU16; difd = mkDifD16;
1802 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1803 case Iop_Or8:
1804 uifu = mkUifU8; difd = mkDifD8;
1805 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1806
1807 do_And_Or:
1808 return
1809 assignNew(
1810 mce,
1811 and_or_ty,
1812 difd(mce, uifu(mce, vatom1, vatom2),
1813 difd(mce, improve(mce, atom1, vatom1),
1814 improve(mce, atom2, vatom2) ) ) );
1815
1816 case Iop_Xor8:
1817 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001818 case Iop_Xor16:
1819 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001820 case Iop_Xor32:
1821 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001822 case Iop_Xor64:
1823 return mkUifU64(mce, vatom1, vatom2);
sewardjf0c1c582005-02-07 23:47:38 +00001824 case Iop_XorV128:
1825 return mkUifUV128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001826
1827 default:
1828 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001829 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001830 }
1831}
1832
1833
1834static
1835IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1836{
1837 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001838 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001839 switch (op) {
1840
sewardj69f9e3e2004-12-30 02:05:34 +00001841 case Iop_Sqrt64Fx2:
1842 return unary64Fx2(mce, vatom);
1843
1844 case Iop_Sqrt64F0x2:
1845 return unary64F0x2(mce, vatom);
1846
1847 case Iop_Sqrt32Fx4:
1848 case Iop_RSqrt32Fx4:
1849 case Iop_Recip32Fx4:
1850 return unary32Fx4(mce, vatom);
1851
1852 case Iop_Sqrt32F0x4:
1853 case Iop_RSqrt32F0x4:
1854 case Iop_Recip32F0x4:
1855 return unary32F0x4(mce, vatom);
1856
sewardjf0c1c582005-02-07 23:47:38 +00001857 case Iop_32UtoV128:
1858 case Iop_64UtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001859 return assignNew(mce, Ity_V128, unop(op, vatom));
1860
sewardjde8a5ae2004-11-06 14:20:54 +00001861 case Iop_F32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001862 case Iop_I32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001863 case Iop_NegF64:
1864 case Iop_SinF64:
1865 case Iop_CosF64:
1866 case Iop_TanF64:
1867 case Iop_SqrtF64:
1868 case Iop_AbsF64:
1869 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001870 return mkPCastTo(mce, Ity_I64, vatom);
1871
sewardj3598ef92004-11-11 02:13:30 +00001872 case Iop_Clz32:
1873 case Iop_Ctz32:
1874 return mkPCastTo(mce, Ity_I32, vatom);
1875
1876 case Iop_32Sto64:
1877 case Iop_32Uto64:
sewardjf0c1c582005-02-07 23:47:38 +00001878 case Iop_V128to64:
1879 case Iop_V128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001880 return assignNew(mce, Ity_I64, unop(op, vatom));
1881
sewardjde8a5ae2004-11-06 14:20:54 +00001882 case Iop_64to32:
1883 case Iop_64HIto32:
1884 case Iop_1Uto32:
1885 case Iop_8Uto32:
1886 case Iop_16Uto32:
1887 case Iop_16Sto32:
1888 case Iop_8Sto32:
1889 return assignNew(mce, Ity_I32, unop(op, vatom));
1890
1891 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001892 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001893 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001894 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001895 return assignNew(mce, Ity_I16, unop(op, vatom));
1896
1897 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001898 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001899 case Iop_32to8:
1900 return assignNew(mce, Ity_I8, unop(op, vatom));
1901
1902 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001903 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001904
sewardj3598ef92004-11-11 02:13:30 +00001905 case Iop_ReinterpF64asI64:
1906 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001907 case Iop_ReinterpI32asF32:
sewardjf0c1c582005-02-07 23:47:38 +00001908 case Iop_NotV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001909 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00001910 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001911 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001912 case Iop_Not8:
1913 case Iop_Not1:
1914 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001915
sewardjde8a5ae2004-11-06 14:20:54 +00001916 default:
1917 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001918 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00001919 }
1920}
1921
1922
sewardj69f9e3e2004-12-30 02:05:34 +00001923/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00001924static
sewardj69f9e3e2004-12-30 02:05:34 +00001925IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001926{
1927 void* helper;
sewardjde8c9872005-03-25 13:48:55 +00001928 HChar* hname;
sewardjde8a5ae2004-11-06 14:20:54 +00001929 IRDirty* di;
1930 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00001931 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001932
sewardj69f9e3e2004-12-30 02:05:34 +00001933 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00001934
1935 /* First, emit a definedness test for the address. This also sets
1936 the address (shadow) to 'defined' following the test. */
1937 complainIfUndefined( mce, addr );
1938
1939 /* Now cook up a call to the relevant helper function, to read the
1940 data V bits from shadow memory. */
1941 ty = shadowType(ty);
1942 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001943 case Ity_I64: helper = &MC_(helperc_LOADV8);
1944 hname = "MC_(helperc_LOADV8)";
1945 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001946 case Ity_I32: helper = &MC_(helperc_LOADV4);
1947 hname = "MC_(helperc_LOADV4)";
1948 break;
1949 case Ity_I16: helper = &MC_(helperc_LOADV2);
1950 hname = "MC_(helperc_LOADV2)";
1951 break;
1952 case Ity_I8: helper = &MC_(helperc_LOADV1);
1953 hname = "MC_(helperc_LOADV1)";
1954 break;
1955 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001956 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00001957 }
1958
sewardj3598ef92004-11-11 02:13:30 +00001959 /* Generate the actual address into addrAct. */
1960 if (bias == 0) {
1961 addrAct = addr;
1962 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001963 IROp mkAdd;
1964 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00001965 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00001966 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
1967 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1968 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00001969 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1970 }
1971
sewardjde8a5ae2004-11-06 14:20:54 +00001972 /* We need to have a place to park the V bits we're just about to
1973 read. */
1974 datavbits = newIRTemp(mce->bb->tyenv, ty);
1975 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00001976 1/*regparms*/, hname, helper,
1977 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00001978 setHelperAnns( mce, di );
1979 stmt( mce->bb, IRStmt_Dirty(di) );
1980
1981 return mkexpr(datavbits);
1982}
1983
1984
1985static
sewardj69f9e3e2004-12-30 02:05:34 +00001986IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
1987{
1988 IRAtom *v64hi, *v64lo;
1989 switch (shadowType(ty)) {
1990 case Ity_I8:
1991 case Ity_I16:
1992 case Ity_I32:
1993 case Ity_I64:
1994 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
1995 case Ity_V128:
1996 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
1997 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
1998 return assignNew( mce,
1999 Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +00002000 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj69f9e3e2004-12-30 02:05:34 +00002001 default:
2002 VG_(tool_panic)("expr2vbits_LDle");
2003 }
2004}
2005
2006
2007static
sewardjde8a5ae2004-11-06 14:20:54 +00002008IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00002009 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00002010{
2011 IRAtom *vbitsC, *vbits0, *vbitsX;
2012 IRType ty;
2013 /* Given Mux0X(cond,expr0,exprX), generate
2014 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2015 That is, steer the V bits like the originals, but trash the
2016 result if the steering value is undefined. This gives
2017 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00002018 tl_assert(isOriginalAtom(mce, cond));
2019 tl_assert(isOriginalAtom(mce, expr0));
2020 tl_assert(isOriginalAtom(mce, exprX));
sewardjde8a5ae2004-11-06 14:20:54 +00002021
2022 vbitsC = expr2vbits(mce, cond);
2023 vbits0 = expr2vbits(mce, expr0);
2024 vbitsX = expr2vbits(mce, exprX);
2025 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2026
2027 return
2028 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2029 mkPCastTo(mce, ty, vbitsC) );
2030}
2031
2032/* --------- This is the main expression-handling function. --------- */
2033
2034static
2035IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2036{
2037 switch (e->tag) {
2038
2039 case Iex_Get:
2040 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2041
2042 case Iex_GetI:
2043 return shadow_GETI( mce, e->Iex.GetI.descr,
2044 e->Iex.GetI.ix, e->Iex.GetI.bias );
2045
2046 case Iex_Tmp:
2047 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
2048
2049 case Iex_Const:
2050 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2051
2052 case Iex_Binop:
2053 return expr2vbits_Binop(
2054 mce,
2055 e->Iex.Binop.op,
2056 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2057 );
2058
2059 case Iex_Unop:
2060 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2061
2062 case Iex_LDle:
sewardj3598ef92004-11-11 02:13:30 +00002063 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
2064 e->Iex.LDle.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002065
2066 case Iex_CCall:
2067 return mkLazyN( mce, e->Iex.CCall.args,
2068 e->Iex.CCall.retty,
2069 e->Iex.CCall.cee );
2070
2071 case Iex_Mux0X:
2072 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2073 e->Iex.Mux0X.exprX);
2074
2075 default:
2076 VG_(printf)("\n");
2077 ppIRExpr(e);
2078 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002079 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002080 }
2081}
2082
2083/*------------------------------------------------------------*/
2084/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2085/*------------------------------------------------------------*/
2086
2087/* Widen a value to the host word size. */
2088
2089static
2090IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2091{
sewardj69f9e3e2004-12-30 02:05:34 +00002092 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002093
sewardj8fc93742004-11-22 11:29:33 +00002094 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002095 tl_assert(isShadowAtom(mce,vatom));
2096
2097 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2098 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002099
sewardjde8a5ae2004-11-06 14:20:54 +00002100 if (tyH == Ity_I32) {
2101 switch (ty) {
2102 case Ity_I32: return vatom;
2103 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2104 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2105 default: goto unhandled;
2106 }
2107 } else {
2108 goto unhandled;
2109 }
2110 unhandled:
2111 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002112 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002113}
2114
2115
sewardj3598ef92004-11-11 02:13:30 +00002116/* Generate a shadow store. addr is always the original address atom.
2117 You can pass in either originals or V-bits for the data atom, but
2118 obviously not both. */
2119
sewardjde8a5ae2004-11-06 14:20:54 +00002120static
sewardj3598ef92004-11-11 02:13:30 +00002121void do_shadow_STle ( MCEnv* mce,
2122 IRAtom* addr, UInt bias,
2123 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002124{
sewardj69f9e3e2004-12-30 02:05:34 +00002125 IROp mkAdd;
2126 IRType ty, tyAddr;
2127 IRDirty *di, *diLo64, *diHi64;
2128 IRAtom *addrAct, *addrLo64, *addrHi64;
2129 IRAtom *vdataLo64, *vdataHi64;
2130 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002131 void* helper = NULL;
2132 Char* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002133
2134 tyAddr = mce->hWordTy;
2135 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2136 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2137
2138 di = diLo64 = diHi64 = NULL;
2139 eBias = eBias0 = eBias8 = NULL;
2140 addrAct = addrLo64 = addrHi64 = NULL;
2141 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002142
sewardj3598ef92004-11-11 02:13:30 +00002143 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002144 tl_assert(!vdata);
2145 tl_assert(isOriginalAtom(mce, data));
2146 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002147 vdata = expr2vbits( mce, data );
2148 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002149 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002150 }
sewardjde8a5ae2004-11-06 14:20:54 +00002151
sewardj69f9e3e2004-12-30 02:05:34 +00002152 tl_assert(isOriginalAtom(mce,addr));
2153 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002154
2155 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002156
2157 /* First, emit a definedness test for the address. This also sets
2158 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002159 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002160
sewardj69f9e3e2004-12-30 02:05:34 +00002161 /* Now decide which helper function to call to write the data V
2162 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002163 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002164 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002165 case Ity_I64: helper = &MC_(helperc_STOREV8);
2166 hname = "MC_(helperc_STOREV8)";
2167 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002168 case Ity_I32: helper = &MC_(helperc_STOREV4);
2169 hname = "MC_(helperc_STOREV4)";
2170 break;
2171 case Ity_I16: helper = &MC_(helperc_STOREV2);
2172 hname = "MC_(helperc_STOREV2)";
2173 break;
2174 case Ity_I8: helper = &MC_(helperc_STOREV1);
2175 hname = "MC_(helperc_STOREV1)";
2176 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002177 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002178 }
2179
sewardj69f9e3e2004-12-30 02:05:34 +00002180 if (ty == Ity_V128) {
2181
sewardjf0c1c582005-02-07 23:47:38 +00002182 /* V128-bit case */
sewardj69f9e3e2004-12-30 02:05:34 +00002183 /* See comment in next clause re 64-bit regparms */
2184 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2185 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
sewardjf0c1c582005-02-07 23:47:38 +00002186 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002187 diLo64 = unsafeIRDirty_0_N(
2188 1/*regparms*/, hname, helper,
2189 mkIRExprVec_2( addrLo64, vdataLo64 ));
2190
2191 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2192 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
sewardjf0c1c582005-02-07 23:47:38 +00002193 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002194 diHi64 = unsafeIRDirty_0_N(
2195 1/*regparms*/, hname, helper,
2196 mkIRExprVec_2( addrHi64, vdataHi64 ));
2197
2198 setHelperAnns( mce, diLo64 );
2199 setHelperAnns( mce, diHi64 );
2200 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2201 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2202
sewardj3598ef92004-11-11 02:13:30 +00002203 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002204
2205 /* 8/16/32/64-bit cases */
2206 /* Generate the actual address into addrAct. */
2207 if (bias == 0) {
2208 addrAct = addr;
2209 } else {
2210 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2211 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2212 }
2213
2214 if (ty == Ity_I64) {
2215 /* We can't do this with regparm 2 on 32-bit platforms, since
2216 the back ends aren't clever enough to handle 64-bit
2217 regparm args. Therefore be different. */
2218 di = unsafeIRDirty_0_N(
2219 1/*regparms*/, hname, helper,
2220 mkIRExprVec_2( addrAct, vdata ));
2221 } else {
2222 di = unsafeIRDirty_0_N(
2223 2/*regparms*/, hname, helper,
2224 mkIRExprVec_2( addrAct,
2225 zwidenToHostWord( mce, vdata )));
2226 }
2227 setHelperAnns( mce, di );
2228 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002229 }
2230
sewardjde8a5ae2004-11-06 14:20:54 +00002231}
2232
2233
sewardj3598ef92004-11-11 02:13:30 +00002234/* Do lazy pessimistic propagation through a dirty helper call, by
2235 looking at the annotations on it. This is the most complex part of
2236 Memcheck. */
2237
2238static IRType szToITy ( Int n )
2239{
2240 switch (n) {
2241 case 1: return Ity_I8;
2242 case 2: return Ity_I16;
2243 case 4: return Ity_I32;
2244 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002245 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002246 }
2247}
2248
2249static
2250void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2251{
sewardj69f9e3e2004-12-30 02:05:34 +00002252 Int i, n, offset, toDo, gSz, gOff;
2253 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002254 IRType tyAddr, tySrc, tyDst;
2255 IRTemp dst;
2256
2257 /* First check the guard. */
2258 complainIfUndefined(mce, d->guard);
2259
2260 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002261 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002262
2263 /* Inputs: unmasked args */
2264 for (i = 0; d->args[i]; i++) {
2265 if (d->cee->mcx_mask & (1<<i)) {
2266 /* ignore this arg */
2267 } else {
2268 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2269 curr = mkUifU32(mce, here, curr);
2270 }
2271 }
2272
2273 /* Inputs: guest state that we read. */
2274 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002275 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002276 if (d->fxState[i].fx == Ifx_Write)
2277 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002278
2279 /* Ignore any sections marked as 'always defined'. */
2280 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2281 if (0)
2282 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2283 d->fxState[i].offset, d->fxState[i].size );
2284 continue;
2285 }
2286
sewardj3598ef92004-11-11 02:13:30 +00002287 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002288 consider it. If larger than 8 bytes, deal with it in 8-byte
2289 chunks. */
2290 gSz = d->fxState[i].size;
2291 gOff = d->fxState[i].offset;
2292 tl_assert(gSz > 0);
2293 while (True) {
2294 if (gSz == 0) break;
2295 n = gSz <= 8 ? gSz : 8;
2296 /* update 'curr' with UifU of the state slice
2297 gOff .. gOff+n-1 */
2298 tySrc = szToITy( n );
2299 src = assignNew( mce, tySrc,
2300 shadow_GET(mce, gOff, tySrc ) );
2301 here = mkPCastTo( mce, Ity_I32, src );
2302 curr = mkUifU32(mce, here, curr);
2303 gSz -= n;
2304 gOff += n;
2305 }
2306
sewardj3598ef92004-11-11 02:13:30 +00002307 }
2308
2309 /* Inputs: memory. First set up some info needed regardless of
2310 whether we're doing reads or writes. */
2311 tyAddr = Ity_INVALID;
2312
2313 if (d->mFx != Ifx_None) {
2314 /* Because we may do multiple shadow loads/stores from the same
2315 base address, it's best to do a single test of its
2316 definedness right now. Post-instrumentation optimisation
2317 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002318 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002319 complainIfUndefined(mce, d->mAddr);
2320
2321 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002322 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2323 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002324 }
2325
2326 /* Deal with memory inputs (reads or modifies) */
2327 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2328 offset = 0;
2329 toDo = d->mSize;
2330 /* chew off 32-bit chunks */
2331 while (toDo >= 4) {
2332 here = mkPCastTo(
2333 mce, Ity_I32,
2334 expr2vbits_LDle ( mce, Ity_I32,
2335 d->mAddr, d->mSize - toDo )
2336 );
2337 curr = mkUifU32(mce, here, curr);
2338 toDo -= 4;
2339 }
2340 /* chew off 16-bit chunks */
2341 while (toDo >= 2) {
2342 here = mkPCastTo(
2343 mce, Ity_I32,
2344 expr2vbits_LDle ( mce, Ity_I16,
2345 d->mAddr, d->mSize - toDo )
2346 );
2347 curr = mkUifU32(mce, here, curr);
2348 toDo -= 2;
2349 }
sewardj69f9e3e2004-12-30 02:05:34 +00002350 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002351 }
2352
2353 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2354 all the inputs to the helper. Now we need to re-distribute the
2355 results to all destinations. */
2356
2357 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002358 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002359 dst = findShadowTmp(mce, d->tmp);
2360 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2361 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2362 }
2363
2364 /* Outputs: guest state that we write or modify. */
2365 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002366 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002367 if (d->fxState[i].fx == Ifx_Read)
2368 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002369 /* Ignore any sections marked as 'always defined'. */
2370 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2371 continue;
2372 /* This state element is written or modified. So we need to
2373 consider it. If larger than 8 bytes, deal with it in 8-byte
2374 chunks. */
2375 gSz = d->fxState[i].size;
2376 gOff = d->fxState[i].offset;
2377 tl_assert(gSz > 0);
2378 while (True) {
2379 if (gSz == 0) break;
2380 n = gSz <= 8 ? gSz : 8;
2381 /* Write suitably-casted 'curr' to the state slice
2382 gOff .. gOff+n-1 */
2383 tyDst = szToITy( n );
2384 do_shadow_PUT( mce, gOff,
2385 NULL, /* original atom */
2386 mkPCastTo( mce, tyDst, curr ) );
2387 gSz -= n;
2388 gOff += n;
2389 }
sewardj3598ef92004-11-11 02:13:30 +00002390 }
2391
2392 /* Outputs: memory that we write or modify. */
2393 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2394 offset = 0;
2395 toDo = d->mSize;
2396 /* chew off 32-bit chunks */
2397 while (toDo >= 4) {
2398 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2399 NULL, /* original data */
2400 mkPCastTo( mce, Ity_I32, curr ) );
2401 toDo -= 4;
2402 }
2403 /* chew off 16-bit chunks */
2404 while (toDo >= 2) {
2405 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2406 NULL, /* original data */
2407 mkPCastTo( mce, Ity_I16, curr ) );
2408 toDo -= 2;
2409 }
sewardj69f9e3e2004-12-30 02:05:34 +00002410 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002411 }
2412
2413}
2414
2415
sewardjde8a5ae2004-11-06 14:20:54 +00002416/*------------------------------------------------------------*/
2417/*--- Memcheck main ---*/
2418/*------------------------------------------------------------*/
2419
sewardj3598ef92004-11-11 02:13:30 +00002420static Bool isBogusAtom ( IRAtom* at )
2421{
2422 ULong n = 0;
2423 IRConst* con;
sewardj496a58d2005-03-20 18:44:44 +00002424 tl_assert(isIRAtom(at));
sewardj3598ef92004-11-11 02:13:30 +00002425 if (at->tag == Iex_Tmp)
2426 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002427 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002428 con = at->Iex.Const.con;
2429 switch (con->tag) {
2430 case Ico_U8: n = (ULong)con->Ico.U8; break;
2431 case Ico_U16: n = (ULong)con->Ico.U16; break;
2432 case Ico_U32: n = (ULong)con->Ico.U32; break;
2433 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002434 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002435 }
2436 /* VG_(printf)("%llx\n", n); */
2437 return (n == 0xFEFEFEFF
2438 || n == 0x80808080
2439 || n == 0x1010101
2440 || n == 1010100);
2441}
2442
2443static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2444{
2445 Int i;
2446 IRExpr* e;
2447 switch (st->tag) {
2448 case Ist_Tmp:
2449 e = st->Ist.Tmp.data;
2450 switch (e->tag) {
2451 case Iex_Get:
2452 case Iex_Tmp:
2453 return False;
2454 case Iex_Unop:
2455 return isBogusAtom(e->Iex.Unop.arg);
2456 case Iex_Binop:
2457 return isBogusAtom(e->Iex.Binop.arg1)
2458 || isBogusAtom(e->Iex.Binop.arg2);
2459 case Iex_Mux0X:
2460 return isBogusAtom(e->Iex.Mux0X.cond)
2461 || isBogusAtom(e->Iex.Mux0X.expr0)
2462 || isBogusAtom(e->Iex.Mux0X.exprX);
2463 case Iex_LDle:
2464 return isBogusAtom(e->Iex.LDle.addr);
2465 case Iex_CCall:
2466 for (i = 0; e->Iex.CCall.args[i]; i++)
2467 if (isBogusAtom(e->Iex.CCall.args[i]))
2468 return True;
2469 return False;
2470 default:
2471 goto unhandled;
2472 }
2473 case Ist_Put:
2474 return isBogusAtom(st->Ist.Put.data);
2475 case Ist_STle:
2476 return isBogusAtom(st->Ist.STle.addr)
2477 || isBogusAtom(st->Ist.STle.data);
2478 case Ist_Exit:
sewardj1ea1b612005-03-26 13:02:20 +00002479 return isBogusAtom(st->Ist.Exit.guard);
sewardj3598ef92004-11-11 02:13:30 +00002480 default:
2481 unhandled:
2482 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002483 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002484 }
2485}
sewardj3598ef92004-11-11 02:13:30 +00002486
sewardj1ea1b612005-03-26 13:02:20 +00002487IRBB* mc_instrument ( IRBB* bb_in, VexGuestLayout* layout,
2488 IRType gWordTy, IRType hWordTy )
sewardjde8a5ae2004-11-06 14:20:54 +00002489{
sewardj3598ef92004-11-11 02:13:30 +00002490 Bool verboze = False; //True;
2491
2492 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002493
2494 Int i, j, first_stmt;
2495 IRStmt* st;
2496 MCEnv mce;
2497
2498 /* Set up BB */
2499 IRBB* bb = emptyIRBB();
2500 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
2501 bb->next = dopyIRExpr(bb_in->next);
2502 bb->jumpkind = bb_in->jumpkind;
2503
2504 /* Set up the running environment. Only .bb is modified as we go
2505 along. */
2506 mce.bb = bb;
2507 mce.layout = layout;
2508 mce.n_originalTmps = bb->tyenv->types_used;
2509 mce.hWordTy = hWordTy;
2510 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2511 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002512 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002513
2514 /* Iterate over the stmts. */
2515
2516 for (i = 0; i < bb_in->stmts_used; i++) {
2517 st = bb_in->stmts[i];
2518 if (!st) continue;
2519
sewardj69f9e3e2004-12-30 02:05:34 +00002520 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002521
2522 /*
2523 if (!hasBogusLiterals) {
2524 hasBogusLiterals = checkForBogusLiterals(st);
2525 if (hasBogusLiterals) {
2526 VG_(printf)("bogus: ");
2527 ppIRStmt(st);
2528 VG_(printf)("\n");
2529 }
2530 }
2531 */
sewardjde8a5ae2004-11-06 14:20:54 +00002532 first_stmt = bb->stmts_used;
2533
2534 if (verboze) {
2535 ppIRStmt(st);
2536 VG_(printf)("\n\n");
2537 }
2538
2539 switch (st->tag) {
2540
2541 case Ist_Tmp:
2542 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
2543 expr2vbits( &mce, st->Ist.Tmp.data) );
2544 break;
2545
2546 case Ist_Put:
2547 do_shadow_PUT( &mce,
2548 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002549 st->Ist.Put.data,
2550 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002551 break;
2552
2553 case Ist_PutI:
2554 do_shadow_PUTI( &mce,
2555 st->Ist.PutI.descr,
2556 st->Ist.PutI.ix,
2557 st->Ist.PutI.bias,
2558 st->Ist.PutI.data );
2559 break;
2560
2561 case Ist_STle:
sewardj3598ef92004-11-11 02:13:30 +00002562 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
2563 st->Ist.STle.data,
2564 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002565 break;
2566
2567 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002568 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002569 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002570 break;
2571
2572 case Ist_Dirty:
2573 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002574 break;
2575
sewardj1ea1b612005-03-26 13:02:20 +00002576 case Ist_IMark:
2577 case Ist_NoOp:
2578 break;
2579
sewardjde8a5ae2004-11-06 14:20:54 +00002580 default:
2581 VG_(printf)("\n");
2582 ppIRStmt(st);
2583 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002584 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002585
2586 } /* switch (st->tag) */
2587
2588 if (verboze) {
2589 for (j = first_stmt; j < bb->stmts_used; j++) {
2590 VG_(printf)(" ");
2591 ppIRStmt(bb->stmts[j]);
2592 VG_(printf)("\n");
2593 }
2594 VG_(printf)("\n");
2595 }
2596
2597 addStmtToIRBB(bb, st);
2598
2599 }
2600
2601 /* Now we need to complain if the jump target is undefined. */
2602 first_stmt = bb->stmts_used;
2603
2604 if (verboze) {
2605 VG_(printf)("bb->next = ");
2606 ppIRExpr(bb->next);
2607 VG_(printf)("\n\n");
2608 }
2609
2610 complainIfUndefined( &mce, bb->next );
2611
2612 if (verboze) {
2613 for (j = first_stmt; j < bb->stmts_used; j++) {
2614 VG_(printf)(" ");
2615 ppIRStmt(bb->stmts[j]);
2616 VG_(printf)("\n");
2617 }
2618 VG_(printf)("\n");
2619 }
2620
2621 return bb;
2622}
cerionaee45242005-03-17 14:03:36 +00002623#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002624
2625/*--------------------------------------------------------------------*/
2626/*--- end mc_translate.c ---*/
2627/*--------------------------------------------------------------------*/