blob: e31ddf9302cd11a19235ee9bf77f3ba3a68f3956 [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
sewardjf05537e2004-10-14 01:08:12 +000042#define N_ORIGBUF 1000
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;
sewardjced9fe52004-07-07 11:55:36 +000069
70 if (argc != 2) {
71 fprintf(stderr, "usage: vex file.org\n");
72 exit(1);
73 }
74 f = fopen(argv[1], "r");
75 if (!f) {
76 fprintf(stderr, "can't open `%s'\n", argv[1]);
77 exit(1);
78 }
79
sewardjb5bf2e02004-10-25 13:06:17 +000080 /* Run with default params. However, we can't allow bb chasing
81 since that causes the front end to get segfaults when it tries
sewardj5bd4d162004-11-10 13:02:48 +000082 to read code outside the initial BB we hand it. So when calling
83 LibVEX_Translate, send in a chase-into predicate that always
84 returns False. */
sewardjb5bf2e02004-10-25 13:06:17 +000085 LibVEX_default_VexControl ( &vcon );
sewardjb4952402004-10-26 13:24:50 +000086 vcon.iropt_level = 2;
sewardjc279b3f2005-03-16 18:10:45 +000087 vcon.guest_max_insns = 50;
sewardjb5bf2e02004-10-25 13:06:17 +000088
sewardjced9fe52004-07-07 11:55:36 +000089 LibVEX_Init ( &failure_exit, &log_bytes,
sewardj1f40a0a2004-07-21 12:28:07 +000090 1, /* debug_paranoia */
sewardjabe017e2004-10-29 23:42:36 +000091 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +000092 &vcon );
sewardjced9fe52004-07-07 11:55:36 +000093
sewardjea64e142004-07-22 16:47:21 +000094
sewardjced9fe52004-07-07 11:55:36 +000095 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +000096
sewardjced9fe52004-07-07 11:55:36 +000097 fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +000098 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +000099 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +0000100
101 if (n_bbs_done == TEST_N_BBS) break;
102 n_bbs_done++;
103
sewardjced9fe52004-07-07 11:55:36 +0000104 /* first line is: . bb-number bb-addr n-bytes */
105 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
106 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000107 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000108 assert(orig_nbytes >= 1);
109 assert(!feof(f));
110 fgets(linebuf, N_LINEBUF,f);
111 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000112
sewardjced9fe52004-07-07 11:55:36 +0000113 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000114 if (verbose)
sewardj07a54cc2005-02-04 21:18:55 +0000115 printf("============ Basic Block %d, Done %d, "
sewardj4459baa2004-09-10 20:00:46 +0000116 "Start %x, nbytes %2d ============",
sewardj07a54cc2005-02-04 21:18:55 +0000117 bb_number, n_bbs_done-1, orig_addr, orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000118
sewardjced9fe52004-07-07 11:55:36 +0000119 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
120 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000121 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
122 origbuf[i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000123 }
124
sewardjabe017e2004-10-29 23:42:36 +0000125 for (i = 0; i < TEST_N_ITERS; i++)
126 tres
127 = LibVEX_Translate (
cerionaee45242005-03-17 14:03:36 +0000128#if 0 /* ppc32 -> ppc32 */
129 VexArchPPC32, VexSubArchPPC32_noAV,
130 VexArchPPC32, VexSubArchPPC32_noAV,
131#endif
sewardj07a54cc2005-02-04 21:18:55 +0000132#if 0 /* ppc32 -> x86 */
133 VexArchPPC32, VexSubArchPPC32_noAV,
sewardjc3263ee2004-12-29 17:48:22 +0000134 VexArchX86, VexSubArchX86_sse2,
sewardj07a54cc2005-02-04 21:18:55 +0000135#endif
sewardjc279b3f2005-03-16 18:10:45 +0000136#if 0 /* amd64 -> amd64 */
sewardj07a54cc2005-02-04 21:18:55 +0000137 VexArchAMD64, VexSubArch_NONE,
138 VexArchAMD64, VexSubArch_NONE,
139#endif
sewardjc279b3f2005-03-16 18:10:45 +0000140#if 1 /* x86 -> x86 */
141 VexArchX86, VexSubArchX86_sse1,
142 VexArchX86, VexSubArchX86_sse1,
143#endif
sewardj07a54cc2005-02-04 21:18:55 +0000144
sewardj5bd4d162004-11-10 13:02:48 +0000145 origbuf, (Addr64)orig_addr, chase_into_not_ok,
sewardj72c72812005-01-19 11:49:45 +0000146 &vge,
sewardjabe017e2004-10-29 23:42:36 +0000147 transbuf, N_TRANSBUF, &trans_used,
sewardj9e7448b2004-11-18 13:44:15 +0000148#if 1 /* no instrumentation */
149 NULL, /* instrument1 */
150 NULL, /* instrument2 */
151 False, /* cleanup after instrument */
152#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000153#if 0 /* addrcheck */
154 ac_instrument, /* instrument1 */
155 NULL, /* instrument2 */
156 False, /* cleanup after instrument */
157#endif
sewardj9e7448b2004-11-18 13:44:15 +0000158#if 0 /* memcheck */
sewardjde8a5ae2004-11-06 14:20:54 +0000159 mc_instrument, /* instrument1 */
160 NULL, /* instrument2 */
sewardj69f9e3e2004-12-30 02:05:34 +0000161 True, /* cleanup after instrument */
sewardjde8a5ae2004-11-06 14:20:54 +0000162#endif
sewardjabe017e2004-10-29 23:42:36 +0000163 NULL, /* access checker */
164 TEST_FLAGS
165 );
166
sewardjd887b862005-01-17 18:34:34 +0000167 if (tres != VexTransOK)
sewardj4459baa2004-09-10 20:00:46 +0000168 printf("\ntres = %d\n", (Int)tres);
sewardjd887b862005-01-17 18:34:34 +0000169 assert(tres == VexTransOK);
sewardj72c72812005-01-19 11:49:45 +0000170 assert(vge.n_used == 1);
171 assert((UInt)(vge.len[0]) == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000172
sewardj4459baa2004-09-10 20:00:46 +0000173 sum = 0;
174 for (i = 0; i < trans_used; i++)
175 sum += (UInt)transbuf[i];
sewardjde8c9872005-03-25 13:48:55 +0000176 printf ( " %6.2f ... %u\n",
177 (double)trans_used / (double)vge.len[0], sum );
sewardjced9fe52004-07-07 11:55:36 +0000178 }
179
180 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000181 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000182 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000183
sewardjce605f92004-07-05 14:39:15 +0000184 return 0;
185}
sewardj9b1004e2004-10-30 22:25:40 +0000186
187//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000188//////////////////////////////////////////////////////////////////////
189//////////////////////////////////////////////////////////////////////
190//////////////////////////////////////////////////////////////////////
191//////////////////////////////////////////////////////////////////////
192//////////////////////////////////////////////////////////////////////
193//////////////////////////////////////////////////////////////////////
194//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000195
sewardj1ea1b612005-03-26 13:02:20 +0000196#if 0 /* UNUSED */
197
sewardj9b1004e2004-10-30 22:25:40 +0000198static
sewardjde8a5ae2004-11-06 14:20:54 +0000199__attribute((noreturn))
sewardjde8c9872005-03-25 13:48:55 +0000200void panic ( HChar* s )
sewardj9b1004e2004-10-30 22:25:40 +0000201{
202 printf("\npanic: %s\n", s);
203 failure_exit();
204}
205
206static
sewardj9578a8b2004-11-04 19:44:48 +0000207IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000208{
209/* Use this rather than eg. -1 because it's a UInt. */
210#define INVALID_DATA_SIZE 999999
211
212 Int i;
213 Int sz;
214 IRCallee* helper;
215 IRStmt* st;
216 IRExpr* data;
217 IRExpr* addr;
218 Bool needSz;
219
220 /* Set up BB */
221 IRBB* bb = emptyIRBB();
222 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
223 bb->next = dopyIRExpr(bb_in->next);
224 bb->jumpkind = bb_in->jumpkind;
225
226 /* No loads to consider in ->next. */
sewardj496a58d2005-03-20 18:44:44 +0000227 assert(isIRAtom(bb_in->next));
sewardj9b1004e2004-10-30 22:25:40 +0000228
229 for (i = 0; i < bb_in->stmts_used; i++) {
230 st = bb_in->stmts[i];
231 if (!st) continue;
232
233 switch (st->tag) {
234
235 case Ist_Tmp:
236 data = st->Ist.Tmp.data;
237 if (data->tag == Iex_LDle) {
238 addr = data->Iex.LDle.addr;
239 sz = sizeofIRType(data->Iex.LDle.ty);
240 needSz = False;
241 switch (sz) {
242 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000243 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000244 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000245 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000246 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000247 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000248 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000249 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000250 needSz = True; break;
251 }
252 if (needSz) {
253 addStmtToIRBB(
254 bb,
255 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000256 unsafeIRDirty_0_N( helper->regparms,
257 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000258 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
259 ));
260 } else {
261 addStmtToIRBB(
262 bb,
263 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000264 unsafeIRDirty_0_N( helper->regparms,
265 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000266 mkIRExprVec_1(addr) )
267 ));
268 }
269 }
270 break;
271
272 case Ist_STle:
273 data = st->Ist.STle.data;
274 addr = st->Ist.STle.addr;
sewardj496a58d2005-03-20 18:44:44 +0000275 assert(isIRAtom(data));
276 assert(isIRAtom(addr));
sewardj9b1004e2004-10-30 22:25:40 +0000277 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
278 needSz = False;
279 switch (sz) {
280 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000281 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000282 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000283 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000284 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000285 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000286 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000287 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000288 needSz = True; break;
289 }
290 if (needSz) {
291 addStmtToIRBB(
292 bb,
293 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000294 unsafeIRDirty_0_N( helper->regparms,
295 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000296 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
297 ));
298 } else {
299 addStmtToIRBB(
300 bb,
301 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000302 unsafeIRDirty_0_N( helper->regparms,
303 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000304 mkIRExprVec_1(addr) )
305 ));
306 }
307 break;
308
309 case Ist_Put:
sewardj496a58d2005-03-20 18:44:44 +0000310 assert(isIRAtom(st->Ist.Put.data));
sewardj9b1004e2004-10-30 22:25:40 +0000311 break;
312
313 case Ist_PutI:
sewardj496a58d2005-03-20 18:44:44 +0000314 assert(isIRAtom(st->Ist.PutI.ix));
315 assert(isIRAtom(st->Ist.PutI.data));
sewardj9b1004e2004-10-30 22:25:40 +0000316 break;
317
318 case Ist_Exit:
sewardj496a58d2005-03-20 18:44:44 +0000319 assert(isIRAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000320 break;
321
322 case Ist_Dirty:
323 /* If the call doesn't interact with memory, we ain't
324 interested. */
325 if (st->Ist.Dirty.details->mFx == Ifx_None)
326 break;
327 goto unhandled;
328
329 default:
330 unhandled:
331 printf("\n");
332 ppIRStmt(st);
333 printf("\n");
334 panic("addrcheck: unhandled IRStmt");
335 }
336
337 addStmtToIRBB( bb, dopyIRStmt(st));
338 }
339
340 return bb;
341}
cerionaee45242005-03-17 14:03:36 +0000342#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +0000343
344//////////////////////////////////////////////////////////////////////
345//////////////////////////////////////////////////////////////////////
346//////////////////////////////////////////////////////////////////////
347//////////////////////////////////////////////////////////////////////
348//////////////////////////////////////////////////////////////////////
349//////////////////////////////////////////////////////////////////////
350//////////////////////////////////////////////////////////////////////
351//////////////////////////////////////////////////////////////////////
352
sewardj1ea1b612005-03-26 13:02:20 +0000353#if 0 /* UNUSED */
354
sewardj69f9e3e2004-12-30 02:05:34 +0000355#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000356#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000357#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000358#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000359#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000360
cerionaee45242005-03-17 14:03:36 +0000361
sewardjde8c9872005-03-25 13:48:55 +0000362static void MC_helperc_complain_undef ( void );
363static void MC_helperc_LOADV8 ( void );
364static void MC_helperc_LOADV4 ( void );
365static void MC_helperc_LOADV2 ( void );
366static void MC_helperc_LOADV1 ( void );
sewardj1ea1b612005-03-26 13:02:20 +0000367static void MC_helperc_STOREV8( void );
368static void MC_helperc_STOREV4( void );
369static void MC_helperc_STOREV2( void );
370static void MC_helperc_STOREV1( void );
sewardjde8c9872005-03-25 13:48:55 +0000371static void MC_helperc_value_check0_fail( void );
372static void MC_helperc_value_check1_fail( void );
373static void MC_helperc_value_check4_fail( void );
374
375static void MC_helperc_complain_undef ( void ) { }
376static void MC_helperc_LOADV8 ( void ) { }
377static void MC_helperc_LOADV4 ( void ) { }
378static void MC_helperc_LOADV2 ( void ) { }
379static void MC_helperc_LOADV1 ( void ) { }
sewardj1ea1b612005-03-26 13:02:20 +0000380static void MC_helperc_STOREV8( void ) { }
381static void MC_helperc_STOREV4( void ) { }
382static void MC_helperc_STOREV2( void ) { }
383static void MC_helperc_STOREV1( void ) { }
sewardjde8c9872005-03-25 13:48:55 +0000384static void MC_helperc_value_check0_fail( void ) { }
385static void MC_helperc_value_check1_fail( void ) { }
386static void MC_helperc_value_check4_fail( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000387
388
sewardj3598ef92004-11-11 02:13:30 +0000389/*--------------------------------------------------------------------*/
390/*--- Instrument IR to perform memory checking operations. ---*/
391/*--- mc_translate.c ---*/
392/*--------------------------------------------------------------------*/
393
394/*
395 This file is part of MemCheck, a heavyweight Valgrind tool for
396 detecting memory errors.
397
398 Copyright (C) 2000-2004 Julian Seward
399 jseward@acm.org
400
401 This program is free software; you can redistribute it and/or
402 modify it under the terms of the GNU General Public License as
403 published by the Free Software Foundation; either version 2 of the
404 License, or (at your option) any later version.
405
406 This program is distributed in the hope that it will be useful, but
407 WITHOUT ANY WARRANTY; without even the implied warranty of
408 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
409 General Public License for more details.
410
411 You should have received a copy of the GNU General Public License
412 along with this program; if not, write to the Free Software
413 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
414 02111-1307, USA.
415
416 The GNU General Public License is contained in the file COPYING.
417*/
418
419//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000420
421
422/*------------------------------------------------------------*/
423/*--- Forward decls ---*/
424/*------------------------------------------------------------*/
425
426struct _MCEnv;
427
428static IRType shadowType ( IRType ty );
429static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
430
431
432/*------------------------------------------------------------*/
433/*--- Memcheck running state, and tmp management. ---*/
434/*------------------------------------------------------------*/
435
436/* Carries around state during memcheck instrumentation. */
437typedef
438 struct _MCEnv {
439 /* MODIFIED: the bb being constructed. IRStmts are added. */
440 IRBB* bb;
441
442 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
443 original temps to their current their current shadow temp.
444 Initially all entries are IRTemp_INVALID. Entries are added
445 lazily since many original temps are not used due to
446 optimisation prior to instrumentation. Note that floating
447 point original tmps are shadowed by integer tmps of the same
448 size, and Bit-typed original tmps are shadowed by the type
449 Ity_I8. See comment below. */
450 IRTemp* tmpMap;
451 Int n_originalTmps; /* for range checking */
452
453 /* READONLY: the guest layout. This indicates which parts of
454 the guest state should be regarded as 'always defined'. */
455 VexGuestLayout* layout;
456 /* READONLY: the host word type. Needed for constructing
457 arguments of type 'HWord' to be passed to helper functions.
458 Ity_I32 or Ity_I64 only. */
459 IRType hWordTy;
460 }
461 MCEnv;
462
463/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
464 demand), as they are encountered. This is for two reasons.
465
466 (1) (less important reason): Many original tmps are unused due to
467 initial IR optimisation, and we do not want to spaces in tables
468 tracking them.
469
470 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
471 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000472 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000473 It is necessary to support making multiple assignments to a shadow
474 -- specifically, after testing a shadow for definedness, it needs
475 to be made defined. But IR's SSA property disallows this.
476
477 (2) (more important reason): Therefore, when a shadow needs to get
478 a new value, a new temporary is created, the value is assigned to
479 that, and the tmpMap is updated to reflect the new binding.
480
481 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000482 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000483 there's a read-before-write error in the original tmps. The IR
484 sanity checker should catch all such anomalies, however.
485*/
486
487/* Find the tmp currently shadowing the given original tmp. If none
488 so far exists, allocate one. */
489static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
490{
sewardj69f9e3e2004-12-30 02:05:34 +0000491 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000492 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000493 mce->tmpMap[orig]
494 = newIRTemp(mce->bb->tyenv,
495 shadowType(mce->bb->tyenv->types[orig]));
496 }
497 return mce->tmpMap[orig];
498}
499
500/* Allocate a new shadow for the given original tmp. This means any
501 previous shadow is abandoned. This is needed because it is
502 necessary to give a new value to a shadow once it has been tested
503 for undefinedness, but unfortunately IR's SSA property disallows
504 this. Instead we must abandon the old shadow, allocate a new one
505 and use that instead. */
506static void newShadowTmp ( MCEnv* mce, IRTemp orig )
507{
sewardj69f9e3e2004-12-30 02:05:34 +0000508 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000509 mce->tmpMap[orig]
510 = newIRTemp(mce->bb->tyenv,
511 shadowType(mce->bb->tyenv->types[orig]));
512}
513
514
515/*------------------------------------------------------------*/
516/*--- IRAtoms -- a subset of IRExprs ---*/
517/*------------------------------------------------------------*/
518
519/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj496a58d2005-03-20 18:44:44 +0000520 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardjde8a5ae2004-11-06 14:20:54 +0000521 input, most of this code deals in atoms. Usefully, a value atom
522 always has a V-value which is also an atom: constants are shadowed
523 by constants, and temps are shadowed by the corresponding shadow
524 temporary. */
525
526typedef IRExpr IRAtom;
527
528/* (used for sanity checks only): is this an atom which looks
529 like it's from original code? */
530static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
531{
532 if (a1->tag == Iex_Const)
533 return True;
534 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
535 return True;
536 return False;
537}
538
539/* (used for sanity checks only): is this an atom which looks
540 like it's from shadow code? */
541static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
542{
543 if (a1->tag == Iex_Const)
544 return True;
545 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
546 return True;
547 return False;
548}
549
550/* (used for sanity checks only): check that both args are atoms and
551 are identically-kinded. */
552static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
553{
554 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
555 return True;
556 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
557 return True;
558 return False;
559}
560
561
562/*------------------------------------------------------------*/
563/*--- Type management ---*/
564/*------------------------------------------------------------*/
565
566/* Shadow state is always accessed using integer types. This returns
567 an integer type with the same size (as per sizeofIRType) as the
568 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000569 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000570
571static IRType shadowType ( IRType ty )
572{
573 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000574 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000575 case Ity_I8:
576 case Ity_I16:
577 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000578 case Ity_I64: return ty;
579 case Ity_F32: return Ity_I32;
580 case Ity_F64: return Ity_I64;
581 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000582 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000583 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000584 }
585}
586
587/* Produce a 'defined' value of the given shadow type. Should only be
588 supplied shadow types (Bit/I8/I16/I32/UI64). */
589static IRExpr* definedOfType ( IRType ty ) {
590 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000591 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
592 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
593 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
594 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
595 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
596 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
597 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000598 }
599}
600
601
602/*------------------------------------------------------------*/
603/*--- Constructing IR fragments ---*/
604/*------------------------------------------------------------*/
605
606/* assign value to tmp */
607#define assign(_bb,_tmp,_expr) \
608 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
609
610/* add stmt to a bb */
611#define stmt(_bb,_stmt) \
612 addStmtToIRBB((_bb), (_stmt))
613
614/* build various kinds of expressions */
615#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
616#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
617#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
618#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
619#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
620#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000621#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardjde8a5ae2004-11-06 14:20:54 +0000622#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
623
624/* bind the given expression to a new temporary, and return the
625 temporary. This effectively converts an arbitrary expression into
626 an atom. */
627static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
628 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
629 assign(mce->bb, t, e);
630 return mkexpr(t);
631}
632
633
634/*------------------------------------------------------------*/
635/*--- Constructing definedness primitive ops ---*/
636/*------------------------------------------------------------*/
637
638/* --------- Defined-if-either-defined --------- */
639
640static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000641 tl_assert(isShadowAtom(mce,a1));
642 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000643 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
644}
645
646static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000647 tl_assert(isShadowAtom(mce,a1));
648 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000649 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
650}
651
652static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000653 tl_assert(isShadowAtom(mce,a1));
654 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000655 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
656}
657
sewardj69f9e3e2004-12-30 02:05:34 +0000658static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
659 tl_assert(isShadowAtom(mce,a1));
660 tl_assert(isShadowAtom(mce,a2));
661 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
662}
663
sewardjf0c1c582005-02-07 23:47:38 +0000664static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000665 tl_assert(isShadowAtom(mce,a1));
666 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000667 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000668}
669
sewardjde8a5ae2004-11-06 14:20:54 +0000670/* --------- Undefined-if-either-undefined --------- */
671
672static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000673 tl_assert(isShadowAtom(mce,a1));
674 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000675 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
676}
677
678static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000679 tl_assert(isShadowAtom(mce,a1));
680 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000681 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
682}
683
684static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000685 tl_assert(isShadowAtom(mce,a1));
686 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000687 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
688}
689
690static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000691 tl_assert(isShadowAtom(mce,a1));
692 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000693 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
694}
695
sewardjf0c1c582005-02-07 23:47:38 +0000696static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000697 tl_assert(isShadowAtom(mce,a1));
698 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000699 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000700}
701
702static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000703 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000704 case Ity_I8: return mkUifU8(mce, a1, a2);
705 case Ity_I16: return mkUifU16(mce, a1, a2);
706 case Ity_I32: return mkUifU32(mce, a1, a2);
707 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardjf0c1c582005-02-07 23:47:38 +0000708 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000709 default:
710 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000711 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000712 }
713}
714
715/* --------- The Left-family of operations. --------- */
716
717static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000718 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000719 /* It's safe to duplicate a1 since it's only an atom */
720 return assignNew(mce, Ity_I8,
721 binop(Iop_Or8, a1,
722 assignNew(mce, Ity_I8,
723 /* unop(Iop_Neg8, a1)))); */
724 binop(Iop_Sub8, mkU8(0), a1) )));
725}
726
727static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000728 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000729 /* It's safe to duplicate a1 since it's only an atom */
730 return assignNew(mce, Ity_I16,
731 binop(Iop_Or16, a1,
732 assignNew(mce, Ity_I16,
733 /* unop(Iop_Neg16, a1)))); */
734 binop(Iop_Sub16, mkU16(0), a1) )));
735}
736
737static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000738 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000739 /* It's safe to duplicate a1 since it's only an atom */
740 return assignNew(mce, Ity_I32,
741 binop(Iop_Or32, a1,
742 assignNew(mce, Ity_I32,
743 /* unop(Iop_Neg32, a1)))); */
744 binop(Iop_Sub32, mkU32(0), a1) )));
745}
746
747/* --------- 'Improvement' functions for AND/OR. --------- */
748
749/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
750 defined (0); all other -> undefined (1).
751*/
752static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
753{
sewardj69f9e3e2004-12-30 02:05:34 +0000754 tl_assert(isOriginalAtom(mce, data));
755 tl_assert(isShadowAtom(mce, vbits));
756 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000757 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
758}
759
sewardj3598ef92004-11-11 02:13:30 +0000760static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
761{
sewardj69f9e3e2004-12-30 02:05:34 +0000762 tl_assert(isOriginalAtom(mce, data));
763 tl_assert(isShadowAtom(mce, vbits));
764 tl_assert(sameKindedAtoms(data, vbits));
sewardj3598ef92004-11-11 02:13:30 +0000765 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
766}
767
sewardjde8a5ae2004-11-06 14:20:54 +0000768static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
769{
sewardj69f9e3e2004-12-30 02:05:34 +0000770 tl_assert(isOriginalAtom(mce, data));
771 tl_assert(isShadowAtom(mce, vbits));
772 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000773 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
774}
775
sewardj69f9e3e2004-12-30 02:05:34 +0000776static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
777{
778 tl_assert(isOriginalAtom(mce, data));
779 tl_assert(isShadowAtom(mce, vbits));
780 tl_assert(sameKindedAtoms(data, vbits));
781 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
782}
783
sewardjf0c1c582005-02-07 23:47:38 +0000784static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000785{
786 tl_assert(isOriginalAtom(mce, data));
787 tl_assert(isShadowAtom(mce, vbits));
788 tl_assert(sameKindedAtoms(data, vbits));
sewardjf0c1c582005-02-07 23:47:38 +0000789 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj69f9e3e2004-12-30 02:05:34 +0000790}
791
sewardjde8a5ae2004-11-06 14:20:54 +0000792/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
793 defined (0); all other -> undefined (1).
794*/
795static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
796{
sewardj69f9e3e2004-12-30 02:05:34 +0000797 tl_assert(isOriginalAtom(mce, data));
798 tl_assert(isShadowAtom(mce, vbits));
799 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000800 return assignNew(
801 mce, Ity_I8,
802 binop(Iop_Or8,
803 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
804 vbits) );
805}
806
807static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
808{
sewardj69f9e3e2004-12-30 02:05:34 +0000809 tl_assert(isOriginalAtom(mce, data));
810 tl_assert(isShadowAtom(mce, vbits));
811 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000812 return assignNew(
813 mce, Ity_I16,
814 binop(Iop_Or16,
815 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
816 vbits) );
817}
818
819static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
820{
sewardj69f9e3e2004-12-30 02:05:34 +0000821 tl_assert(isOriginalAtom(mce, data));
822 tl_assert(isShadowAtom(mce, vbits));
823 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000824 return assignNew(
825 mce, Ity_I32,
826 binop(Iop_Or32,
827 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
828 vbits) );
829}
830
sewardj69f9e3e2004-12-30 02:05:34 +0000831static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
832{
833 tl_assert(isOriginalAtom(mce, data));
834 tl_assert(isShadowAtom(mce, vbits));
835 tl_assert(sameKindedAtoms(data, vbits));
836 return assignNew(
837 mce, Ity_I64,
838 binop(Iop_Or64,
839 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
840 vbits) );
841}
842
sewardjf0c1c582005-02-07 23:47:38 +0000843static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000844{
845 tl_assert(isOriginalAtom(mce, data));
846 tl_assert(isShadowAtom(mce, vbits));
847 tl_assert(sameKindedAtoms(data, vbits));
848 return assignNew(
849 mce, Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +0000850 binop(Iop_OrV128,
851 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj69f9e3e2004-12-30 02:05:34 +0000852 vbits) );
853}
854
sewardjde8a5ae2004-11-06 14:20:54 +0000855/* --------- Pessimising casts. --------- */
856
857static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
858{
sewardj8fc93742004-11-22 11:29:33 +0000859 IRType ty;
860 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000861 /* Note, dst_ty is a shadow type, not an original type. */
862 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000863 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000864 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
865 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000866 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000867 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000868 tmp1 = vbits;
869 break;
870 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000871 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000872 break;
873 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000874 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000875 break;
876 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000877 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000878 break;
879 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000880 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000881 break;
882 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000883 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000884 }
sewardj69f9e3e2004-12-30 02:05:34 +0000885 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000886 /* Now widen up to the dst type. */
887 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000888 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000889 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000890 case Ity_I8:
891 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000892 case Ity_I16:
893 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
894 case Ity_I32:
895 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
896 case Ity_I64:
897 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000898 case Ity_V128:
899 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardjf0c1c582005-02-07 23:47:38 +0000900 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000901 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000902 default:
903 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000904 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +0000905 }
906}
907
908
909/*------------------------------------------------------------*/
910/*--- Emit a test and complaint if something is undefined. ---*/
911/*------------------------------------------------------------*/
912
913/* Set the annotations on a dirty helper to indicate that the stack
914 pointer and instruction pointers might be read. This is the
915 behaviour of all 'emit-a-complaint' style functions we might
916 call. */
917
918static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
919 di->nFxState = 2;
920 di->fxState[0].fx = Ifx_Read;
921 di->fxState[0].offset = mce->layout->offset_SP;
922 di->fxState[0].size = mce->layout->sizeof_SP;
923 di->fxState[1].fx = Ifx_Read;
924 di->fxState[1].offset = mce->layout->offset_IP;
925 di->fxState[1].size = mce->layout->sizeof_IP;
926}
927
928
929/* Check the supplied **original** atom for undefinedness, and emit a
930 complaint if so. Once that happens, mark it as defined. This is
931 possible because the atom is either a tmp or literal. If it's a
932 tmp, it will be shadowed by a tmp, and so we can set the shadow to
933 be defined. In fact as mentioned above, we will have to allocate a
934 new tmp to carry the new 'defined' shadow value, and update the
935 original->tmp mapping accordingly; we cannot simply assign a new
936 value to an existing shadow tmp as this breaks SSAness -- resulting
937 in the post-instrumentation sanity checker spluttering in disapproval.
938*/
939static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
940{
sewardj8fc93742004-11-22 11:29:33 +0000941 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +0000942 IRType ty;
943 Int sz;
sewardj8fc93742004-11-22 11:29:33 +0000944 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +0000945 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +0000946
sewardjde8a5ae2004-11-06 14:20:54 +0000947 /* Since the original expression is atomic, there's no duplicated
948 work generated by making multiple V-expressions for it. So we
949 don't really care about the possibility that someone else may
950 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +0000951 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +0000952 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +0000953 tl_assert(isShadowAtom(mce, vatom));
954 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +0000955
sewardj8fc93742004-11-22 11:29:33 +0000956 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +0000957
958 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +0000959 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +0000960
sewardj8fc93742004-11-22 11:29:33 +0000961 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +0000962 /* cond will be 0 if all defined, and 1 if any not defined. */
963
sewardj3598ef92004-11-11 02:13:30 +0000964 switch (sz) {
965 case 0:
966 di = unsafeIRDirty_0_N( 0/*regparms*/,
967 "MC_(helperc_value_check0_fail)",
968 &MC_(helperc_value_check0_fail),
969 mkIRExprVec_0()
970 );
971 break;
972 case 1:
973 di = unsafeIRDirty_0_N( 0/*regparms*/,
974 "MC_(helperc_value_check1_fail)",
975 &MC_(helperc_value_check1_fail),
976 mkIRExprVec_0()
977 );
978 break;
979 case 4:
980 di = unsafeIRDirty_0_N( 0/*regparms*/,
981 "MC_(helperc_value_check4_fail)",
982 &MC_(helperc_value_check4_fail),
983 mkIRExprVec_0()
984 );
985 break;
986 default:
987 di = unsafeIRDirty_0_N( 1/*regparms*/,
988 "MC_(helperc_complain_undef)",
989 &MC_(helperc_complain_undef),
990 mkIRExprVec_1( mkIRExpr_HWord( sz ))
991 );
992 break;
993 }
sewardjde8a5ae2004-11-06 14:20:54 +0000994 di->guard = cond;
995 setHelperAnns( mce, di );
996 stmt( mce->bb, IRStmt_Dirty(di));
997
998 /* Set the shadow tmp to be defined. First, update the
999 orig->shadow tmp mapping to reflect the fact that this shadow is
1000 getting a new value. */
sewardj496a58d2005-03-20 18:44:44 +00001001 tl_assert(isIRAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001002 /* sameKindedAtoms ... */
1003 if (vatom->tag == Iex_Tmp) {
sewardj69f9e3e2004-12-30 02:05:34 +00001004 tl_assert(atom->tag == Iex_Tmp);
sewardjde8a5ae2004-11-06 14:20:54 +00001005 newShadowTmp(mce, atom->Iex.Tmp.tmp);
1006 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
1007 definedOfType(ty));
1008 }
1009}
1010
1011
1012/*------------------------------------------------------------*/
1013/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
1014/*------------------------------------------------------------*/
1015
1016/* Examine the always-defined sections declared in layout to see if
1017 the (offset,size) section is within one. Note, is is an error to
1018 partially fall into such a region: (offset,size) should either be
1019 completely in such a region or completely not-in such a region.
1020*/
1021static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1022{
1023 Int minoffD, maxoffD, i;
1024 Int minoff = offset;
1025 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001026 tl_assert((minoff & ~0xFFFF) == 0);
1027 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001028
1029 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1030 minoffD = mce->layout->alwaysDefd[i].offset;
1031 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001032 tl_assert((minoffD & ~0xFFFF) == 0);
1033 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001034
1035 if (maxoff < minoffD || maxoffD < minoff)
1036 continue; /* no overlap */
1037 if (minoff >= minoffD && maxoff <= maxoffD)
1038 return True; /* completely contained in an always-defd section */
1039
sewardj69f9e3e2004-12-30 02:05:34 +00001040 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001041 }
1042 return False; /* could not find any containing section */
1043}
1044
1045
1046/* Generate into bb suitable actions to shadow this Put. If the state
1047 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001048 supplied V bits to the shadow state. We can pass in either an
1049 original atom or a V-atom, but not both. In the former case the
1050 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001051*/
1052static
sewardj3598ef92004-11-11 02:13:30 +00001053void do_shadow_PUT ( MCEnv* mce, Int offset,
1054 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001055{
sewardj8fc93742004-11-22 11:29:33 +00001056 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001057 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001058 tl_assert(!vatom);
1059 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001060 vatom = expr2vbits( mce, atom );
1061 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001062 tl_assert(vatom);
1063 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001064 }
1065
sewardj8fc93742004-11-22 11:29:33 +00001066 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001067 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001068 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1069 /* later: no ... */
1070 /* emit code to emit a complaint if any of the vbits are 1. */
1071 /* complainIfUndefined(mce, atom); */
1072 } else {
1073 /* Do a plain shadow Put. */
1074 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1075 }
1076}
1077
1078
1079/* Return an expression which contains the V bits corresponding to the
1080 given GETI (passed in in pieces).
1081*/
1082static
1083void do_shadow_PUTI ( MCEnv* mce,
1084 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
1085{
sewardj8fc93742004-11-22 11:29:33 +00001086 IRAtom* vatom;
1087 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001088 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001089
sewardj69f9e3e2004-12-30 02:05:34 +00001090 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001091 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001092 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001093 ty = descr->elemTy;
1094 tyS = shadowType(ty);
1095 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001096 tl_assert(ty != Ity_I1);
1097 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001098 complainIfUndefined(mce,ix);
1099 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1100 /* later: no ... */
1101 /* emit code to emit a complaint if any of the vbits are 1. */
1102 /* complainIfUndefined(mce, atom); */
1103 } else {
1104 /* Do a cloned version of the Put that refers to the shadow
1105 area. */
1106 IRArray* new_descr
1107 = mkIRArray( descr->base + mce->layout->total_sizeB,
1108 tyS, descr->nElems);
1109 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1110 }
1111}
1112
1113
1114/* Return an expression which contains the V bits corresponding to the
1115 given GET (passed in in pieces).
1116*/
1117static
1118IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1119{
1120 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001121 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001122 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1123 /* Always defined, return all zeroes of the relevant type */
1124 return definedOfType(tyS);
1125 } else {
1126 /* return a cloned version of the Get that refers to the shadow
1127 area. */
1128 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1129 }
1130}
1131
1132
1133/* Return an expression which contains the V bits corresponding to the
1134 given GETI (passed in in pieces).
1135*/
1136static
1137IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
1138{
1139 IRType ty = descr->elemTy;
1140 IRType tyS = shadowType(ty);
1141 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001142 tl_assert(ty != Ity_I1);
1143 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001144 complainIfUndefined(mce,ix);
1145 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1146 /* Always defined, return all zeroes of the relevant type */
1147 return definedOfType(tyS);
1148 } else {
1149 /* return a cloned version of the Get that refers to the shadow
1150 area. */
1151 IRArray* new_descr
1152 = mkIRArray( descr->base + mce->layout->total_sizeB,
1153 tyS, descr->nElems);
1154 return IRExpr_GetI( new_descr, ix, bias );
1155 }
1156}
1157
1158
1159/*------------------------------------------------------------*/
1160/*--- Generating approximations for unknown operations, ---*/
1161/*--- using lazy-propagate semantics ---*/
1162/*------------------------------------------------------------*/
1163
1164/* Lazy propagation of undefinedness from two values, resulting in the
1165 specified shadow type.
1166*/
1167static
1168IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1169{
1170 /* force everything via 32-bit intermediaries. */
1171 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001172 tl_assert(isShadowAtom(mce,va1));
1173 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001174 at = mkPCastTo(mce, Ity_I32, va1);
1175 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1176 at = mkPCastTo(mce, finalVty, at);
1177 return at;
1178}
1179
1180
1181/* Do the lazy propagation game from a null-terminated vector of
1182 atoms. This is presumably the arguments to a helper call, so the
1183 IRCallee info is also supplied in order that we can know which
1184 arguments should be ignored (via the .mcx_mask field).
1185*/
1186static
1187IRAtom* mkLazyN ( MCEnv* mce,
1188 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1189{
1190 Int i;
1191 IRAtom* here;
1192 IRAtom* curr = definedOfType(Ity_I32);
1193 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001194 tl_assert(i < 32);
1195 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001196 /* Only take notice of this arg if the callee's mc-exclusion
1197 mask does not say it is to be excluded. */
1198 if (cee->mcx_mask & (1<<i)) {
1199 /* the arg is to be excluded from definedness checking. Do
1200 nothing. */
1201 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1202 } else {
1203 /* calculate the arg's definedness, and pessimistically merge
1204 it in. */
1205 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1206 curr = mkUifU32(mce, here, curr);
1207 }
1208 }
1209 return mkPCastTo(mce, finalVtype, curr );
1210}
1211
1212
1213/*------------------------------------------------------------*/
1214/*--- Generating expensive sequences for exact carry-chain ---*/
1215/*--- propagation in add/sub and related operations. ---*/
1216/*------------------------------------------------------------*/
1217
1218static
1219IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1220 IRAtom* aa, IRAtom* bb )
1221{
sewardj69f9e3e2004-12-30 02:05:34 +00001222 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001223 IRType ty;
1224 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001225
sewardj69f9e3e2004-12-30 02:05:34 +00001226 tl_assert(isShadowAtom(mce,qaa));
1227 tl_assert(isShadowAtom(mce,qbb));
1228 tl_assert(isOriginalAtom(mce,aa));
1229 tl_assert(isOriginalAtom(mce,bb));
1230 tl_assert(sameKindedAtoms(qaa,aa));
1231 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001232
sewardj8fc93742004-11-22 11:29:33 +00001233 ty = Ity_I32;
1234 opAND = Iop_And32;
1235 opOR = Iop_Or32;
1236 opXOR = Iop_Xor32;
1237 opNOT = Iop_Not32;
1238 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001239
1240 // a_min = aa & ~qaa
1241 a_min = assignNew(mce,ty,
1242 binop(opAND, aa,
1243 assignNew(mce,ty, unop(opNOT, qaa))));
1244
1245 // b_min = bb & ~qbb
1246 b_min = assignNew(mce,ty,
1247 binop(opAND, bb,
1248 assignNew(mce,ty, unop(opNOT, qbb))));
1249
1250 // a_max = aa | qaa
1251 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1252
1253 // b_max = bb | qbb
1254 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1255
1256 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1257 return
1258 assignNew(mce,ty,
1259 binop( opOR,
1260 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1261 assignNew(mce,ty,
1262 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1263 assignNew(mce,ty, binop(opADD, a_max, b_max))
1264 )
1265 )
1266 )
1267 );
1268}
1269
1270
1271/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001272/*--- Helpers for dealing with vector primops. ---*/
1273/*------------------------------------------------------------*/
1274
1275/* Vector pessimisation -- pessimise within each lane individually. */
1276
1277static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1278{
1279 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1280}
1281
1282static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1283{
1284 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1285}
1286
1287static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1288{
1289 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1290}
1291
1292static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1293{
1294 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1295}
1296
1297
1298/* Here's a simple scheme capable of handling ops derived from SSE1
1299 code and while only generating ops that can be efficiently
1300 implemented in SSE1. */
1301
1302/* All-lanes versions are straightforward:
1303
sewardjf0c1c582005-02-07 23:47:38 +00001304 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj69f9e3e2004-12-30 02:05:34 +00001305
1306 unary32Fx4(x,y) ==> PCast32x4(x#)
1307
1308 Lowest-lane-only versions are more complex:
1309
sewardjf0c1c582005-02-07 23:47:38 +00001310 binary32F0x4(x,y) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001311 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001312 PCast32(V128to32(UifUV128(x#,y#)))
sewardj69f9e3e2004-12-30 02:05:34 +00001313 )
1314
1315 This is perhaps not so obvious. In particular, it's faster to
sewardjf0c1c582005-02-07 23:47:38 +00001316 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj69f9e3e2004-12-30 02:05:34 +00001317 obvious scheme of taking the bottom 32 bits of each operand
1318 and doing a 32-bit UifU. Basically since UifU is fast and
1319 chopping lanes off vector values is slow.
1320
1321 Finally:
1322
sewardjf0c1c582005-02-07 23:47:38 +00001323 unary32F0x4(x) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001324 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001325 PCast32(V128to32(x#))
sewardj69f9e3e2004-12-30 02:05:34 +00001326 )
1327
1328 Where:
1329
1330 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1331 PCast32x4(v#) = CmpNEZ32x4(v#)
1332*/
1333
1334static
1335IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1336{
1337 IRAtom* at;
1338 tl_assert(isShadowAtom(mce, vatomX));
1339 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001340 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001341 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1342 return at;
1343}
1344
1345static
1346IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1347{
1348 IRAtom* at;
1349 tl_assert(isShadowAtom(mce, vatomX));
1350 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1351 return at;
1352}
1353
1354static
1355IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1356{
1357 IRAtom* at;
1358 tl_assert(isShadowAtom(mce, vatomX));
1359 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001360 at = mkUifUV128(mce, vatomX, vatomY);
1361 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001362 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001363 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001364 return at;
1365}
1366
1367static
1368IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1369{
1370 IRAtom* at;
1371 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001372 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001373 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001374 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001375 return at;
1376}
1377
1378/* --- ... and ... 64Fx2 versions of the same ... --- */
1379
1380static
1381IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1382{
1383 IRAtom* at;
1384 tl_assert(isShadowAtom(mce, vatomX));
1385 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001386 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001387 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1388 return at;
1389}
1390
1391static
1392IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1393{
1394 IRAtom* at;
1395 tl_assert(isShadowAtom(mce, vatomX));
1396 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1397 return at;
1398}
1399
1400static
1401IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1402{
1403 IRAtom* at;
1404 tl_assert(isShadowAtom(mce, vatomX));
1405 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001406 at = mkUifUV128(mce, vatomX, vatomY);
1407 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001408 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001409 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001410 return at;
1411}
1412
1413static
1414IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1415{
1416 IRAtom* at;
1417 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001418 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001419 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001420 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001421 return at;
1422}
1423
1424/* --- --- Vector saturated narrowing --- --- */
1425
1426/* This is quite subtle. What to do is simple:
1427
1428 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1429
1430 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1431
1432 Why this is right is not so simple. Consider a lane in the args,
1433 vatom1 or 2, doesn't matter.
1434
1435 After the PCast, that lane is all 0s (defined) or all
1436 1s(undefined).
1437
1438 Both signed and unsigned saturating narrowing of all 0s produces
1439 all 0s, which is what we want.
1440
1441 The all-1s case is more complex. Unsigned narrowing interprets an
1442 all-1s input as the largest unsigned integer, and so produces all
1443 1s as a result since that is the largest unsigned value at the
1444 smaller width.
1445
1446 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1447 to -1, so we still wind up with all 1s at the smaller width.
1448
1449 So: In short, pessimise the args, then apply the original narrowing
1450 op.
1451*/
1452static
sewardjf0c1c582005-02-07 23:47:38 +00001453IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardj69f9e3e2004-12-30 02:05:34 +00001454 IRAtom* vatom1, IRAtom* vatom2)
1455{
1456 IRAtom *at1, *at2, *at3;
1457 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1458 switch (narrow_op) {
1459 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1460 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1461 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardjf0c1c582005-02-07 23:47:38 +00001462 default: VG_(tool_panic)("vectorNarrowV128");
sewardj69f9e3e2004-12-30 02:05:34 +00001463 }
1464 tl_assert(isShadowAtom(mce,vatom1));
1465 tl_assert(isShadowAtom(mce,vatom2));
1466 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1467 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1468 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1469 return at3;
1470}
1471
1472
1473/* --- --- Vector integer arithmetic --- --- */
1474
1475/* Simple ... UifU the args and per-lane pessimise the results. */
1476static
1477IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1478{
1479 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001480 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001481 at = mkPCast8x16(mce, at);
1482 return at;
1483}
1484
1485static
1486IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1487{
1488 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001489 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001490 at = mkPCast16x8(mce, at);
1491 return at;
1492}
1493
1494static
1495IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1496{
1497 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001498 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001499 at = mkPCast32x4(mce, at);
1500 return at;
1501}
1502
1503static
1504IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1505{
1506 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001507 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001508 at = mkPCast64x2(mce, at);
1509 return at;
1510}
1511
1512
1513/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001514/*--- Generate shadow values from all kinds of IRExprs. ---*/
1515/*------------------------------------------------------------*/
1516
1517static
1518IRAtom* expr2vbits_Binop ( MCEnv* mce,
1519 IROp op,
1520 IRAtom* atom1, IRAtom* atom2 )
1521{
1522 IRType and_or_ty;
1523 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1524 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1525 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1526
1527 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1528 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1529
sewardj69f9e3e2004-12-30 02:05:34 +00001530 tl_assert(isOriginalAtom(mce,atom1));
1531 tl_assert(isOriginalAtom(mce,atom2));
1532 tl_assert(isShadowAtom(mce,vatom1));
1533 tl_assert(isShadowAtom(mce,vatom2));
1534 tl_assert(sameKindedAtoms(atom1,vatom1));
1535 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001536 switch (op) {
1537
sewardjf0c1c582005-02-07 23:47:38 +00001538 /* V128-bit SIMD (SSE2-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001539
1540 case Iop_ShrN16x8:
1541 case Iop_ShrN32x4:
1542 case Iop_ShrN64x2:
1543 case Iop_SarN16x8:
1544 case Iop_SarN32x4:
1545 case Iop_ShlN16x8:
1546 case Iop_ShlN32x4:
1547 case Iop_ShlN64x2:
1548 /* Same scheme as with all other shifts. */
1549 complainIfUndefined(mce, atom2);
1550 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1551
1552 case Iop_QSub8Ux16:
1553 case Iop_QSub8Sx16:
1554 case Iop_Sub8x16:
1555 case Iop_Min8Ux16:
1556 case Iop_Max8Ux16:
1557 case Iop_CmpGT8Sx16:
1558 case Iop_CmpEQ8x16:
1559 case Iop_Avg8Ux16:
1560 case Iop_QAdd8Ux16:
1561 case Iop_QAdd8Sx16:
1562 case Iop_Add8x16:
1563 return binary8Ix16(mce, vatom1, vatom2);
1564
1565 case Iop_QSub16Ux8:
1566 case Iop_QSub16Sx8:
1567 case Iop_Sub16x8:
1568 case Iop_Mul16x8:
1569 case Iop_MulHi16Sx8:
1570 case Iop_MulHi16Ux8:
1571 case Iop_Min16Sx8:
1572 case Iop_Max16Sx8:
1573 case Iop_CmpGT16Sx8:
1574 case Iop_CmpEQ16x8:
1575 case Iop_Avg16Ux8:
1576 case Iop_QAdd16Ux8:
1577 case Iop_QAdd16Sx8:
1578 case Iop_Add16x8:
1579 return binary16Ix8(mce, vatom1, vatom2);
1580
1581 case Iop_Sub32x4:
1582 case Iop_CmpGT32Sx4:
1583 case Iop_CmpEQ32x4:
1584 case Iop_Add32x4:
1585 return binary32Ix4(mce, vatom1, vatom2);
1586
1587 case Iop_Sub64x2:
1588 case Iop_Add64x2:
1589 return binary64Ix2(mce, vatom1, vatom2);
1590
1591 case Iop_QNarrow32Sx4:
1592 case Iop_QNarrow16Sx8:
1593 case Iop_QNarrow16Ux8:
sewardjf0c1c582005-02-07 23:47:38 +00001594 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001595
1596 case Iop_Sub64Fx2:
1597 case Iop_Mul64Fx2:
1598 case Iop_Min64Fx2:
1599 case Iop_Max64Fx2:
1600 case Iop_Div64Fx2:
1601 case Iop_CmpLT64Fx2:
1602 case Iop_CmpLE64Fx2:
1603 case Iop_CmpEQ64Fx2:
1604 case Iop_Add64Fx2:
1605 return binary64Fx2(mce, vatom1, vatom2);
1606
1607 case Iop_Sub64F0x2:
1608 case Iop_Mul64F0x2:
1609 case Iop_Min64F0x2:
1610 case Iop_Max64F0x2:
1611 case Iop_Div64F0x2:
1612 case Iop_CmpLT64F0x2:
1613 case Iop_CmpLE64F0x2:
1614 case Iop_CmpEQ64F0x2:
1615 case Iop_Add64F0x2:
1616 return binary64F0x2(mce, vatom1, vatom2);
1617
sewardjf0c1c582005-02-07 23:47:38 +00001618 /* V128-bit SIMD (SSE1-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001619
1620 case Iop_Sub32Fx4:
1621 case Iop_Mul32Fx4:
1622 case Iop_Min32Fx4:
1623 case Iop_Max32Fx4:
1624 case Iop_Div32Fx4:
1625 case Iop_CmpLT32Fx4:
1626 case Iop_CmpLE32Fx4:
1627 case Iop_CmpEQ32Fx4:
1628 case Iop_Add32Fx4:
1629 return binary32Fx4(mce, vatom1, vatom2);
1630
1631 case Iop_Sub32F0x4:
1632 case Iop_Mul32F0x4:
1633 case Iop_Min32F0x4:
1634 case Iop_Max32F0x4:
1635 case Iop_Div32F0x4:
1636 case Iop_CmpLT32F0x4:
1637 case Iop_CmpLE32F0x4:
1638 case Iop_CmpEQ32F0x4:
1639 case Iop_Add32F0x4:
1640 return binary32F0x4(mce, vatom1, vatom2);
1641
sewardjf0c1c582005-02-07 23:47:38 +00001642 /* V128-bit data-steering */
1643 case Iop_SetV128lo32:
1644 case Iop_SetV128lo64:
1645 case Iop_64HLtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001646 case Iop_InterleaveLO64x2:
1647 case Iop_InterleaveLO32x4:
1648 case Iop_InterleaveLO16x8:
1649 case Iop_InterleaveLO8x16:
1650 case Iop_InterleaveHI64x2:
1651 case Iop_InterleaveHI32x4:
1652 case Iop_InterleaveHI16x8:
1653 case Iop_InterleaveHI8x16:
1654 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1655
1656 /* Scalar floating point */
1657
sewardj3598ef92004-11-11 02:13:30 +00001658 case Iop_RoundF64:
1659 case Iop_F64toI64:
sewardj69f9e3e2004-12-30 02:05:34 +00001660 case Iop_I64toF64:
1661 /* First arg is I32 (rounding mode), second is F64 or I64
1662 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001663 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1664
1665 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1666 /* Takes two F64 args. */
sewardjde8a5ae2004-11-06 14:20:54 +00001667 case Iop_F64toI32:
sewardj69f9e3e2004-12-30 02:05:34 +00001668 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001669 /* First arg is I32 (rounding mode), second is F64 (data). */
1670 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1671
1672 case Iop_F64toI16:
1673 /* First arg is I32 (rounding mode), second is F64 (data). */
1674 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1675
sewardj3598ef92004-11-11 02:13:30 +00001676 case Iop_ScaleF64:
1677 case Iop_Yl2xF64:
1678 case Iop_Yl2xp1F64:
1679 case Iop_PRemF64:
1680 case Iop_AtanF64:
1681 case Iop_AddF64:
1682 case Iop_DivF64:
1683 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001684 case Iop_MulF64:
1685 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1686
sewardj3598ef92004-11-11 02:13:30 +00001687 case Iop_CmpF64:
1688 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1689
sewardjde8a5ae2004-11-06 14:20:54 +00001690 /* non-FP after here */
1691
1692 case Iop_DivModU64to32:
1693 case Iop_DivModS64to32:
1694 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1695
sewardj3598ef92004-11-11 02:13:30 +00001696 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001697 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001698 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001699 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001700
1701 case Iop_MullS32:
1702 case Iop_MullU32: {
1703 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1704 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1705 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1706 }
1707
sewardj3598ef92004-11-11 02:13:30 +00001708 case Iop_MullS16:
1709 case Iop_MullU16: {
1710 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1711 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1712 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1713 }
1714
1715 case Iop_MullS8:
1716 case Iop_MullU8: {
1717 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1718 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1719 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1720 }
1721
sewardjde8a5ae2004-11-06 14:20:54 +00001722 case Iop_Add32:
1723# if 0
1724 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1725# endif
1726 case Iop_Sub32:
1727 case Iop_Mul32:
1728 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1729
sewardj3598ef92004-11-11 02:13:30 +00001730 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001731 case Iop_Add16:
1732 case Iop_Sub16:
1733 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1734
1735 case Iop_Sub8:
1736 case Iop_Add8:
1737 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1738
1739 case Iop_CmpLE32S: case Iop_CmpLE32U:
1740 case Iop_CmpLT32U: case Iop_CmpLT32S:
1741 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001742 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001743
sewardj3598ef92004-11-11 02:13:30 +00001744 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001745 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001746
1747 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001748 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001749
1750 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1751 /* Complain if the shift amount is undefined. Then simply
1752 shift the first arg's V bits by the real shift amount. */
1753 complainIfUndefined(mce, atom2);
1754 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1755
sewardj69f9e3e2004-12-30 02:05:34 +00001756 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001757 /* Same scheme as with 32-bit shifts. */
1758 complainIfUndefined(mce, atom2);
1759 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1760
sewardj3598ef92004-11-11 02:13:30 +00001761 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001762 /* Same scheme as with 32-bit shifts. */
1763 complainIfUndefined(mce, atom2);
1764 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1765
1766 case Iop_Shl64: case Iop_Shr64:
1767 /* Same scheme as with 32-bit shifts. */
1768 complainIfUndefined(mce, atom2);
1769 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1770
sewardjf0c1c582005-02-07 23:47:38 +00001771 case Iop_AndV128:
1772 uifu = mkUifUV128; difd = mkDifDV128;
1773 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001774 case Iop_And64:
1775 uifu = mkUifU64; difd = mkDifD64;
1776 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001777 case Iop_And32:
1778 uifu = mkUifU32; difd = mkDifD32;
1779 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001780 case Iop_And16:
1781 uifu = mkUifU16; difd = mkDifD16;
1782 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001783 case Iop_And8:
1784 uifu = mkUifU8; difd = mkDifD8;
1785 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1786
sewardjf0c1c582005-02-07 23:47:38 +00001787 case Iop_OrV128:
1788 uifu = mkUifUV128; difd = mkDifDV128;
1789 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001790 case Iop_Or64:
1791 uifu = mkUifU64; difd = mkDifD64;
1792 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001793 case Iop_Or32:
1794 uifu = mkUifU32; difd = mkDifD32;
1795 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1796 case Iop_Or16:
1797 uifu = mkUifU16; difd = mkDifD16;
1798 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1799 case Iop_Or8:
1800 uifu = mkUifU8; difd = mkDifD8;
1801 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1802
1803 do_And_Or:
1804 return
1805 assignNew(
1806 mce,
1807 and_or_ty,
1808 difd(mce, uifu(mce, vatom1, vatom2),
1809 difd(mce, improve(mce, atom1, vatom1),
1810 improve(mce, atom2, vatom2) ) ) );
1811
1812 case Iop_Xor8:
1813 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001814 case Iop_Xor16:
1815 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001816 case Iop_Xor32:
1817 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001818 case Iop_Xor64:
1819 return mkUifU64(mce, vatom1, vatom2);
sewardjf0c1c582005-02-07 23:47:38 +00001820 case Iop_XorV128:
1821 return mkUifUV128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001822
1823 default:
1824 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001825 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001826 }
1827}
1828
1829
1830static
1831IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1832{
1833 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001834 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001835 switch (op) {
1836
sewardj69f9e3e2004-12-30 02:05:34 +00001837 case Iop_Sqrt64Fx2:
1838 return unary64Fx2(mce, vatom);
1839
1840 case Iop_Sqrt64F0x2:
1841 return unary64F0x2(mce, vatom);
1842
1843 case Iop_Sqrt32Fx4:
1844 case Iop_RSqrt32Fx4:
1845 case Iop_Recip32Fx4:
1846 return unary32Fx4(mce, vatom);
1847
1848 case Iop_Sqrt32F0x4:
1849 case Iop_RSqrt32F0x4:
1850 case Iop_Recip32F0x4:
1851 return unary32F0x4(mce, vatom);
1852
sewardjf0c1c582005-02-07 23:47:38 +00001853 case Iop_32UtoV128:
1854 case Iop_64UtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001855 return assignNew(mce, Ity_V128, unop(op, vatom));
1856
sewardjde8a5ae2004-11-06 14:20:54 +00001857 case Iop_F32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001858 case Iop_I32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001859 case Iop_NegF64:
1860 case Iop_SinF64:
1861 case Iop_CosF64:
1862 case Iop_TanF64:
1863 case Iop_SqrtF64:
1864 case Iop_AbsF64:
1865 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001866 return mkPCastTo(mce, Ity_I64, vatom);
1867
sewardj3598ef92004-11-11 02:13:30 +00001868 case Iop_Clz32:
1869 case Iop_Ctz32:
1870 return mkPCastTo(mce, Ity_I32, vatom);
1871
1872 case Iop_32Sto64:
1873 case Iop_32Uto64:
sewardjf0c1c582005-02-07 23:47:38 +00001874 case Iop_V128to64:
1875 case Iop_V128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001876 return assignNew(mce, Ity_I64, unop(op, vatom));
1877
sewardjde8a5ae2004-11-06 14:20:54 +00001878 case Iop_64to32:
1879 case Iop_64HIto32:
1880 case Iop_1Uto32:
1881 case Iop_8Uto32:
1882 case Iop_16Uto32:
1883 case Iop_16Sto32:
1884 case Iop_8Sto32:
1885 return assignNew(mce, Ity_I32, unop(op, vatom));
1886
1887 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001888 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001889 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001890 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001891 return assignNew(mce, Ity_I16, unop(op, vatom));
1892
1893 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001894 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001895 case Iop_32to8:
1896 return assignNew(mce, Ity_I8, unop(op, vatom));
1897
1898 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001899 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001900
sewardj3598ef92004-11-11 02:13:30 +00001901 case Iop_ReinterpF64asI64:
1902 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001903 case Iop_ReinterpI32asF32:
sewardjf0c1c582005-02-07 23:47:38 +00001904 case Iop_NotV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001905 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00001906 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001907 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001908 case Iop_Not8:
1909 case Iop_Not1:
1910 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001911
sewardjde8a5ae2004-11-06 14:20:54 +00001912 default:
1913 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001914 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00001915 }
1916}
1917
1918
sewardj69f9e3e2004-12-30 02:05:34 +00001919/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00001920static
sewardj69f9e3e2004-12-30 02:05:34 +00001921IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001922{
1923 void* helper;
sewardjde8c9872005-03-25 13:48:55 +00001924 HChar* hname;
sewardjde8a5ae2004-11-06 14:20:54 +00001925 IRDirty* di;
1926 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00001927 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001928
sewardj69f9e3e2004-12-30 02:05:34 +00001929 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00001930
1931 /* First, emit a definedness test for the address. This also sets
1932 the address (shadow) to 'defined' following the test. */
1933 complainIfUndefined( mce, addr );
1934
1935 /* Now cook up a call to the relevant helper function, to read the
1936 data V bits from shadow memory. */
1937 ty = shadowType(ty);
1938 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001939 case Ity_I64: helper = &MC_(helperc_LOADV8);
1940 hname = "MC_(helperc_LOADV8)";
1941 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001942 case Ity_I32: helper = &MC_(helperc_LOADV4);
1943 hname = "MC_(helperc_LOADV4)";
1944 break;
1945 case Ity_I16: helper = &MC_(helperc_LOADV2);
1946 hname = "MC_(helperc_LOADV2)";
1947 break;
1948 case Ity_I8: helper = &MC_(helperc_LOADV1);
1949 hname = "MC_(helperc_LOADV1)";
1950 break;
1951 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001952 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00001953 }
1954
sewardj3598ef92004-11-11 02:13:30 +00001955 /* Generate the actual address into addrAct. */
1956 if (bias == 0) {
1957 addrAct = addr;
1958 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001959 IROp mkAdd;
1960 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00001961 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00001962 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
1963 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1964 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00001965 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1966 }
1967
sewardjde8a5ae2004-11-06 14:20:54 +00001968 /* We need to have a place to park the V bits we're just about to
1969 read. */
1970 datavbits = newIRTemp(mce->bb->tyenv, ty);
1971 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00001972 1/*regparms*/, hname, helper,
1973 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00001974 setHelperAnns( mce, di );
1975 stmt( mce->bb, IRStmt_Dirty(di) );
1976
1977 return mkexpr(datavbits);
1978}
1979
1980
1981static
sewardj69f9e3e2004-12-30 02:05:34 +00001982IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
1983{
1984 IRAtom *v64hi, *v64lo;
1985 switch (shadowType(ty)) {
1986 case Ity_I8:
1987 case Ity_I16:
1988 case Ity_I32:
1989 case Ity_I64:
1990 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
1991 case Ity_V128:
1992 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
1993 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
1994 return assignNew( mce,
1995 Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +00001996 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj69f9e3e2004-12-30 02:05:34 +00001997 default:
1998 VG_(tool_panic)("expr2vbits_LDle");
1999 }
2000}
2001
2002
2003static
sewardjde8a5ae2004-11-06 14:20:54 +00002004IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00002005 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00002006{
2007 IRAtom *vbitsC, *vbits0, *vbitsX;
2008 IRType ty;
2009 /* Given Mux0X(cond,expr0,exprX), generate
2010 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2011 That is, steer the V bits like the originals, but trash the
2012 result if the steering value is undefined. This gives
2013 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00002014 tl_assert(isOriginalAtom(mce, cond));
2015 tl_assert(isOriginalAtom(mce, expr0));
2016 tl_assert(isOriginalAtom(mce, exprX));
sewardjde8a5ae2004-11-06 14:20:54 +00002017
2018 vbitsC = expr2vbits(mce, cond);
2019 vbits0 = expr2vbits(mce, expr0);
2020 vbitsX = expr2vbits(mce, exprX);
2021 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2022
2023 return
2024 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2025 mkPCastTo(mce, ty, vbitsC) );
2026}
2027
2028/* --------- This is the main expression-handling function. --------- */
2029
2030static
2031IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2032{
2033 switch (e->tag) {
2034
2035 case Iex_Get:
2036 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2037
2038 case Iex_GetI:
2039 return shadow_GETI( mce, e->Iex.GetI.descr,
2040 e->Iex.GetI.ix, e->Iex.GetI.bias );
2041
2042 case Iex_Tmp:
2043 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
2044
2045 case Iex_Const:
2046 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2047
2048 case Iex_Binop:
2049 return expr2vbits_Binop(
2050 mce,
2051 e->Iex.Binop.op,
2052 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2053 );
2054
2055 case Iex_Unop:
2056 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2057
2058 case Iex_LDle:
sewardj3598ef92004-11-11 02:13:30 +00002059 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
2060 e->Iex.LDle.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002061
2062 case Iex_CCall:
2063 return mkLazyN( mce, e->Iex.CCall.args,
2064 e->Iex.CCall.retty,
2065 e->Iex.CCall.cee );
2066
2067 case Iex_Mux0X:
2068 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2069 e->Iex.Mux0X.exprX);
2070
2071 default:
2072 VG_(printf)("\n");
2073 ppIRExpr(e);
2074 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002075 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002076 }
2077}
2078
2079/*------------------------------------------------------------*/
2080/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2081/*------------------------------------------------------------*/
2082
2083/* Widen a value to the host word size. */
2084
2085static
2086IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2087{
sewardj69f9e3e2004-12-30 02:05:34 +00002088 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002089
sewardj8fc93742004-11-22 11:29:33 +00002090 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002091 tl_assert(isShadowAtom(mce,vatom));
2092
2093 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2094 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002095
sewardjde8a5ae2004-11-06 14:20:54 +00002096 if (tyH == Ity_I32) {
2097 switch (ty) {
2098 case Ity_I32: return vatom;
2099 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2100 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2101 default: goto unhandled;
2102 }
2103 } else {
2104 goto unhandled;
2105 }
2106 unhandled:
2107 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002108 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002109}
2110
2111
sewardj3598ef92004-11-11 02:13:30 +00002112/* Generate a shadow store. addr is always the original address atom.
2113 You can pass in either originals or V-bits for the data atom, but
2114 obviously not both. */
2115
sewardjde8a5ae2004-11-06 14:20:54 +00002116static
sewardj3598ef92004-11-11 02:13:30 +00002117void do_shadow_STle ( MCEnv* mce,
2118 IRAtom* addr, UInt bias,
2119 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002120{
sewardj69f9e3e2004-12-30 02:05:34 +00002121 IROp mkAdd;
2122 IRType ty, tyAddr;
2123 IRDirty *di, *diLo64, *diHi64;
2124 IRAtom *addrAct, *addrLo64, *addrHi64;
2125 IRAtom *vdataLo64, *vdataHi64;
2126 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002127 void* helper = NULL;
2128 Char* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002129
2130 tyAddr = mce->hWordTy;
2131 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2132 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2133
2134 di = diLo64 = diHi64 = NULL;
2135 eBias = eBias0 = eBias8 = NULL;
2136 addrAct = addrLo64 = addrHi64 = NULL;
2137 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002138
sewardj3598ef92004-11-11 02:13:30 +00002139 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002140 tl_assert(!vdata);
2141 tl_assert(isOriginalAtom(mce, data));
2142 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002143 vdata = expr2vbits( mce, data );
2144 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002145 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002146 }
sewardjde8a5ae2004-11-06 14:20:54 +00002147
sewardj69f9e3e2004-12-30 02:05:34 +00002148 tl_assert(isOriginalAtom(mce,addr));
2149 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002150
2151 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002152
2153 /* First, emit a definedness test for the address. This also sets
2154 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002155 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002156
sewardj69f9e3e2004-12-30 02:05:34 +00002157 /* Now decide which helper function to call to write the data V
2158 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002159 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002160 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002161 case Ity_I64: helper = &MC_(helperc_STOREV8);
2162 hname = "MC_(helperc_STOREV8)";
2163 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002164 case Ity_I32: helper = &MC_(helperc_STOREV4);
2165 hname = "MC_(helperc_STOREV4)";
2166 break;
2167 case Ity_I16: helper = &MC_(helperc_STOREV2);
2168 hname = "MC_(helperc_STOREV2)";
2169 break;
2170 case Ity_I8: helper = &MC_(helperc_STOREV1);
2171 hname = "MC_(helperc_STOREV1)";
2172 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002173 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002174 }
2175
sewardj69f9e3e2004-12-30 02:05:34 +00002176 if (ty == Ity_V128) {
2177
sewardjf0c1c582005-02-07 23:47:38 +00002178 /* V128-bit case */
sewardj69f9e3e2004-12-30 02:05:34 +00002179 /* See comment in next clause re 64-bit regparms */
2180 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2181 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
sewardjf0c1c582005-02-07 23:47:38 +00002182 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002183 diLo64 = unsafeIRDirty_0_N(
2184 1/*regparms*/, hname, helper,
2185 mkIRExprVec_2( addrLo64, vdataLo64 ));
2186
2187 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2188 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
sewardjf0c1c582005-02-07 23:47:38 +00002189 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002190 diHi64 = unsafeIRDirty_0_N(
2191 1/*regparms*/, hname, helper,
2192 mkIRExprVec_2( addrHi64, vdataHi64 ));
2193
2194 setHelperAnns( mce, diLo64 );
2195 setHelperAnns( mce, diHi64 );
2196 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2197 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2198
sewardj3598ef92004-11-11 02:13:30 +00002199 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002200
2201 /* 8/16/32/64-bit cases */
2202 /* Generate the actual address into addrAct. */
2203 if (bias == 0) {
2204 addrAct = addr;
2205 } else {
2206 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2207 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2208 }
2209
2210 if (ty == Ity_I64) {
2211 /* We can't do this with regparm 2 on 32-bit platforms, since
2212 the back ends aren't clever enough to handle 64-bit
2213 regparm args. Therefore be different. */
2214 di = unsafeIRDirty_0_N(
2215 1/*regparms*/, hname, helper,
2216 mkIRExprVec_2( addrAct, vdata ));
2217 } else {
2218 di = unsafeIRDirty_0_N(
2219 2/*regparms*/, hname, helper,
2220 mkIRExprVec_2( addrAct,
2221 zwidenToHostWord( mce, vdata )));
2222 }
2223 setHelperAnns( mce, di );
2224 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002225 }
2226
sewardjde8a5ae2004-11-06 14:20:54 +00002227}
2228
2229
sewardj3598ef92004-11-11 02:13:30 +00002230/* Do lazy pessimistic propagation through a dirty helper call, by
2231 looking at the annotations on it. This is the most complex part of
2232 Memcheck. */
2233
2234static IRType szToITy ( Int n )
2235{
2236 switch (n) {
2237 case 1: return Ity_I8;
2238 case 2: return Ity_I16;
2239 case 4: return Ity_I32;
2240 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002241 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002242 }
2243}
2244
2245static
2246void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2247{
sewardj69f9e3e2004-12-30 02:05:34 +00002248 Int i, n, offset, toDo, gSz, gOff;
2249 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002250 IRType tyAddr, tySrc, tyDst;
2251 IRTemp dst;
2252
2253 /* First check the guard. */
2254 complainIfUndefined(mce, d->guard);
2255
2256 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002257 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002258
2259 /* Inputs: unmasked args */
2260 for (i = 0; d->args[i]; i++) {
2261 if (d->cee->mcx_mask & (1<<i)) {
2262 /* ignore this arg */
2263 } else {
2264 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2265 curr = mkUifU32(mce, here, curr);
2266 }
2267 }
2268
2269 /* Inputs: guest state that we read. */
2270 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002271 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002272 if (d->fxState[i].fx == Ifx_Write)
2273 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002274
2275 /* Ignore any sections marked as 'always defined'. */
2276 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2277 if (0)
2278 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2279 d->fxState[i].offset, d->fxState[i].size );
2280 continue;
2281 }
2282
sewardj3598ef92004-11-11 02:13:30 +00002283 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002284 consider it. If larger than 8 bytes, deal with it in 8-byte
2285 chunks. */
2286 gSz = d->fxState[i].size;
2287 gOff = d->fxState[i].offset;
2288 tl_assert(gSz > 0);
2289 while (True) {
2290 if (gSz == 0) break;
2291 n = gSz <= 8 ? gSz : 8;
2292 /* update 'curr' with UifU of the state slice
2293 gOff .. gOff+n-1 */
2294 tySrc = szToITy( n );
2295 src = assignNew( mce, tySrc,
2296 shadow_GET(mce, gOff, tySrc ) );
2297 here = mkPCastTo( mce, Ity_I32, src );
2298 curr = mkUifU32(mce, here, curr);
2299 gSz -= n;
2300 gOff += n;
2301 }
2302
sewardj3598ef92004-11-11 02:13:30 +00002303 }
2304
2305 /* Inputs: memory. First set up some info needed regardless of
2306 whether we're doing reads or writes. */
2307 tyAddr = Ity_INVALID;
2308
2309 if (d->mFx != Ifx_None) {
2310 /* Because we may do multiple shadow loads/stores from the same
2311 base address, it's best to do a single test of its
2312 definedness right now. Post-instrumentation optimisation
2313 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002314 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002315 complainIfUndefined(mce, d->mAddr);
2316
2317 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002318 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2319 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002320 }
2321
2322 /* Deal with memory inputs (reads or modifies) */
2323 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2324 offset = 0;
2325 toDo = d->mSize;
2326 /* chew off 32-bit chunks */
2327 while (toDo >= 4) {
2328 here = mkPCastTo(
2329 mce, Ity_I32,
2330 expr2vbits_LDle ( mce, Ity_I32,
2331 d->mAddr, d->mSize - toDo )
2332 );
2333 curr = mkUifU32(mce, here, curr);
2334 toDo -= 4;
2335 }
2336 /* chew off 16-bit chunks */
2337 while (toDo >= 2) {
2338 here = mkPCastTo(
2339 mce, Ity_I32,
2340 expr2vbits_LDle ( mce, Ity_I16,
2341 d->mAddr, d->mSize - toDo )
2342 );
2343 curr = mkUifU32(mce, here, curr);
2344 toDo -= 2;
2345 }
sewardj69f9e3e2004-12-30 02:05:34 +00002346 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002347 }
2348
2349 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2350 all the inputs to the helper. Now we need to re-distribute the
2351 results to all destinations. */
2352
2353 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002354 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002355 dst = findShadowTmp(mce, d->tmp);
2356 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2357 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2358 }
2359
2360 /* Outputs: guest state that we write or modify. */
2361 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002362 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002363 if (d->fxState[i].fx == Ifx_Read)
2364 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002365 /* Ignore any sections marked as 'always defined'. */
2366 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2367 continue;
2368 /* This state element is written or modified. So we need to
2369 consider it. If larger than 8 bytes, deal with it in 8-byte
2370 chunks. */
2371 gSz = d->fxState[i].size;
2372 gOff = d->fxState[i].offset;
2373 tl_assert(gSz > 0);
2374 while (True) {
2375 if (gSz == 0) break;
2376 n = gSz <= 8 ? gSz : 8;
2377 /* Write suitably-casted 'curr' to the state slice
2378 gOff .. gOff+n-1 */
2379 tyDst = szToITy( n );
2380 do_shadow_PUT( mce, gOff,
2381 NULL, /* original atom */
2382 mkPCastTo( mce, tyDst, curr ) );
2383 gSz -= n;
2384 gOff += n;
2385 }
sewardj3598ef92004-11-11 02:13:30 +00002386 }
2387
2388 /* Outputs: memory that we write or modify. */
2389 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2390 offset = 0;
2391 toDo = d->mSize;
2392 /* chew off 32-bit chunks */
2393 while (toDo >= 4) {
2394 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2395 NULL, /* original data */
2396 mkPCastTo( mce, Ity_I32, curr ) );
2397 toDo -= 4;
2398 }
2399 /* chew off 16-bit chunks */
2400 while (toDo >= 2) {
2401 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2402 NULL, /* original data */
2403 mkPCastTo( mce, Ity_I16, curr ) );
2404 toDo -= 2;
2405 }
sewardj69f9e3e2004-12-30 02:05:34 +00002406 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002407 }
2408
2409}
2410
2411
sewardjde8a5ae2004-11-06 14:20:54 +00002412/*------------------------------------------------------------*/
2413/*--- Memcheck main ---*/
2414/*------------------------------------------------------------*/
2415
sewardj3598ef92004-11-11 02:13:30 +00002416static Bool isBogusAtom ( IRAtom* at )
2417{
2418 ULong n = 0;
2419 IRConst* con;
sewardj496a58d2005-03-20 18:44:44 +00002420 tl_assert(isIRAtom(at));
sewardj3598ef92004-11-11 02:13:30 +00002421 if (at->tag == Iex_Tmp)
2422 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002423 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002424 con = at->Iex.Const.con;
2425 switch (con->tag) {
2426 case Ico_U8: n = (ULong)con->Ico.U8; break;
2427 case Ico_U16: n = (ULong)con->Ico.U16; break;
2428 case Ico_U32: n = (ULong)con->Ico.U32; break;
2429 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002430 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002431 }
2432 /* VG_(printf)("%llx\n", n); */
2433 return (n == 0xFEFEFEFF
2434 || n == 0x80808080
2435 || n == 0x1010101
2436 || n == 1010100);
2437}
2438
2439static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2440{
2441 Int i;
2442 IRExpr* e;
2443 switch (st->tag) {
2444 case Ist_Tmp:
2445 e = st->Ist.Tmp.data;
2446 switch (e->tag) {
2447 case Iex_Get:
2448 case Iex_Tmp:
2449 return False;
2450 case Iex_Unop:
2451 return isBogusAtom(e->Iex.Unop.arg);
2452 case Iex_Binop:
2453 return isBogusAtom(e->Iex.Binop.arg1)
2454 || isBogusAtom(e->Iex.Binop.arg2);
2455 case Iex_Mux0X:
2456 return isBogusAtom(e->Iex.Mux0X.cond)
2457 || isBogusAtom(e->Iex.Mux0X.expr0)
2458 || isBogusAtom(e->Iex.Mux0X.exprX);
2459 case Iex_LDle:
2460 return isBogusAtom(e->Iex.LDle.addr);
2461 case Iex_CCall:
2462 for (i = 0; e->Iex.CCall.args[i]; i++)
2463 if (isBogusAtom(e->Iex.CCall.args[i]))
2464 return True;
2465 return False;
2466 default:
2467 goto unhandled;
2468 }
2469 case Ist_Put:
2470 return isBogusAtom(st->Ist.Put.data);
2471 case Ist_STle:
2472 return isBogusAtom(st->Ist.STle.addr)
2473 || isBogusAtom(st->Ist.STle.data);
2474 case Ist_Exit:
sewardj1ea1b612005-03-26 13:02:20 +00002475 return isBogusAtom(st->Ist.Exit.guard);
sewardj3598ef92004-11-11 02:13:30 +00002476 default:
2477 unhandled:
2478 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002479 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002480 }
2481}
sewardj3598ef92004-11-11 02:13:30 +00002482
sewardj1ea1b612005-03-26 13:02:20 +00002483IRBB* mc_instrument ( IRBB* bb_in, VexGuestLayout* layout,
2484 IRType gWordTy, IRType hWordTy )
sewardjde8a5ae2004-11-06 14:20:54 +00002485{
sewardj3598ef92004-11-11 02:13:30 +00002486 Bool verboze = False; //True;
2487
2488 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002489
2490 Int i, j, first_stmt;
2491 IRStmt* st;
2492 MCEnv mce;
2493
2494 /* Set up BB */
2495 IRBB* bb = emptyIRBB();
2496 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
2497 bb->next = dopyIRExpr(bb_in->next);
2498 bb->jumpkind = bb_in->jumpkind;
2499
2500 /* Set up the running environment. Only .bb is modified as we go
2501 along. */
2502 mce.bb = bb;
2503 mce.layout = layout;
2504 mce.n_originalTmps = bb->tyenv->types_used;
2505 mce.hWordTy = hWordTy;
2506 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2507 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002508 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002509
2510 /* Iterate over the stmts. */
2511
2512 for (i = 0; i < bb_in->stmts_used; i++) {
2513 st = bb_in->stmts[i];
2514 if (!st) continue;
2515
sewardj69f9e3e2004-12-30 02:05:34 +00002516 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002517
2518 /*
2519 if (!hasBogusLiterals) {
2520 hasBogusLiterals = checkForBogusLiterals(st);
2521 if (hasBogusLiterals) {
2522 VG_(printf)("bogus: ");
2523 ppIRStmt(st);
2524 VG_(printf)("\n");
2525 }
2526 }
2527 */
sewardjde8a5ae2004-11-06 14:20:54 +00002528 first_stmt = bb->stmts_used;
2529
2530 if (verboze) {
2531 ppIRStmt(st);
2532 VG_(printf)("\n\n");
2533 }
2534
2535 switch (st->tag) {
2536
2537 case Ist_Tmp:
2538 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
2539 expr2vbits( &mce, st->Ist.Tmp.data) );
2540 break;
2541
2542 case Ist_Put:
2543 do_shadow_PUT( &mce,
2544 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002545 st->Ist.Put.data,
2546 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002547 break;
2548
2549 case Ist_PutI:
2550 do_shadow_PUTI( &mce,
2551 st->Ist.PutI.descr,
2552 st->Ist.PutI.ix,
2553 st->Ist.PutI.bias,
2554 st->Ist.PutI.data );
2555 break;
2556
2557 case Ist_STle:
sewardj3598ef92004-11-11 02:13:30 +00002558 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
2559 st->Ist.STle.data,
2560 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002561 break;
2562
2563 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002564 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002565 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002566 break;
2567
2568 case Ist_Dirty:
2569 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002570 break;
2571
sewardj1ea1b612005-03-26 13:02:20 +00002572 case Ist_IMark:
2573 case Ist_NoOp:
2574 break;
2575
sewardjde8a5ae2004-11-06 14:20:54 +00002576 default:
2577 VG_(printf)("\n");
2578 ppIRStmt(st);
2579 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002580 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002581
2582 } /* switch (st->tag) */
2583
2584 if (verboze) {
2585 for (j = first_stmt; j < bb->stmts_used; j++) {
2586 VG_(printf)(" ");
2587 ppIRStmt(bb->stmts[j]);
2588 VG_(printf)("\n");
2589 }
2590 VG_(printf)("\n");
2591 }
2592
2593 addStmtToIRBB(bb, st);
2594
2595 }
2596
2597 /* Now we need to complain if the jump target is undefined. */
2598 first_stmt = bb->stmts_used;
2599
2600 if (verboze) {
2601 VG_(printf)("bb->next = ");
2602 ppIRExpr(bb->next);
2603 VG_(printf)("\n\n");
2604 }
2605
2606 complainIfUndefined( &mce, bb->next );
2607
2608 if (verboze) {
2609 for (j = first_stmt; j < bb->stmts_used; j++) {
2610 VG_(printf)(" ");
2611 ppIRStmt(bb->stmts[j]);
2612 VG_(printf)("\n");
2613 }
2614 VG_(printf)("\n");
2615 }
2616
2617 return bb;
2618}
cerionaee45242005-03-17 14:03:36 +00002619#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002620
2621/*--------------------------------------------------------------------*/
2622/*--- end mc_translate.c ---*/
2623/*--------------------------------------------------------------------*/