blob: 57107408678f1e6001dd7b45f854932a227d70ae [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;
sewardj9e6491a2005-07-02 19:24:10 +000069 VexArchInfo vai_x86, vai_amd64, vai_ppc32;
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
sewardj9e6491a2005-07-02 19:24:10 +0000126 LibVEX_default_VexArchInfo(&vai_x86);
127 vai_x86.subarch = VexSubArchX86_sse1;
128
129 LibVEX_default_VexArchInfo(&vai_amd64);
130 vai_amd64.subarch = VexSubArch_NONE;
131
132 LibVEX_default_VexArchInfo(&vai_ppc32);
133 vai_ppc32.subarch = VexSubArchPPC32_AV;
134 vai_ppc32.ppc32_cache_line_szB = 128;
sewardj02ef7162005-06-30 12:50:50 +0000135
sewardjabe017e2004-10-29 23:42:36 +0000136 for (i = 0; i < TEST_N_ITERS; i++)
137 tres
138 = LibVEX_Translate (
sewardj9e6491a2005-07-02 19:24:10 +0000139#if 1 /* ppc32 -> ppc32 */
140 VexArchPPC32, &vai_ppc32,
141 VexArchPPC32, &vai_ppc32,
sewardj07a54cc2005-02-04 21:18:55 +0000142#endif
sewardjc279b3f2005-03-16 18:10:45 +0000143#if 0 /* amd64 -> amd64 */
sewardj9e6491a2005-07-02 19:24:10 +0000144 VexArchAMD64, &vai_amd64,
145 VexArchAMD64, &vai_amd64,
sewardj07a54cc2005-02-04 21:18:55 +0000146#endif
sewardj9e6491a2005-07-02 19:24:10 +0000147#if 0 /* x86 -> x86 */
148 VexArchX86, &vai_x86,
149 VexArchX86, &vai_x86,
sewardjc279b3f2005-03-16 18:10:45 +0000150#endif
sewardj5bd4d162004-11-10 13:02:48 +0000151 origbuf, (Addr64)orig_addr, chase_into_not_ok,
sewardj72c72812005-01-19 11:49:45 +0000152 &vge,
sewardjabe017e2004-10-29 23:42:36 +0000153 transbuf, N_TRANSBUF, &trans_used,
sewardj9e7448b2004-11-18 13:44:15 +0000154#if 1 /* no instrumentation */
155 NULL, /* instrument1 */
156 NULL, /* instrument2 */
157 False, /* cleanup after instrument */
158#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000159#if 0 /* addrcheck */
160 ac_instrument, /* instrument1 */
161 NULL, /* instrument2 */
162 False, /* cleanup after instrument */
163#endif
sewardj9e7448b2004-11-18 13:44:15 +0000164#if 0 /* memcheck */
sewardjde8a5ae2004-11-06 14:20:54 +0000165 mc_instrument, /* instrument1 */
166 NULL, /* instrument2 */
sewardj69f9e3e2004-12-30 02:05:34 +0000167 True, /* cleanup after instrument */
sewardjde8a5ae2004-11-06 14:20:54 +0000168#endif
sewardjec3c8852005-07-07 09:56:24 +0000169 False, /* do_self_check ? */
sewardjabe017e2004-10-29 23:42:36 +0000170 NULL, /* access checker */
171 TEST_FLAGS
172 );
173
sewardjd887b862005-01-17 18:34:34 +0000174 if (tres != VexTransOK)
sewardj4459baa2004-09-10 20:00:46 +0000175 printf("\ntres = %d\n", (Int)tres);
sewardjd887b862005-01-17 18:34:34 +0000176 assert(tres == VexTransOK);
sewardj72c72812005-01-19 11:49:45 +0000177 assert(vge.n_used == 1);
178 assert((UInt)(vge.len[0]) == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000179
sewardj4459baa2004-09-10 20:00:46 +0000180 sum = 0;
181 for (i = 0; i < trans_used; i++)
182 sum += (UInt)transbuf[i];
sewardjde8c9872005-03-25 13:48:55 +0000183 printf ( " %6.2f ... %u\n",
184 (double)trans_used / (double)vge.len[0], sum );
sewardjced9fe52004-07-07 11:55:36 +0000185 }
186
187 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000188 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000189 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000190
sewardjce605f92004-07-05 14:39:15 +0000191 return 0;
192}
sewardj9b1004e2004-10-30 22:25:40 +0000193
194//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000195//////////////////////////////////////////////////////////////////////
196//////////////////////////////////////////////////////////////////////
197//////////////////////////////////////////////////////////////////////
198//////////////////////////////////////////////////////////////////////
199//////////////////////////////////////////////////////////////////////
200//////////////////////////////////////////////////////////////////////
201//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000202
sewardj1ea1b612005-03-26 13:02:20 +0000203#if 0 /* UNUSED */
204
sewardj9b1004e2004-10-30 22:25:40 +0000205static
sewardjde8a5ae2004-11-06 14:20:54 +0000206__attribute((noreturn))
sewardjde8c9872005-03-25 13:48:55 +0000207void panic ( HChar* s )
sewardj9b1004e2004-10-30 22:25:40 +0000208{
209 printf("\npanic: %s\n", s);
210 failure_exit();
211}
212
213static
sewardj9578a8b2004-11-04 19:44:48 +0000214IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000215{
216/* Use this rather than eg. -1 because it's a UInt. */
217#define INVALID_DATA_SIZE 999999
218
219 Int i;
220 Int sz;
221 IRCallee* helper;
222 IRStmt* st;
223 IRExpr* data;
224 IRExpr* addr;
225 Bool needSz;
226
227 /* Set up BB */
228 IRBB* bb = emptyIRBB();
229 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
230 bb->next = dopyIRExpr(bb_in->next);
231 bb->jumpkind = bb_in->jumpkind;
232
233 /* No loads to consider in ->next. */
sewardj496a58d2005-03-20 18:44:44 +0000234 assert(isIRAtom(bb_in->next));
sewardj9b1004e2004-10-30 22:25:40 +0000235
236 for (i = 0; i < bb_in->stmts_used; i++) {
237 st = bb_in->stmts[i];
238 if (!st) continue;
239
240 switch (st->tag) {
241
242 case Ist_Tmp:
243 data = st->Ist.Tmp.data;
244 if (data->tag == Iex_LDle) {
245 addr = data->Iex.LDle.addr;
246 sz = sizeofIRType(data->Iex.LDle.ty);
247 needSz = False;
248 switch (sz) {
249 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000250 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000251 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000252 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000253 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000254 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000255 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000256 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000257 needSz = True; break;
258 }
259 if (needSz) {
260 addStmtToIRBB(
261 bb,
262 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000263 unsafeIRDirty_0_N( helper->regparms,
264 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000265 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
266 ));
267 } else {
268 addStmtToIRBB(
269 bb,
270 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000271 unsafeIRDirty_0_N( helper->regparms,
272 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000273 mkIRExprVec_1(addr) )
274 ));
275 }
276 }
277 break;
278
279 case Ist_STle:
280 data = st->Ist.STle.data;
281 addr = st->Ist.STle.addr;
sewardj496a58d2005-03-20 18:44:44 +0000282 assert(isIRAtom(data));
283 assert(isIRAtom(addr));
sewardj9b1004e2004-10-30 22:25:40 +0000284 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
285 needSz = False;
286 switch (sz) {
287 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000288 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000289 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000290 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000291 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000292 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000293 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000294 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000295 needSz = True; break;
296 }
297 if (needSz) {
298 addStmtToIRBB(
299 bb,
300 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000301 unsafeIRDirty_0_N( helper->regparms,
302 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000303 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
304 ));
305 } else {
306 addStmtToIRBB(
307 bb,
308 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000309 unsafeIRDirty_0_N( helper->regparms,
310 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000311 mkIRExprVec_1(addr) )
312 ));
313 }
314 break;
315
316 case Ist_Put:
sewardj496a58d2005-03-20 18:44:44 +0000317 assert(isIRAtom(st->Ist.Put.data));
sewardj9b1004e2004-10-30 22:25:40 +0000318 break;
319
320 case Ist_PutI:
sewardj496a58d2005-03-20 18:44:44 +0000321 assert(isIRAtom(st->Ist.PutI.ix));
322 assert(isIRAtom(st->Ist.PutI.data));
sewardj9b1004e2004-10-30 22:25:40 +0000323 break;
324
325 case Ist_Exit:
sewardj496a58d2005-03-20 18:44:44 +0000326 assert(isIRAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000327 break;
328
329 case Ist_Dirty:
330 /* If the call doesn't interact with memory, we ain't
331 interested. */
332 if (st->Ist.Dirty.details->mFx == Ifx_None)
333 break;
334 goto unhandled;
335
336 default:
337 unhandled:
338 printf("\n");
339 ppIRStmt(st);
340 printf("\n");
341 panic("addrcheck: unhandled IRStmt");
342 }
343
344 addStmtToIRBB( bb, dopyIRStmt(st));
345 }
346
347 return bb;
348}
cerionaee45242005-03-17 14:03:36 +0000349#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +0000350
351//////////////////////////////////////////////////////////////////////
352//////////////////////////////////////////////////////////////////////
353//////////////////////////////////////////////////////////////////////
354//////////////////////////////////////////////////////////////////////
355//////////////////////////////////////////////////////////////////////
356//////////////////////////////////////////////////////////////////////
357//////////////////////////////////////////////////////////////////////
358//////////////////////////////////////////////////////////////////////
359
sewardj1ea1b612005-03-26 13:02:20 +0000360#if 0 /* UNUSED */
361
sewardj69f9e3e2004-12-30 02:05:34 +0000362#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000363#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000364#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000365#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000366#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000367
cerionaee45242005-03-17 14:03:36 +0000368
sewardjde8c9872005-03-25 13:48:55 +0000369static void MC_helperc_complain_undef ( void );
370static void MC_helperc_LOADV8 ( void );
371static void MC_helperc_LOADV4 ( void );
372static void MC_helperc_LOADV2 ( void );
373static void MC_helperc_LOADV1 ( void );
sewardj1ea1b612005-03-26 13:02:20 +0000374static void MC_helperc_STOREV8( void );
375static void MC_helperc_STOREV4( void );
376static void MC_helperc_STOREV2( void );
377static void MC_helperc_STOREV1( void );
sewardjde8c9872005-03-25 13:48:55 +0000378static void MC_helperc_value_check0_fail( void );
379static void MC_helperc_value_check1_fail( void );
380static void MC_helperc_value_check4_fail( void );
381
382static void MC_helperc_complain_undef ( void ) { }
383static void MC_helperc_LOADV8 ( void ) { }
384static void MC_helperc_LOADV4 ( void ) { }
385static void MC_helperc_LOADV2 ( void ) { }
386static void MC_helperc_LOADV1 ( void ) { }
sewardj1ea1b612005-03-26 13:02:20 +0000387static void MC_helperc_STOREV8( void ) { }
388static void MC_helperc_STOREV4( void ) { }
389static void MC_helperc_STOREV2( void ) { }
390static void MC_helperc_STOREV1( void ) { }
sewardjde8c9872005-03-25 13:48:55 +0000391static void MC_helperc_value_check0_fail( void ) { }
392static void MC_helperc_value_check1_fail( void ) { }
393static void MC_helperc_value_check4_fail( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000394
395
sewardj3598ef92004-11-11 02:13:30 +0000396/*--------------------------------------------------------------------*/
397/*--- Instrument IR to perform memory checking operations. ---*/
398/*--- mc_translate.c ---*/
399/*--------------------------------------------------------------------*/
400
401/*
402 This file is part of MemCheck, a heavyweight Valgrind tool for
403 detecting memory errors.
404
405 Copyright (C) 2000-2004 Julian Seward
406 jseward@acm.org
407
408 This program is free software; you can redistribute it and/or
409 modify it under the terms of the GNU General Public License as
410 published by the Free Software Foundation; either version 2 of the
411 License, or (at your option) any later version.
412
413 This program is distributed in the hope that it will be useful, but
414 WITHOUT ANY WARRANTY; without even the implied warranty of
415 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
416 General Public License for more details.
417
418 You should have received a copy of the GNU General Public License
419 along with this program; if not, write to the Free Software
420 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
421 02111-1307, USA.
422
423 The GNU General Public License is contained in the file COPYING.
424*/
425
426//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000427
428
429/*------------------------------------------------------------*/
430/*--- Forward decls ---*/
431/*------------------------------------------------------------*/
432
433struct _MCEnv;
434
435static IRType shadowType ( IRType ty );
436static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
437
438
439/*------------------------------------------------------------*/
440/*--- Memcheck running state, and tmp management. ---*/
441/*------------------------------------------------------------*/
442
443/* Carries around state during memcheck instrumentation. */
444typedef
445 struct _MCEnv {
446 /* MODIFIED: the bb being constructed. IRStmts are added. */
447 IRBB* bb;
448
449 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
450 original temps to their current their current shadow temp.
451 Initially all entries are IRTemp_INVALID. Entries are added
452 lazily since many original temps are not used due to
453 optimisation prior to instrumentation. Note that floating
454 point original tmps are shadowed by integer tmps of the same
455 size, and Bit-typed original tmps are shadowed by the type
456 Ity_I8. See comment below. */
457 IRTemp* tmpMap;
458 Int n_originalTmps; /* for range checking */
459
460 /* READONLY: the guest layout. This indicates which parts of
461 the guest state should be regarded as 'always defined'. */
462 VexGuestLayout* layout;
463 /* READONLY: the host word type. Needed for constructing
464 arguments of type 'HWord' to be passed to helper functions.
465 Ity_I32 or Ity_I64 only. */
466 IRType hWordTy;
467 }
468 MCEnv;
469
470/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
471 demand), as they are encountered. This is for two reasons.
472
473 (1) (less important reason): Many original tmps are unused due to
474 initial IR optimisation, and we do not want to spaces in tables
475 tracking them.
476
477 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
478 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000479 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000480 It is necessary to support making multiple assignments to a shadow
481 -- specifically, after testing a shadow for definedness, it needs
482 to be made defined. But IR's SSA property disallows this.
483
484 (2) (more important reason): Therefore, when a shadow needs to get
485 a new value, a new temporary is created, the value is assigned to
486 that, and the tmpMap is updated to reflect the new binding.
487
488 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000489 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000490 there's a read-before-write error in the original tmps. The IR
491 sanity checker should catch all such anomalies, however.
492*/
493
494/* Find the tmp currently shadowing the given original tmp. If none
495 so far exists, allocate one. */
496static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
497{
sewardj69f9e3e2004-12-30 02:05:34 +0000498 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000499 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000500 mce->tmpMap[orig]
501 = newIRTemp(mce->bb->tyenv,
502 shadowType(mce->bb->tyenv->types[orig]));
503 }
504 return mce->tmpMap[orig];
505}
506
507/* Allocate a new shadow for the given original tmp. This means any
508 previous shadow is abandoned. This is needed because it is
509 necessary to give a new value to a shadow once it has been tested
510 for undefinedness, but unfortunately IR's SSA property disallows
511 this. Instead we must abandon the old shadow, allocate a new one
512 and use that instead. */
513static void newShadowTmp ( MCEnv* mce, IRTemp orig )
514{
sewardj69f9e3e2004-12-30 02:05:34 +0000515 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000516 mce->tmpMap[orig]
517 = newIRTemp(mce->bb->tyenv,
518 shadowType(mce->bb->tyenv->types[orig]));
519}
520
521
522/*------------------------------------------------------------*/
523/*--- IRAtoms -- a subset of IRExprs ---*/
524/*------------------------------------------------------------*/
525
526/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj496a58d2005-03-20 18:44:44 +0000527 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardjde8a5ae2004-11-06 14:20:54 +0000528 input, most of this code deals in atoms. Usefully, a value atom
529 always has a V-value which is also an atom: constants are shadowed
530 by constants, and temps are shadowed by the corresponding shadow
531 temporary. */
532
533typedef IRExpr IRAtom;
534
535/* (used for sanity checks only): is this an atom which looks
536 like it's from original code? */
537static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
538{
539 if (a1->tag == Iex_Const)
540 return True;
541 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
542 return True;
543 return False;
544}
545
546/* (used for sanity checks only): is this an atom which looks
547 like it's from shadow code? */
548static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
549{
550 if (a1->tag == Iex_Const)
551 return True;
552 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
553 return True;
554 return False;
555}
556
557/* (used for sanity checks only): check that both args are atoms and
558 are identically-kinded. */
559static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
560{
561 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
562 return True;
563 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
564 return True;
565 return False;
566}
567
568
569/*------------------------------------------------------------*/
570/*--- Type management ---*/
571/*------------------------------------------------------------*/
572
573/* Shadow state is always accessed using integer types. This returns
574 an integer type with the same size (as per sizeofIRType) as the
575 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000576 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000577
578static IRType shadowType ( IRType ty )
579{
580 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000581 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000582 case Ity_I8:
583 case Ity_I16:
584 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000585 case Ity_I64: return ty;
586 case Ity_F32: return Ity_I32;
587 case Ity_F64: return Ity_I64;
588 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000589 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000590 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000591 }
592}
593
594/* Produce a 'defined' value of the given shadow type. Should only be
595 supplied shadow types (Bit/I8/I16/I32/UI64). */
596static IRExpr* definedOfType ( IRType ty ) {
597 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000598 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
599 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
600 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
601 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
602 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
603 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
604 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000605 }
606}
607
608
609/*------------------------------------------------------------*/
610/*--- Constructing IR fragments ---*/
611/*------------------------------------------------------------*/
612
613/* assign value to tmp */
614#define assign(_bb,_tmp,_expr) \
615 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
616
617/* add stmt to a bb */
618#define stmt(_bb,_stmt) \
619 addStmtToIRBB((_bb), (_stmt))
620
621/* build various kinds of expressions */
622#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
623#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
624#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
625#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
626#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
627#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000628#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardjde8a5ae2004-11-06 14:20:54 +0000629#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
630
631/* bind the given expression to a new temporary, and return the
632 temporary. This effectively converts an arbitrary expression into
633 an atom. */
634static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
635 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
636 assign(mce->bb, t, e);
637 return mkexpr(t);
638}
639
640
641/*------------------------------------------------------------*/
642/*--- Constructing definedness primitive ops ---*/
643/*------------------------------------------------------------*/
644
645/* --------- Defined-if-either-defined --------- */
646
647static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000648 tl_assert(isShadowAtom(mce,a1));
649 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000650 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
651}
652
653static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000654 tl_assert(isShadowAtom(mce,a1));
655 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000656 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
657}
658
659static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000660 tl_assert(isShadowAtom(mce,a1));
661 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000662 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
663}
664
sewardj69f9e3e2004-12-30 02:05:34 +0000665static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
666 tl_assert(isShadowAtom(mce,a1));
667 tl_assert(isShadowAtom(mce,a2));
668 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
669}
670
sewardjf0c1c582005-02-07 23:47:38 +0000671static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000672 tl_assert(isShadowAtom(mce,a1));
673 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000674 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000675}
676
sewardjde8a5ae2004-11-06 14:20:54 +0000677/* --------- Undefined-if-either-undefined --------- */
678
679static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000680 tl_assert(isShadowAtom(mce,a1));
681 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000682 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
683}
684
685static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000686 tl_assert(isShadowAtom(mce,a1));
687 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000688 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
689}
690
691static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000692 tl_assert(isShadowAtom(mce,a1));
693 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000694 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
695}
696
697static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000698 tl_assert(isShadowAtom(mce,a1));
699 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000700 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
701}
702
sewardjf0c1c582005-02-07 23:47:38 +0000703static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000704 tl_assert(isShadowAtom(mce,a1));
705 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000706 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000707}
708
709static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000710 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000711 case Ity_I8: return mkUifU8(mce, a1, a2);
712 case Ity_I16: return mkUifU16(mce, a1, a2);
713 case Ity_I32: return mkUifU32(mce, a1, a2);
714 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardjf0c1c582005-02-07 23:47:38 +0000715 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000716 default:
717 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000718 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000719 }
720}
721
722/* --------- The Left-family of operations. --------- */
723
724static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000725 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000726 /* It's safe to duplicate a1 since it's only an atom */
727 return assignNew(mce, Ity_I8,
728 binop(Iop_Or8, a1,
729 assignNew(mce, Ity_I8,
730 /* unop(Iop_Neg8, a1)))); */
731 binop(Iop_Sub8, mkU8(0), a1) )));
732}
733
734static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000735 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000736 /* It's safe to duplicate a1 since it's only an atom */
737 return assignNew(mce, Ity_I16,
738 binop(Iop_Or16, a1,
739 assignNew(mce, Ity_I16,
740 /* unop(Iop_Neg16, a1)))); */
741 binop(Iop_Sub16, mkU16(0), a1) )));
742}
743
744static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000745 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000746 /* It's safe to duplicate a1 since it's only an atom */
747 return assignNew(mce, Ity_I32,
748 binop(Iop_Or32, a1,
749 assignNew(mce, Ity_I32,
750 /* unop(Iop_Neg32, a1)))); */
751 binop(Iop_Sub32, mkU32(0), a1) )));
752}
753
754/* --------- 'Improvement' functions for AND/OR. --------- */
755
756/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
757 defined (0); all other -> undefined (1).
758*/
759static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
760{
sewardj69f9e3e2004-12-30 02:05:34 +0000761 tl_assert(isOriginalAtom(mce, data));
762 tl_assert(isShadowAtom(mce, vbits));
763 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000764 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
765}
766
sewardj3598ef92004-11-11 02:13:30 +0000767static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
768{
sewardj69f9e3e2004-12-30 02:05:34 +0000769 tl_assert(isOriginalAtom(mce, data));
770 tl_assert(isShadowAtom(mce, vbits));
771 tl_assert(sameKindedAtoms(data, vbits));
sewardj3598ef92004-11-11 02:13:30 +0000772 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
773}
774
sewardjde8a5ae2004-11-06 14:20:54 +0000775static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
776{
sewardj69f9e3e2004-12-30 02:05:34 +0000777 tl_assert(isOriginalAtom(mce, data));
778 tl_assert(isShadowAtom(mce, vbits));
779 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000780 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
781}
782
sewardj69f9e3e2004-12-30 02:05:34 +0000783static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
784{
785 tl_assert(isOriginalAtom(mce, data));
786 tl_assert(isShadowAtom(mce, vbits));
787 tl_assert(sameKindedAtoms(data, vbits));
788 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
789}
790
sewardjf0c1c582005-02-07 23:47:38 +0000791static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000792{
793 tl_assert(isOriginalAtom(mce, data));
794 tl_assert(isShadowAtom(mce, vbits));
795 tl_assert(sameKindedAtoms(data, vbits));
sewardjf0c1c582005-02-07 23:47:38 +0000796 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj69f9e3e2004-12-30 02:05:34 +0000797}
798
sewardjde8a5ae2004-11-06 14:20:54 +0000799/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
800 defined (0); all other -> undefined (1).
801*/
802static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
803{
sewardj69f9e3e2004-12-30 02:05:34 +0000804 tl_assert(isOriginalAtom(mce, data));
805 tl_assert(isShadowAtom(mce, vbits));
806 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000807 return assignNew(
808 mce, Ity_I8,
809 binop(Iop_Or8,
810 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
811 vbits) );
812}
813
814static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
815{
sewardj69f9e3e2004-12-30 02:05:34 +0000816 tl_assert(isOriginalAtom(mce, data));
817 tl_assert(isShadowAtom(mce, vbits));
818 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000819 return assignNew(
820 mce, Ity_I16,
821 binop(Iop_Or16,
822 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
823 vbits) );
824}
825
826static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
827{
sewardj69f9e3e2004-12-30 02:05:34 +0000828 tl_assert(isOriginalAtom(mce, data));
829 tl_assert(isShadowAtom(mce, vbits));
830 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000831 return assignNew(
832 mce, Ity_I32,
833 binop(Iop_Or32,
834 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
835 vbits) );
836}
837
sewardj69f9e3e2004-12-30 02:05:34 +0000838static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
839{
840 tl_assert(isOriginalAtom(mce, data));
841 tl_assert(isShadowAtom(mce, vbits));
842 tl_assert(sameKindedAtoms(data, vbits));
843 return assignNew(
844 mce, Ity_I64,
845 binop(Iop_Or64,
846 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
847 vbits) );
848}
849
sewardjf0c1c582005-02-07 23:47:38 +0000850static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000851{
852 tl_assert(isOriginalAtom(mce, data));
853 tl_assert(isShadowAtom(mce, vbits));
854 tl_assert(sameKindedAtoms(data, vbits));
855 return assignNew(
856 mce, Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +0000857 binop(Iop_OrV128,
858 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj69f9e3e2004-12-30 02:05:34 +0000859 vbits) );
860}
861
sewardjde8a5ae2004-11-06 14:20:54 +0000862/* --------- Pessimising casts. --------- */
863
864static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
865{
sewardj8fc93742004-11-22 11:29:33 +0000866 IRType ty;
867 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000868 /* Note, dst_ty is a shadow type, not an original type. */
869 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000870 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000871 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
872 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000873 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000874 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000875 tmp1 = vbits;
876 break;
877 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000878 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000879 break;
880 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000881 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000882 break;
883 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000884 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000885 break;
886 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000887 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000888 break;
889 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000890 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000891 }
sewardj69f9e3e2004-12-30 02:05:34 +0000892 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000893 /* Now widen up to the dst type. */
894 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000895 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000896 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000897 case Ity_I8:
898 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000899 case Ity_I16:
900 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
901 case Ity_I32:
902 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
903 case Ity_I64:
904 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000905 case Ity_V128:
906 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardjf0c1c582005-02-07 23:47:38 +0000907 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000908 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000909 default:
910 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000911 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +0000912 }
913}
914
915
916/*------------------------------------------------------------*/
917/*--- Emit a test and complaint if something is undefined. ---*/
918/*------------------------------------------------------------*/
919
920/* Set the annotations on a dirty helper to indicate that the stack
921 pointer and instruction pointers might be read. This is the
922 behaviour of all 'emit-a-complaint' style functions we might
923 call. */
924
925static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
926 di->nFxState = 2;
927 di->fxState[0].fx = Ifx_Read;
928 di->fxState[0].offset = mce->layout->offset_SP;
929 di->fxState[0].size = mce->layout->sizeof_SP;
930 di->fxState[1].fx = Ifx_Read;
931 di->fxState[1].offset = mce->layout->offset_IP;
932 di->fxState[1].size = mce->layout->sizeof_IP;
933}
934
935
936/* Check the supplied **original** atom for undefinedness, and emit a
937 complaint if so. Once that happens, mark it as defined. This is
938 possible because the atom is either a tmp or literal. If it's a
939 tmp, it will be shadowed by a tmp, and so we can set the shadow to
940 be defined. In fact as mentioned above, we will have to allocate a
941 new tmp to carry the new 'defined' shadow value, and update the
942 original->tmp mapping accordingly; we cannot simply assign a new
943 value to an existing shadow tmp as this breaks SSAness -- resulting
944 in the post-instrumentation sanity checker spluttering in disapproval.
945*/
946static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
947{
sewardj8fc93742004-11-22 11:29:33 +0000948 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +0000949 IRType ty;
950 Int sz;
sewardj8fc93742004-11-22 11:29:33 +0000951 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +0000952 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +0000953
sewardjde8a5ae2004-11-06 14:20:54 +0000954 /* Since the original expression is atomic, there's no duplicated
955 work generated by making multiple V-expressions for it. So we
956 don't really care about the possibility that someone else may
957 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +0000958 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +0000959 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +0000960 tl_assert(isShadowAtom(mce, vatom));
961 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +0000962
sewardj8fc93742004-11-22 11:29:33 +0000963 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +0000964
965 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +0000966 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +0000967
sewardj8fc93742004-11-22 11:29:33 +0000968 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +0000969 /* cond will be 0 if all defined, and 1 if any not defined. */
970
sewardj3598ef92004-11-11 02:13:30 +0000971 switch (sz) {
972 case 0:
973 di = unsafeIRDirty_0_N( 0/*regparms*/,
974 "MC_(helperc_value_check0_fail)",
975 &MC_(helperc_value_check0_fail),
976 mkIRExprVec_0()
977 );
978 break;
979 case 1:
980 di = unsafeIRDirty_0_N( 0/*regparms*/,
981 "MC_(helperc_value_check1_fail)",
982 &MC_(helperc_value_check1_fail),
983 mkIRExprVec_0()
984 );
985 break;
986 case 4:
987 di = unsafeIRDirty_0_N( 0/*regparms*/,
988 "MC_(helperc_value_check4_fail)",
989 &MC_(helperc_value_check4_fail),
990 mkIRExprVec_0()
991 );
992 break;
993 default:
994 di = unsafeIRDirty_0_N( 1/*regparms*/,
995 "MC_(helperc_complain_undef)",
996 &MC_(helperc_complain_undef),
997 mkIRExprVec_1( mkIRExpr_HWord( sz ))
998 );
999 break;
1000 }
sewardjde8a5ae2004-11-06 14:20:54 +00001001 di->guard = cond;
1002 setHelperAnns( mce, di );
1003 stmt( mce->bb, IRStmt_Dirty(di));
1004
1005 /* Set the shadow tmp to be defined. First, update the
1006 orig->shadow tmp mapping to reflect the fact that this shadow is
1007 getting a new value. */
sewardj496a58d2005-03-20 18:44:44 +00001008 tl_assert(isIRAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001009 /* sameKindedAtoms ... */
1010 if (vatom->tag == Iex_Tmp) {
sewardj69f9e3e2004-12-30 02:05:34 +00001011 tl_assert(atom->tag == Iex_Tmp);
sewardjde8a5ae2004-11-06 14:20:54 +00001012 newShadowTmp(mce, atom->Iex.Tmp.tmp);
1013 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
1014 definedOfType(ty));
1015 }
1016}
1017
1018
1019/*------------------------------------------------------------*/
1020/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
1021/*------------------------------------------------------------*/
1022
1023/* Examine the always-defined sections declared in layout to see if
1024 the (offset,size) section is within one. Note, is is an error to
1025 partially fall into such a region: (offset,size) should either be
1026 completely in such a region or completely not-in such a region.
1027*/
1028static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1029{
1030 Int minoffD, maxoffD, i;
1031 Int minoff = offset;
1032 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001033 tl_assert((minoff & ~0xFFFF) == 0);
1034 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001035
1036 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1037 minoffD = mce->layout->alwaysDefd[i].offset;
1038 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001039 tl_assert((minoffD & ~0xFFFF) == 0);
1040 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001041
1042 if (maxoff < minoffD || maxoffD < minoff)
1043 continue; /* no overlap */
1044 if (minoff >= minoffD && maxoff <= maxoffD)
1045 return True; /* completely contained in an always-defd section */
1046
sewardj69f9e3e2004-12-30 02:05:34 +00001047 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001048 }
1049 return False; /* could not find any containing section */
1050}
1051
1052
1053/* Generate into bb suitable actions to shadow this Put. If the state
1054 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001055 supplied V bits to the shadow state. We can pass in either an
1056 original atom or a V-atom, but not both. In the former case the
1057 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001058*/
1059static
sewardj3598ef92004-11-11 02:13:30 +00001060void do_shadow_PUT ( MCEnv* mce, Int offset,
1061 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001062{
sewardj8fc93742004-11-22 11:29:33 +00001063 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001064 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001065 tl_assert(!vatom);
1066 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001067 vatom = expr2vbits( mce, atom );
1068 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001069 tl_assert(vatom);
1070 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001071 }
1072
sewardj8fc93742004-11-22 11:29:33 +00001073 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001074 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001075 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1076 /* later: no ... */
1077 /* emit code to emit a complaint if any of the vbits are 1. */
1078 /* complainIfUndefined(mce, atom); */
1079 } else {
1080 /* Do a plain shadow Put. */
1081 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1082 }
1083}
1084
1085
1086/* Return an expression which contains the V bits corresponding to the
1087 given GETI (passed in in pieces).
1088*/
1089static
1090void do_shadow_PUTI ( MCEnv* mce,
1091 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
1092{
sewardj8fc93742004-11-22 11:29:33 +00001093 IRAtom* vatom;
1094 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001095 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001096
sewardj69f9e3e2004-12-30 02:05:34 +00001097 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001098 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001099 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001100 ty = descr->elemTy;
1101 tyS = shadowType(ty);
1102 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001103 tl_assert(ty != Ity_I1);
1104 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001105 complainIfUndefined(mce,ix);
1106 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1107 /* later: no ... */
1108 /* emit code to emit a complaint if any of the vbits are 1. */
1109 /* complainIfUndefined(mce, atom); */
1110 } else {
1111 /* Do a cloned version of the Put that refers to the shadow
1112 area. */
1113 IRArray* new_descr
1114 = mkIRArray( descr->base + mce->layout->total_sizeB,
1115 tyS, descr->nElems);
1116 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1117 }
1118}
1119
1120
1121/* Return an expression which contains the V bits corresponding to the
1122 given GET (passed in in pieces).
1123*/
1124static
1125IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1126{
1127 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001128 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001129 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1130 /* Always defined, return all zeroes of the relevant type */
1131 return definedOfType(tyS);
1132 } else {
1133 /* return a cloned version of the Get that refers to the shadow
1134 area. */
1135 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1136 }
1137}
1138
1139
1140/* Return an expression which contains the V bits corresponding to the
1141 given GETI (passed in in pieces).
1142*/
1143static
1144IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
1145{
1146 IRType ty = descr->elemTy;
1147 IRType tyS = shadowType(ty);
1148 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001149 tl_assert(ty != Ity_I1);
1150 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001151 complainIfUndefined(mce,ix);
1152 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1153 /* Always defined, return all zeroes of the relevant type */
1154 return definedOfType(tyS);
1155 } else {
1156 /* return a cloned version of the Get that refers to the shadow
1157 area. */
1158 IRArray* new_descr
1159 = mkIRArray( descr->base + mce->layout->total_sizeB,
1160 tyS, descr->nElems);
1161 return IRExpr_GetI( new_descr, ix, bias );
1162 }
1163}
1164
1165
1166/*------------------------------------------------------------*/
1167/*--- Generating approximations for unknown operations, ---*/
1168/*--- using lazy-propagate semantics ---*/
1169/*------------------------------------------------------------*/
1170
1171/* Lazy propagation of undefinedness from two values, resulting in the
1172 specified shadow type.
1173*/
1174static
1175IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1176{
1177 /* force everything via 32-bit intermediaries. */
1178 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001179 tl_assert(isShadowAtom(mce,va1));
1180 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001181 at = mkPCastTo(mce, Ity_I32, va1);
1182 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1183 at = mkPCastTo(mce, finalVty, at);
1184 return at;
1185}
1186
1187
1188/* Do the lazy propagation game from a null-terminated vector of
1189 atoms. This is presumably the arguments to a helper call, so the
1190 IRCallee info is also supplied in order that we can know which
1191 arguments should be ignored (via the .mcx_mask field).
1192*/
1193static
1194IRAtom* mkLazyN ( MCEnv* mce,
1195 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1196{
1197 Int i;
1198 IRAtom* here;
1199 IRAtom* curr = definedOfType(Ity_I32);
1200 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001201 tl_assert(i < 32);
1202 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001203 /* Only take notice of this arg if the callee's mc-exclusion
1204 mask does not say it is to be excluded. */
1205 if (cee->mcx_mask & (1<<i)) {
1206 /* the arg is to be excluded from definedness checking. Do
1207 nothing. */
1208 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1209 } else {
1210 /* calculate the arg's definedness, and pessimistically merge
1211 it in. */
1212 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1213 curr = mkUifU32(mce, here, curr);
1214 }
1215 }
1216 return mkPCastTo(mce, finalVtype, curr );
1217}
1218
1219
1220/*------------------------------------------------------------*/
1221/*--- Generating expensive sequences for exact carry-chain ---*/
1222/*--- propagation in add/sub and related operations. ---*/
1223/*------------------------------------------------------------*/
1224
1225static
1226IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1227 IRAtom* aa, IRAtom* bb )
1228{
sewardj69f9e3e2004-12-30 02:05:34 +00001229 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001230 IRType ty;
1231 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001232
sewardj69f9e3e2004-12-30 02:05:34 +00001233 tl_assert(isShadowAtom(mce,qaa));
1234 tl_assert(isShadowAtom(mce,qbb));
1235 tl_assert(isOriginalAtom(mce,aa));
1236 tl_assert(isOriginalAtom(mce,bb));
1237 tl_assert(sameKindedAtoms(qaa,aa));
1238 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001239
sewardj8fc93742004-11-22 11:29:33 +00001240 ty = Ity_I32;
1241 opAND = Iop_And32;
1242 opOR = Iop_Or32;
1243 opXOR = Iop_Xor32;
1244 opNOT = Iop_Not32;
1245 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001246
1247 // a_min = aa & ~qaa
1248 a_min = assignNew(mce,ty,
1249 binop(opAND, aa,
1250 assignNew(mce,ty, unop(opNOT, qaa))));
1251
1252 // b_min = bb & ~qbb
1253 b_min = assignNew(mce,ty,
1254 binop(opAND, bb,
1255 assignNew(mce,ty, unop(opNOT, qbb))));
1256
1257 // a_max = aa | qaa
1258 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1259
1260 // b_max = bb | qbb
1261 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1262
1263 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1264 return
1265 assignNew(mce,ty,
1266 binop( opOR,
1267 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1268 assignNew(mce,ty,
1269 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1270 assignNew(mce,ty, binop(opADD, a_max, b_max))
1271 )
1272 )
1273 )
1274 );
1275}
1276
1277
1278/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001279/*--- Helpers for dealing with vector primops. ---*/
1280/*------------------------------------------------------------*/
1281
1282/* Vector pessimisation -- pessimise within each lane individually. */
1283
1284static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1285{
1286 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1287}
1288
1289static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1290{
1291 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1292}
1293
1294static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1295{
1296 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1297}
1298
1299static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1300{
1301 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1302}
1303
1304
1305/* Here's a simple scheme capable of handling ops derived from SSE1
1306 code and while only generating ops that can be efficiently
1307 implemented in SSE1. */
1308
1309/* All-lanes versions are straightforward:
1310
sewardjf0c1c582005-02-07 23:47:38 +00001311 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj69f9e3e2004-12-30 02:05:34 +00001312
1313 unary32Fx4(x,y) ==> PCast32x4(x#)
1314
1315 Lowest-lane-only versions are more complex:
1316
sewardjf0c1c582005-02-07 23:47:38 +00001317 binary32F0x4(x,y) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001318 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001319 PCast32(V128to32(UifUV128(x#,y#)))
sewardj69f9e3e2004-12-30 02:05:34 +00001320 )
1321
1322 This is perhaps not so obvious. In particular, it's faster to
sewardjf0c1c582005-02-07 23:47:38 +00001323 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj69f9e3e2004-12-30 02:05:34 +00001324 obvious scheme of taking the bottom 32 bits of each operand
1325 and doing a 32-bit UifU. Basically since UifU is fast and
1326 chopping lanes off vector values is slow.
1327
1328 Finally:
1329
sewardjf0c1c582005-02-07 23:47:38 +00001330 unary32F0x4(x) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001331 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001332 PCast32(V128to32(x#))
sewardj69f9e3e2004-12-30 02:05:34 +00001333 )
1334
1335 Where:
1336
1337 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1338 PCast32x4(v#) = CmpNEZ32x4(v#)
1339*/
1340
1341static
1342IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1343{
1344 IRAtom* at;
1345 tl_assert(isShadowAtom(mce, vatomX));
1346 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001347 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001348 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1349 return at;
1350}
1351
1352static
1353IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1354{
1355 IRAtom* at;
1356 tl_assert(isShadowAtom(mce, vatomX));
1357 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1358 return at;
1359}
1360
1361static
1362IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1363{
1364 IRAtom* at;
1365 tl_assert(isShadowAtom(mce, vatomX));
1366 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001367 at = mkUifUV128(mce, vatomX, vatomY);
1368 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001369 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001370 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001371 return at;
1372}
1373
1374static
1375IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1376{
1377 IRAtom* at;
1378 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001379 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001380 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001381 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001382 return at;
1383}
1384
1385/* --- ... and ... 64Fx2 versions of the same ... --- */
1386
1387static
1388IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1389{
1390 IRAtom* at;
1391 tl_assert(isShadowAtom(mce, vatomX));
1392 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001393 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001394 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1395 return at;
1396}
1397
1398static
1399IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1400{
1401 IRAtom* at;
1402 tl_assert(isShadowAtom(mce, vatomX));
1403 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1404 return at;
1405}
1406
1407static
1408IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1409{
1410 IRAtom* at;
1411 tl_assert(isShadowAtom(mce, vatomX));
1412 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001413 at = mkUifUV128(mce, vatomX, vatomY);
1414 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001415 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001416 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001417 return at;
1418}
1419
1420static
1421IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1422{
1423 IRAtom* at;
1424 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001425 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001426 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001427 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001428 return at;
1429}
1430
1431/* --- --- Vector saturated narrowing --- --- */
1432
1433/* This is quite subtle. What to do is simple:
1434
1435 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1436
1437 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1438
1439 Why this is right is not so simple. Consider a lane in the args,
1440 vatom1 or 2, doesn't matter.
1441
1442 After the PCast, that lane is all 0s (defined) or all
1443 1s(undefined).
1444
1445 Both signed and unsigned saturating narrowing of all 0s produces
1446 all 0s, which is what we want.
1447
1448 The all-1s case is more complex. Unsigned narrowing interprets an
1449 all-1s input as the largest unsigned integer, and so produces all
1450 1s as a result since that is the largest unsigned value at the
1451 smaller width.
1452
1453 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1454 to -1, so we still wind up with all 1s at the smaller width.
1455
1456 So: In short, pessimise the args, then apply the original narrowing
1457 op.
1458*/
1459static
sewardjf0c1c582005-02-07 23:47:38 +00001460IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardj69f9e3e2004-12-30 02:05:34 +00001461 IRAtom* vatom1, IRAtom* vatom2)
1462{
1463 IRAtom *at1, *at2, *at3;
1464 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1465 switch (narrow_op) {
1466 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1467 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1468 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardjf0c1c582005-02-07 23:47:38 +00001469 default: VG_(tool_panic)("vectorNarrowV128");
sewardj69f9e3e2004-12-30 02:05:34 +00001470 }
1471 tl_assert(isShadowAtom(mce,vatom1));
1472 tl_assert(isShadowAtom(mce,vatom2));
1473 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1474 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1475 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1476 return at3;
1477}
1478
1479
1480/* --- --- Vector integer arithmetic --- --- */
1481
1482/* Simple ... UifU the args and per-lane pessimise the results. */
1483static
1484IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1485{
1486 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001487 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001488 at = mkPCast8x16(mce, at);
1489 return at;
1490}
1491
1492static
1493IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1494{
1495 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001496 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001497 at = mkPCast16x8(mce, at);
1498 return at;
1499}
1500
1501static
1502IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1503{
1504 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001505 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001506 at = mkPCast32x4(mce, at);
1507 return at;
1508}
1509
1510static
1511IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1512{
1513 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001514 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001515 at = mkPCast64x2(mce, at);
1516 return at;
1517}
1518
1519
1520/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001521/*--- Generate shadow values from all kinds of IRExprs. ---*/
1522/*------------------------------------------------------------*/
1523
1524static
1525IRAtom* expr2vbits_Binop ( MCEnv* mce,
1526 IROp op,
1527 IRAtom* atom1, IRAtom* atom2 )
1528{
1529 IRType and_or_ty;
1530 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1531 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1532 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1533
1534 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1535 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1536
sewardj69f9e3e2004-12-30 02:05:34 +00001537 tl_assert(isOriginalAtom(mce,atom1));
1538 tl_assert(isOriginalAtom(mce,atom2));
1539 tl_assert(isShadowAtom(mce,vatom1));
1540 tl_assert(isShadowAtom(mce,vatom2));
1541 tl_assert(sameKindedAtoms(atom1,vatom1));
1542 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001543 switch (op) {
1544
sewardjf0c1c582005-02-07 23:47:38 +00001545 /* V128-bit SIMD (SSE2-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001546
1547 case Iop_ShrN16x8:
1548 case Iop_ShrN32x4:
1549 case Iop_ShrN64x2:
1550 case Iop_SarN16x8:
1551 case Iop_SarN32x4:
1552 case Iop_ShlN16x8:
1553 case Iop_ShlN32x4:
1554 case Iop_ShlN64x2:
1555 /* Same scheme as with all other shifts. */
1556 complainIfUndefined(mce, atom2);
1557 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1558
1559 case Iop_QSub8Ux16:
1560 case Iop_QSub8Sx16:
1561 case Iop_Sub8x16:
1562 case Iop_Min8Ux16:
1563 case Iop_Max8Ux16:
1564 case Iop_CmpGT8Sx16:
1565 case Iop_CmpEQ8x16:
1566 case Iop_Avg8Ux16:
1567 case Iop_QAdd8Ux16:
1568 case Iop_QAdd8Sx16:
1569 case Iop_Add8x16:
1570 return binary8Ix16(mce, vatom1, vatom2);
1571
1572 case Iop_QSub16Ux8:
1573 case Iop_QSub16Sx8:
1574 case Iop_Sub16x8:
1575 case Iop_Mul16x8:
1576 case Iop_MulHi16Sx8:
1577 case Iop_MulHi16Ux8:
1578 case Iop_Min16Sx8:
1579 case Iop_Max16Sx8:
1580 case Iop_CmpGT16Sx8:
1581 case Iop_CmpEQ16x8:
1582 case Iop_Avg16Ux8:
1583 case Iop_QAdd16Ux8:
1584 case Iop_QAdd16Sx8:
1585 case Iop_Add16x8:
1586 return binary16Ix8(mce, vatom1, vatom2);
1587
1588 case Iop_Sub32x4:
1589 case Iop_CmpGT32Sx4:
1590 case Iop_CmpEQ32x4:
1591 case Iop_Add32x4:
1592 return binary32Ix4(mce, vatom1, vatom2);
1593
1594 case Iop_Sub64x2:
1595 case Iop_Add64x2:
1596 return binary64Ix2(mce, vatom1, vatom2);
1597
1598 case Iop_QNarrow32Sx4:
1599 case Iop_QNarrow16Sx8:
1600 case Iop_QNarrow16Ux8:
sewardjf0c1c582005-02-07 23:47:38 +00001601 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001602
1603 case Iop_Sub64Fx2:
1604 case Iop_Mul64Fx2:
1605 case Iop_Min64Fx2:
1606 case Iop_Max64Fx2:
1607 case Iop_Div64Fx2:
1608 case Iop_CmpLT64Fx2:
1609 case Iop_CmpLE64Fx2:
1610 case Iop_CmpEQ64Fx2:
1611 case Iop_Add64Fx2:
1612 return binary64Fx2(mce, vatom1, vatom2);
1613
1614 case Iop_Sub64F0x2:
1615 case Iop_Mul64F0x2:
1616 case Iop_Min64F0x2:
1617 case Iop_Max64F0x2:
1618 case Iop_Div64F0x2:
1619 case Iop_CmpLT64F0x2:
1620 case Iop_CmpLE64F0x2:
1621 case Iop_CmpEQ64F0x2:
1622 case Iop_Add64F0x2:
1623 return binary64F0x2(mce, vatom1, vatom2);
1624
sewardjf0c1c582005-02-07 23:47:38 +00001625 /* V128-bit SIMD (SSE1-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001626
1627 case Iop_Sub32Fx4:
1628 case Iop_Mul32Fx4:
1629 case Iop_Min32Fx4:
1630 case Iop_Max32Fx4:
1631 case Iop_Div32Fx4:
1632 case Iop_CmpLT32Fx4:
1633 case Iop_CmpLE32Fx4:
1634 case Iop_CmpEQ32Fx4:
1635 case Iop_Add32Fx4:
1636 return binary32Fx4(mce, vatom1, vatom2);
1637
1638 case Iop_Sub32F0x4:
1639 case Iop_Mul32F0x4:
1640 case Iop_Min32F0x4:
1641 case Iop_Max32F0x4:
1642 case Iop_Div32F0x4:
1643 case Iop_CmpLT32F0x4:
1644 case Iop_CmpLE32F0x4:
1645 case Iop_CmpEQ32F0x4:
1646 case Iop_Add32F0x4:
1647 return binary32F0x4(mce, vatom1, vatom2);
1648
sewardjf0c1c582005-02-07 23:47:38 +00001649 /* V128-bit data-steering */
1650 case Iop_SetV128lo32:
1651 case Iop_SetV128lo64:
1652 case Iop_64HLtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001653 case Iop_InterleaveLO64x2:
1654 case Iop_InterleaveLO32x4:
1655 case Iop_InterleaveLO16x8:
1656 case Iop_InterleaveLO8x16:
1657 case Iop_InterleaveHI64x2:
1658 case Iop_InterleaveHI32x4:
1659 case Iop_InterleaveHI16x8:
1660 case Iop_InterleaveHI8x16:
1661 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1662
1663 /* Scalar floating point */
1664
sewardj3598ef92004-11-11 02:13:30 +00001665 case Iop_RoundF64:
1666 case Iop_F64toI64:
sewardj69f9e3e2004-12-30 02:05:34 +00001667 case Iop_I64toF64:
1668 /* First arg is I32 (rounding mode), second is F64 or I64
1669 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001670 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1671
1672 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1673 /* Takes two F64 args. */
sewardjde8a5ae2004-11-06 14:20:54 +00001674 case Iop_F64toI32:
sewardj69f9e3e2004-12-30 02:05:34 +00001675 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001676 /* First arg is I32 (rounding mode), second is F64 (data). */
1677 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1678
1679 case Iop_F64toI16:
1680 /* First arg is I32 (rounding mode), second is F64 (data). */
1681 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1682
sewardj3598ef92004-11-11 02:13:30 +00001683 case Iop_ScaleF64:
1684 case Iop_Yl2xF64:
1685 case Iop_Yl2xp1F64:
1686 case Iop_PRemF64:
1687 case Iop_AtanF64:
1688 case Iop_AddF64:
1689 case Iop_DivF64:
1690 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001691 case Iop_MulF64:
1692 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1693
sewardj3598ef92004-11-11 02:13:30 +00001694 case Iop_CmpF64:
1695 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1696
sewardjde8a5ae2004-11-06 14:20:54 +00001697 /* non-FP after here */
1698
1699 case Iop_DivModU64to32:
1700 case Iop_DivModS64to32:
1701 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1702
sewardj3598ef92004-11-11 02:13:30 +00001703 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001704 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001705 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001706 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001707
1708 case Iop_MullS32:
1709 case Iop_MullU32: {
1710 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1711 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1712 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1713 }
1714
sewardj3598ef92004-11-11 02:13:30 +00001715 case Iop_MullS16:
1716 case Iop_MullU16: {
1717 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1718 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1719 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1720 }
1721
1722 case Iop_MullS8:
1723 case Iop_MullU8: {
1724 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1725 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1726 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1727 }
1728
sewardjde8a5ae2004-11-06 14:20:54 +00001729 case Iop_Add32:
1730# if 0
1731 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1732# endif
1733 case Iop_Sub32:
1734 case Iop_Mul32:
1735 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1736
sewardj3598ef92004-11-11 02:13:30 +00001737 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001738 case Iop_Add16:
1739 case Iop_Sub16:
1740 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1741
1742 case Iop_Sub8:
1743 case Iop_Add8:
1744 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1745
1746 case Iop_CmpLE32S: case Iop_CmpLE32U:
1747 case Iop_CmpLT32U: case Iop_CmpLT32S:
1748 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001749 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001750
sewardj3598ef92004-11-11 02:13:30 +00001751 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001752 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001753
1754 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001755 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001756
1757 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1758 /* Complain if the shift amount is undefined. Then simply
1759 shift the first arg's V bits by the real shift amount. */
1760 complainIfUndefined(mce, atom2);
1761 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1762
sewardj69f9e3e2004-12-30 02:05:34 +00001763 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001764 /* Same scheme as with 32-bit shifts. */
1765 complainIfUndefined(mce, atom2);
1766 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1767
sewardj3598ef92004-11-11 02:13:30 +00001768 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001769 /* Same scheme as with 32-bit shifts. */
1770 complainIfUndefined(mce, atom2);
1771 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1772
1773 case Iop_Shl64: case Iop_Shr64:
1774 /* Same scheme as with 32-bit shifts. */
1775 complainIfUndefined(mce, atom2);
1776 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1777
sewardjf0c1c582005-02-07 23:47:38 +00001778 case Iop_AndV128:
1779 uifu = mkUifUV128; difd = mkDifDV128;
1780 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001781 case Iop_And64:
1782 uifu = mkUifU64; difd = mkDifD64;
1783 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001784 case Iop_And32:
1785 uifu = mkUifU32; difd = mkDifD32;
1786 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001787 case Iop_And16:
1788 uifu = mkUifU16; difd = mkDifD16;
1789 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001790 case Iop_And8:
1791 uifu = mkUifU8; difd = mkDifD8;
1792 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1793
sewardjf0c1c582005-02-07 23:47:38 +00001794 case Iop_OrV128:
1795 uifu = mkUifUV128; difd = mkDifDV128;
1796 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001797 case Iop_Or64:
1798 uifu = mkUifU64; difd = mkDifD64;
1799 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001800 case Iop_Or32:
1801 uifu = mkUifU32; difd = mkDifD32;
1802 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1803 case Iop_Or16:
1804 uifu = mkUifU16; difd = mkDifD16;
1805 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1806 case Iop_Or8:
1807 uifu = mkUifU8; difd = mkDifD8;
1808 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1809
1810 do_And_Or:
1811 return
1812 assignNew(
1813 mce,
1814 and_or_ty,
1815 difd(mce, uifu(mce, vatom1, vatom2),
1816 difd(mce, improve(mce, atom1, vatom1),
1817 improve(mce, atom2, vatom2) ) ) );
1818
1819 case Iop_Xor8:
1820 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001821 case Iop_Xor16:
1822 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001823 case Iop_Xor32:
1824 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001825 case Iop_Xor64:
1826 return mkUifU64(mce, vatom1, vatom2);
sewardjf0c1c582005-02-07 23:47:38 +00001827 case Iop_XorV128:
1828 return mkUifUV128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001829
1830 default:
1831 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001832 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001833 }
1834}
1835
1836
1837static
1838IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1839{
1840 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001841 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001842 switch (op) {
1843
sewardj69f9e3e2004-12-30 02:05:34 +00001844 case Iop_Sqrt64Fx2:
1845 return unary64Fx2(mce, vatom);
1846
1847 case Iop_Sqrt64F0x2:
1848 return unary64F0x2(mce, vatom);
1849
1850 case Iop_Sqrt32Fx4:
1851 case Iop_RSqrt32Fx4:
1852 case Iop_Recip32Fx4:
1853 return unary32Fx4(mce, vatom);
1854
1855 case Iop_Sqrt32F0x4:
1856 case Iop_RSqrt32F0x4:
1857 case Iop_Recip32F0x4:
1858 return unary32F0x4(mce, vatom);
1859
sewardjf0c1c582005-02-07 23:47:38 +00001860 case Iop_32UtoV128:
1861 case Iop_64UtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001862 return assignNew(mce, Ity_V128, unop(op, vatom));
1863
sewardjde8a5ae2004-11-06 14:20:54 +00001864 case Iop_F32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001865 case Iop_I32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001866 case Iop_NegF64:
1867 case Iop_SinF64:
1868 case Iop_CosF64:
1869 case Iop_TanF64:
1870 case Iop_SqrtF64:
1871 case Iop_AbsF64:
1872 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001873 return mkPCastTo(mce, Ity_I64, vatom);
1874
sewardj3598ef92004-11-11 02:13:30 +00001875 case Iop_Clz32:
1876 case Iop_Ctz32:
1877 return mkPCastTo(mce, Ity_I32, vatom);
1878
1879 case Iop_32Sto64:
1880 case Iop_32Uto64:
sewardjf0c1c582005-02-07 23:47:38 +00001881 case Iop_V128to64:
1882 case Iop_V128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001883 return assignNew(mce, Ity_I64, unop(op, vatom));
1884
sewardjde8a5ae2004-11-06 14:20:54 +00001885 case Iop_64to32:
1886 case Iop_64HIto32:
1887 case Iop_1Uto32:
1888 case Iop_8Uto32:
1889 case Iop_16Uto32:
1890 case Iop_16Sto32:
1891 case Iop_8Sto32:
1892 return assignNew(mce, Ity_I32, unop(op, vatom));
1893
1894 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001895 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001896 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001897 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001898 return assignNew(mce, Ity_I16, unop(op, vatom));
1899
1900 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001901 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001902 case Iop_32to8:
1903 return assignNew(mce, Ity_I8, unop(op, vatom));
1904
1905 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001906 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001907
sewardj3598ef92004-11-11 02:13:30 +00001908 case Iop_ReinterpF64asI64:
1909 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001910 case Iop_ReinterpI32asF32:
sewardjf0c1c582005-02-07 23:47:38 +00001911 case Iop_NotV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001912 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00001913 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001914 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001915 case Iop_Not8:
1916 case Iop_Not1:
1917 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001918
sewardjde8a5ae2004-11-06 14:20:54 +00001919 default:
1920 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001921 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00001922 }
1923}
1924
1925
sewardj69f9e3e2004-12-30 02:05:34 +00001926/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00001927static
sewardj69f9e3e2004-12-30 02:05:34 +00001928IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001929{
1930 void* helper;
sewardjde8c9872005-03-25 13:48:55 +00001931 HChar* hname;
sewardjde8a5ae2004-11-06 14:20:54 +00001932 IRDirty* di;
1933 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00001934 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001935
sewardj69f9e3e2004-12-30 02:05:34 +00001936 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00001937
1938 /* First, emit a definedness test for the address. This also sets
1939 the address (shadow) to 'defined' following the test. */
1940 complainIfUndefined( mce, addr );
1941
1942 /* Now cook up a call to the relevant helper function, to read the
1943 data V bits from shadow memory. */
1944 ty = shadowType(ty);
1945 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001946 case Ity_I64: helper = &MC_(helperc_LOADV8);
1947 hname = "MC_(helperc_LOADV8)";
1948 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001949 case Ity_I32: helper = &MC_(helperc_LOADV4);
1950 hname = "MC_(helperc_LOADV4)";
1951 break;
1952 case Ity_I16: helper = &MC_(helperc_LOADV2);
1953 hname = "MC_(helperc_LOADV2)";
1954 break;
1955 case Ity_I8: helper = &MC_(helperc_LOADV1);
1956 hname = "MC_(helperc_LOADV1)";
1957 break;
1958 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001959 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00001960 }
1961
sewardj3598ef92004-11-11 02:13:30 +00001962 /* Generate the actual address into addrAct. */
1963 if (bias == 0) {
1964 addrAct = addr;
1965 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001966 IROp mkAdd;
1967 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00001968 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00001969 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
1970 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1971 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00001972 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1973 }
1974
sewardjde8a5ae2004-11-06 14:20:54 +00001975 /* We need to have a place to park the V bits we're just about to
1976 read. */
1977 datavbits = newIRTemp(mce->bb->tyenv, ty);
1978 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00001979 1/*regparms*/, hname, helper,
1980 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00001981 setHelperAnns( mce, di );
1982 stmt( mce->bb, IRStmt_Dirty(di) );
1983
1984 return mkexpr(datavbits);
1985}
1986
1987
1988static
sewardj69f9e3e2004-12-30 02:05:34 +00001989IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
1990{
1991 IRAtom *v64hi, *v64lo;
1992 switch (shadowType(ty)) {
1993 case Ity_I8:
1994 case Ity_I16:
1995 case Ity_I32:
1996 case Ity_I64:
1997 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
1998 case Ity_V128:
1999 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
2000 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
2001 return assignNew( mce,
2002 Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +00002003 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj69f9e3e2004-12-30 02:05:34 +00002004 default:
2005 VG_(tool_panic)("expr2vbits_LDle");
2006 }
2007}
2008
2009
2010static
sewardjde8a5ae2004-11-06 14:20:54 +00002011IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00002012 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00002013{
2014 IRAtom *vbitsC, *vbits0, *vbitsX;
2015 IRType ty;
2016 /* Given Mux0X(cond,expr0,exprX), generate
2017 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2018 That is, steer the V bits like the originals, but trash the
2019 result if the steering value is undefined. This gives
2020 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00002021 tl_assert(isOriginalAtom(mce, cond));
2022 tl_assert(isOriginalAtom(mce, expr0));
2023 tl_assert(isOriginalAtom(mce, exprX));
sewardjde8a5ae2004-11-06 14:20:54 +00002024
2025 vbitsC = expr2vbits(mce, cond);
2026 vbits0 = expr2vbits(mce, expr0);
2027 vbitsX = expr2vbits(mce, exprX);
2028 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2029
2030 return
2031 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2032 mkPCastTo(mce, ty, vbitsC) );
2033}
2034
2035/* --------- This is the main expression-handling function. --------- */
2036
2037static
2038IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2039{
2040 switch (e->tag) {
2041
2042 case Iex_Get:
2043 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2044
2045 case Iex_GetI:
2046 return shadow_GETI( mce, e->Iex.GetI.descr,
2047 e->Iex.GetI.ix, e->Iex.GetI.bias );
2048
2049 case Iex_Tmp:
2050 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
2051
2052 case Iex_Const:
2053 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2054
2055 case Iex_Binop:
2056 return expr2vbits_Binop(
2057 mce,
2058 e->Iex.Binop.op,
2059 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2060 );
2061
2062 case Iex_Unop:
2063 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2064
2065 case Iex_LDle:
sewardj3598ef92004-11-11 02:13:30 +00002066 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
2067 e->Iex.LDle.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002068
2069 case Iex_CCall:
2070 return mkLazyN( mce, e->Iex.CCall.args,
2071 e->Iex.CCall.retty,
2072 e->Iex.CCall.cee );
2073
2074 case Iex_Mux0X:
2075 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2076 e->Iex.Mux0X.exprX);
2077
2078 default:
2079 VG_(printf)("\n");
2080 ppIRExpr(e);
2081 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002082 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002083 }
2084}
2085
2086/*------------------------------------------------------------*/
2087/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2088/*------------------------------------------------------------*/
2089
2090/* Widen a value to the host word size. */
2091
2092static
2093IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2094{
sewardj69f9e3e2004-12-30 02:05:34 +00002095 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002096
sewardj8fc93742004-11-22 11:29:33 +00002097 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002098 tl_assert(isShadowAtom(mce,vatom));
2099
2100 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2101 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002102
sewardjde8a5ae2004-11-06 14:20:54 +00002103 if (tyH == Ity_I32) {
2104 switch (ty) {
2105 case Ity_I32: return vatom;
2106 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2107 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2108 default: goto unhandled;
2109 }
2110 } else {
2111 goto unhandled;
2112 }
2113 unhandled:
2114 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002115 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002116}
2117
2118
sewardj3598ef92004-11-11 02:13:30 +00002119/* Generate a shadow store. addr is always the original address atom.
2120 You can pass in either originals or V-bits for the data atom, but
2121 obviously not both. */
2122
sewardjde8a5ae2004-11-06 14:20:54 +00002123static
sewardj3598ef92004-11-11 02:13:30 +00002124void do_shadow_STle ( MCEnv* mce,
2125 IRAtom* addr, UInt bias,
2126 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002127{
sewardj69f9e3e2004-12-30 02:05:34 +00002128 IROp mkAdd;
2129 IRType ty, tyAddr;
2130 IRDirty *di, *diLo64, *diHi64;
2131 IRAtom *addrAct, *addrLo64, *addrHi64;
2132 IRAtom *vdataLo64, *vdataHi64;
2133 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002134 void* helper = NULL;
2135 Char* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002136
2137 tyAddr = mce->hWordTy;
2138 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2139 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2140
2141 di = diLo64 = diHi64 = NULL;
2142 eBias = eBias0 = eBias8 = NULL;
2143 addrAct = addrLo64 = addrHi64 = NULL;
2144 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002145
sewardj3598ef92004-11-11 02:13:30 +00002146 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002147 tl_assert(!vdata);
2148 tl_assert(isOriginalAtom(mce, data));
2149 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002150 vdata = expr2vbits( mce, data );
2151 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002152 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002153 }
sewardjde8a5ae2004-11-06 14:20:54 +00002154
sewardj69f9e3e2004-12-30 02:05:34 +00002155 tl_assert(isOriginalAtom(mce,addr));
2156 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002157
2158 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002159
2160 /* First, emit a definedness test for the address. This also sets
2161 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002162 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002163
sewardj69f9e3e2004-12-30 02:05:34 +00002164 /* Now decide which helper function to call to write the data V
2165 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002166 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002167 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002168 case Ity_I64: helper = &MC_(helperc_STOREV8);
2169 hname = "MC_(helperc_STOREV8)";
2170 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002171 case Ity_I32: helper = &MC_(helperc_STOREV4);
2172 hname = "MC_(helperc_STOREV4)";
2173 break;
2174 case Ity_I16: helper = &MC_(helperc_STOREV2);
2175 hname = "MC_(helperc_STOREV2)";
2176 break;
2177 case Ity_I8: helper = &MC_(helperc_STOREV1);
2178 hname = "MC_(helperc_STOREV1)";
2179 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002180 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002181 }
2182
sewardj69f9e3e2004-12-30 02:05:34 +00002183 if (ty == Ity_V128) {
2184
sewardjf0c1c582005-02-07 23:47:38 +00002185 /* V128-bit case */
sewardj69f9e3e2004-12-30 02:05:34 +00002186 /* See comment in next clause re 64-bit regparms */
2187 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2188 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
sewardjf0c1c582005-02-07 23:47:38 +00002189 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002190 diLo64 = unsafeIRDirty_0_N(
2191 1/*regparms*/, hname, helper,
2192 mkIRExprVec_2( addrLo64, vdataLo64 ));
2193
2194 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2195 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
sewardjf0c1c582005-02-07 23:47:38 +00002196 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002197 diHi64 = unsafeIRDirty_0_N(
2198 1/*regparms*/, hname, helper,
2199 mkIRExprVec_2( addrHi64, vdataHi64 ));
2200
2201 setHelperAnns( mce, diLo64 );
2202 setHelperAnns( mce, diHi64 );
2203 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2204 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2205
sewardj3598ef92004-11-11 02:13:30 +00002206 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002207
2208 /* 8/16/32/64-bit cases */
2209 /* Generate the actual address into addrAct. */
2210 if (bias == 0) {
2211 addrAct = addr;
2212 } else {
2213 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2214 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2215 }
2216
2217 if (ty == Ity_I64) {
2218 /* We can't do this with regparm 2 on 32-bit platforms, since
2219 the back ends aren't clever enough to handle 64-bit
2220 regparm args. Therefore be different. */
2221 di = unsafeIRDirty_0_N(
2222 1/*regparms*/, hname, helper,
2223 mkIRExprVec_2( addrAct, vdata ));
2224 } else {
2225 di = unsafeIRDirty_0_N(
2226 2/*regparms*/, hname, helper,
2227 mkIRExprVec_2( addrAct,
2228 zwidenToHostWord( mce, vdata )));
2229 }
2230 setHelperAnns( mce, di );
2231 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002232 }
2233
sewardjde8a5ae2004-11-06 14:20:54 +00002234}
2235
2236
sewardj3598ef92004-11-11 02:13:30 +00002237/* Do lazy pessimistic propagation through a dirty helper call, by
2238 looking at the annotations on it. This is the most complex part of
2239 Memcheck. */
2240
2241static IRType szToITy ( Int n )
2242{
2243 switch (n) {
2244 case 1: return Ity_I8;
2245 case 2: return Ity_I16;
2246 case 4: return Ity_I32;
2247 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002248 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002249 }
2250}
2251
2252static
2253void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2254{
sewardj69f9e3e2004-12-30 02:05:34 +00002255 Int i, n, offset, toDo, gSz, gOff;
2256 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002257 IRType tyAddr, tySrc, tyDst;
2258 IRTemp dst;
2259
2260 /* First check the guard. */
2261 complainIfUndefined(mce, d->guard);
2262
2263 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002264 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002265
2266 /* Inputs: unmasked args */
2267 for (i = 0; d->args[i]; i++) {
2268 if (d->cee->mcx_mask & (1<<i)) {
2269 /* ignore this arg */
2270 } else {
2271 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2272 curr = mkUifU32(mce, here, curr);
2273 }
2274 }
2275
2276 /* Inputs: guest state that we read. */
2277 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002278 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002279 if (d->fxState[i].fx == Ifx_Write)
2280 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002281
2282 /* Ignore any sections marked as 'always defined'. */
2283 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2284 if (0)
2285 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2286 d->fxState[i].offset, d->fxState[i].size );
2287 continue;
2288 }
2289
sewardj3598ef92004-11-11 02:13:30 +00002290 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002291 consider it. If larger than 8 bytes, deal with it in 8-byte
2292 chunks. */
2293 gSz = d->fxState[i].size;
2294 gOff = d->fxState[i].offset;
2295 tl_assert(gSz > 0);
2296 while (True) {
2297 if (gSz == 0) break;
2298 n = gSz <= 8 ? gSz : 8;
2299 /* update 'curr' with UifU of the state slice
2300 gOff .. gOff+n-1 */
2301 tySrc = szToITy( n );
2302 src = assignNew( mce, tySrc,
2303 shadow_GET(mce, gOff, tySrc ) );
2304 here = mkPCastTo( mce, Ity_I32, src );
2305 curr = mkUifU32(mce, here, curr);
2306 gSz -= n;
2307 gOff += n;
2308 }
2309
sewardj3598ef92004-11-11 02:13:30 +00002310 }
2311
2312 /* Inputs: memory. First set up some info needed regardless of
2313 whether we're doing reads or writes. */
2314 tyAddr = Ity_INVALID;
2315
2316 if (d->mFx != Ifx_None) {
2317 /* Because we may do multiple shadow loads/stores from the same
2318 base address, it's best to do a single test of its
2319 definedness right now. Post-instrumentation optimisation
2320 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002321 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002322 complainIfUndefined(mce, d->mAddr);
2323
2324 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002325 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2326 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002327 }
2328
2329 /* Deal with memory inputs (reads or modifies) */
2330 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2331 offset = 0;
2332 toDo = d->mSize;
2333 /* chew off 32-bit chunks */
2334 while (toDo >= 4) {
2335 here = mkPCastTo(
2336 mce, Ity_I32,
2337 expr2vbits_LDle ( mce, Ity_I32,
2338 d->mAddr, d->mSize - toDo )
2339 );
2340 curr = mkUifU32(mce, here, curr);
2341 toDo -= 4;
2342 }
2343 /* chew off 16-bit chunks */
2344 while (toDo >= 2) {
2345 here = mkPCastTo(
2346 mce, Ity_I32,
2347 expr2vbits_LDle ( mce, Ity_I16,
2348 d->mAddr, d->mSize - toDo )
2349 );
2350 curr = mkUifU32(mce, here, curr);
2351 toDo -= 2;
2352 }
sewardj69f9e3e2004-12-30 02:05:34 +00002353 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002354 }
2355
2356 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2357 all the inputs to the helper. Now we need to re-distribute the
2358 results to all destinations. */
2359
2360 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002361 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002362 dst = findShadowTmp(mce, d->tmp);
2363 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2364 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2365 }
2366
2367 /* Outputs: guest state that we write or modify. */
2368 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002369 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002370 if (d->fxState[i].fx == Ifx_Read)
2371 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002372 /* Ignore any sections marked as 'always defined'. */
2373 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2374 continue;
2375 /* This state element is written or modified. So we need to
2376 consider it. If larger than 8 bytes, deal with it in 8-byte
2377 chunks. */
2378 gSz = d->fxState[i].size;
2379 gOff = d->fxState[i].offset;
2380 tl_assert(gSz > 0);
2381 while (True) {
2382 if (gSz == 0) break;
2383 n = gSz <= 8 ? gSz : 8;
2384 /* Write suitably-casted 'curr' to the state slice
2385 gOff .. gOff+n-1 */
2386 tyDst = szToITy( n );
2387 do_shadow_PUT( mce, gOff,
2388 NULL, /* original atom */
2389 mkPCastTo( mce, tyDst, curr ) );
2390 gSz -= n;
2391 gOff += n;
2392 }
sewardj3598ef92004-11-11 02:13:30 +00002393 }
2394
2395 /* Outputs: memory that we write or modify. */
2396 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2397 offset = 0;
2398 toDo = d->mSize;
2399 /* chew off 32-bit chunks */
2400 while (toDo >= 4) {
2401 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2402 NULL, /* original data */
2403 mkPCastTo( mce, Ity_I32, curr ) );
2404 toDo -= 4;
2405 }
2406 /* chew off 16-bit chunks */
2407 while (toDo >= 2) {
2408 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2409 NULL, /* original data */
2410 mkPCastTo( mce, Ity_I16, curr ) );
2411 toDo -= 2;
2412 }
sewardj69f9e3e2004-12-30 02:05:34 +00002413 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002414 }
2415
2416}
2417
2418
sewardjde8a5ae2004-11-06 14:20:54 +00002419/*------------------------------------------------------------*/
2420/*--- Memcheck main ---*/
2421/*------------------------------------------------------------*/
2422
sewardj3598ef92004-11-11 02:13:30 +00002423static Bool isBogusAtom ( IRAtom* at )
2424{
2425 ULong n = 0;
2426 IRConst* con;
sewardj496a58d2005-03-20 18:44:44 +00002427 tl_assert(isIRAtom(at));
sewardj3598ef92004-11-11 02:13:30 +00002428 if (at->tag == Iex_Tmp)
2429 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002430 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002431 con = at->Iex.Const.con;
2432 switch (con->tag) {
2433 case Ico_U8: n = (ULong)con->Ico.U8; break;
2434 case Ico_U16: n = (ULong)con->Ico.U16; break;
2435 case Ico_U32: n = (ULong)con->Ico.U32; break;
2436 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002437 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002438 }
2439 /* VG_(printf)("%llx\n", n); */
2440 return (n == 0xFEFEFEFF
2441 || n == 0x80808080
2442 || n == 0x1010101
2443 || n == 1010100);
2444}
2445
2446static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2447{
2448 Int i;
2449 IRExpr* e;
2450 switch (st->tag) {
2451 case Ist_Tmp:
2452 e = st->Ist.Tmp.data;
2453 switch (e->tag) {
2454 case Iex_Get:
2455 case Iex_Tmp:
2456 return False;
2457 case Iex_Unop:
2458 return isBogusAtom(e->Iex.Unop.arg);
2459 case Iex_Binop:
2460 return isBogusAtom(e->Iex.Binop.arg1)
2461 || isBogusAtom(e->Iex.Binop.arg2);
2462 case Iex_Mux0X:
2463 return isBogusAtom(e->Iex.Mux0X.cond)
2464 || isBogusAtom(e->Iex.Mux0X.expr0)
2465 || isBogusAtom(e->Iex.Mux0X.exprX);
2466 case Iex_LDle:
2467 return isBogusAtom(e->Iex.LDle.addr);
2468 case Iex_CCall:
2469 for (i = 0; e->Iex.CCall.args[i]; i++)
2470 if (isBogusAtom(e->Iex.CCall.args[i]))
2471 return True;
2472 return False;
2473 default:
2474 goto unhandled;
2475 }
2476 case Ist_Put:
2477 return isBogusAtom(st->Ist.Put.data);
2478 case Ist_STle:
2479 return isBogusAtom(st->Ist.STle.addr)
2480 || isBogusAtom(st->Ist.STle.data);
2481 case Ist_Exit:
sewardj1ea1b612005-03-26 13:02:20 +00002482 return isBogusAtom(st->Ist.Exit.guard);
sewardj3598ef92004-11-11 02:13:30 +00002483 default:
2484 unhandled:
2485 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002486 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002487 }
2488}
sewardj3598ef92004-11-11 02:13:30 +00002489
sewardj1ea1b612005-03-26 13:02:20 +00002490IRBB* mc_instrument ( IRBB* bb_in, VexGuestLayout* layout,
2491 IRType gWordTy, IRType hWordTy )
sewardjde8a5ae2004-11-06 14:20:54 +00002492{
sewardj3598ef92004-11-11 02:13:30 +00002493 Bool verboze = False; //True;
2494
2495 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002496
2497 Int i, j, first_stmt;
2498 IRStmt* st;
2499 MCEnv mce;
2500
2501 /* Set up BB */
2502 IRBB* bb = emptyIRBB();
2503 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
2504 bb->next = dopyIRExpr(bb_in->next);
2505 bb->jumpkind = bb_in->jumpkind;
2506
2507 /* Set up the running environment. Only .bb is modified as we go
2508 along. */
2509 mce.bb = bb;
2510 mce.layout = layout;
2511 mce.n_originalTmps = bb->tyenv->types_used;
2512 mce.hWordTy = hWordTy;
2513 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2514 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002515 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002516
2517 /* Iterate over the stmts. */
2518
2519 for (i = 0; i < bb_in->stmts_used; i++) {
2520 st = bb_in->stmts[i];
2521 if (!st) continue;
2522
sewardj69f9e3e2004-12-30 02:05:34 +00002523 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002524
2525 /*
2526 if (!hasBogusLiterals) {
2527 hasBogusLiterals = checkForBogusLiterals(st);
2528 if (hasBogusLiterals) {
2529 VG_(printf)("bogus: ");
2530 ppIRStmt(st);
2531 VG_(printf)("\n");
2532 }
2533 }
2534 */
sewardjde8a5ae2004-11-06 14:20:54 +00002535 first_stmt = bb->stmts_used;
2536
2537 if (verboze) {
2538 ppIRStmt(st);
2539 VG_(printf)("\n\n");
2540 }
2541
2542 switch (st->tag) {
2543
2544 case Ist_Tmp:
2545 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
2546 expr2vbits( &mce, st->Ist.Tmp.data) );
2547 break;
2548
2549 case Ist_Put:
2550 do_shadow_PUT( &mce,
2551 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002552 st->Ist.Put.data,
2553 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002554 break;
2555
2556 case Ist_PutI:
2557 do_shadow_PUTI( &mce,
2558 st->Ist.PutI.descr,
2559 st->Ist.PutI.ix,
2560 st->Ist.PutI.bias,
2561 st->Ist.PutI.data );
2562 break;
2563
2564 case Ist_STle:
sewardj3598ef92004-11-11 02:13:30 +00002565 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
2566 st->Ist.STle.data,
2567 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002568 break;
2569
2570 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002571 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002572 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002573 break;
2574
2575 case Ist_Dirty:
2576 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002577 break;
2578
sewardj1ea1b612005-03-26 13:02:20 +00002579 case Ist_IMark:
2580 case Ist_NoOp:
2581 break;
2582
sewardjde8a5ae2004-11-06 14:20:54 +00002583 default:
2584 VG_(printf)("\n");
2585 ppIRStmt(st);
2586 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002587 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002588
2589 } /* switch (st->tag) */
2590
2591 if (verboze) {
2592 for (j = first_stmt; j < bb->stmts_used; j++) {
2593 VG_(printf)(" ");
2594 ppIRStmt(bb->stmts[j]);
2595 VG_(printf)("\n");
2596 }
2597 VG_(printf)("\n");
2598 }
2599
2600 addStmtToIRBB(bb, st);
2601
2602 }
2603
2604 /* Now we need to complain if the jump target is undefined. */
2605 first_stmt = bb->stmts_used;
2606
2607 if (verboze) {
2608 VG_(printf)("bb->next = ");
2609 ppIRExpr(bb->next);
2610 VG_(printf)("\n\n");
2611 }
2612
2613 complainIfUndefined( &mce, bb->next );
2614
2615 if (verboze) {
2616 for (j = first_stmt; j < bb->stmts_used; j++) {
2617 VG_(printf)(" ");
2618 ppIRStmt(bb->stmts[j]);
2619 VG_(printf)("\n");
2620 }
2621 VG_(printf)("\n");
2622 }
2623
2624 return bb;
2625}
cerionaee45242005-03-17 14:03:36 +00002626#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002627
2628/*--------------------------------------------------------------------*/
2629/*--- end mc_translate.c ---*/
2630/*--------------------------------------------------------------------*/