blob: c40a7f32b4ee159edba16b843a0a6faa31246159 [file] [log] [blame]
sewardjc97096c2004-06-30 09:28:04 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
4/*--- This file (test_main.c) is ---*/
sewardjdbcfae72005-08-02 11:14:04 +00005/*--- Copyright (C) 2005 OpenWorks LLP. All rights reserved. ---*/
sewardjc97096c2004-06-30 09:28:04 +00006/*--- ---*/
7/*---------------------------------------------------------------*/
8
9#include <stdio.h>
10#include <stdlib.h>
sewardjced9fe52004-07-07 11:55:36 +000011#include <assert.h>
sewardj9b1004e2004-10-30 22:25:40 +000012#include <string.h>
sewardjc97096c2004-06-30 09:28:04 +000013
sewardjced9fe52004-07-07 11:55:36 +000014#include "libvex_basictypes.h"
15#include "libvex.h"
sewardjc97096c2004-06-30 09:28:04 +000016
sewardjabe017e2004-10-29 23:42:36 +000017#include "test_main.h"
18
19
sewardjc97096c2004-06-30 09:28:04 +000020/*---------------------------------------------------------------*/
21/*--- Test ---*/
22/*---------------------------------------------------------------*/
23
sewardjce605f92004-07-05 14:39:15 +000024
sewardj2b515872004-07-05 20:50:45 +000025__attribute__ ((noreturn))
sewardj41f43bc2004-07-08 14:23:22 +000026static
sewardjce605f92004-07-05 14:39:15 +000027void failure_exit ( void )
28{
29 fprintf(stdout, "VEX did failure_exit. Bye.\n");
30 exit(1);
31}
32
sewardj41f43bc2004-07-08 14:23:22 +000033static
sewardj58277842005-02-07 03:11:17 +000034void log_bytes ( HChar* bytes, Int nbytes )
sewardjce605f92004-07-05 14:39:15 +000035{
36 fwrite ( bytes, 1, nbytes, stdout );
37}
38
sewardjced9fe52004-07-07 11:55:36 +000039#define N_LINEBUF 10000
sewardjde8c9872005-03-25 13:48:55 +000040static HChar linebuf[N_LINEBUF];
sewardjced9fe52004-07-07 11:55:36 +000041
cerion094d1392005-06-20 13:45:57 +000042#define N_ORIGBUF 10000
sewardj4459baa2004-09-10 20:00:46 +000043#define N_TRANSBUF 5000
sewardjced9fe52004-07-07 11:55:36 +000044
sewardj4459baa2004-09-10 20:00:46 +000045static UChar origbuf[N_ORIGBUF];
46static UChar transbuf[N_TRANSBUF];
sewardjced9fe52004-07-07 11:55:36 +000047
sewardj1f40a0a2004-07-21 12:28:07 +000048static Bool verbose = True;
sewardjced9fe52004-07-07 11:55:36 +000049
sewardj9b1004e2004-10-30 22:25:40 +000050/* Forwards */
cerionaee45242005-03-17 14:03:36 +000051#if 0 /* UNUSED */
sewardj9578a8b2004-11-04 19:44:48 +000052static IRBB* ac_instrument ( IRBB*, VexGuestLayout*, IRType );
sewardj1ea1b612005-03-26 13:02:20 +000053static IRBB* mc_instrument ( IRBB*, VexGuestLayout*, IRType, IRType );
cerionaee45242005-03-17 14:03:36 +000054#endif
sewardj9b1004e2004-10-30 22:25:40 +000055
sewardj5bd4d162004-11-10 13:02:48 +000056static Bool chase_into_not_ok ( Addr64 dst ) { return False; }
sewardj9b1004e2004-10-30 22:25:40 +000057
sewardjced9fe52004-07-07 11:55:36 +000058int main ( int argc, char** argv )
sewardjce605f92004-07-05 14:39:15 +000059{
sewardjced9fe52004-07-07 11:55:36 +000060 FILE* f;
61 Int i;
sewardj4459baa2004-09-10 20:00:46 +000062 UInt u, sum;
sewardjced9fe52004-07-07 11:55:36 +000063 Addr32 orig_addr;
sewardjabe017e2004-10-29 23:42:36 +000064 Int bb_number, n_bbs_done = 0;
sewardj72c72812005-01-19 11:49:45 +000065 Int orig_nbytes, trans_used;
sewardjd887b862005-01-17 18:34:34 +000066 VexTranslateResult tres;
sewardjb5bf2e02004-10-25 13:06:17 +000067 VexControl vcon;
sewardj72c72812005-01-19 11:49:45 +000068 VexGuestExtents vge;
sewardj9e6491a2005-07-02 19:24:10 +000069 VexArchInfo vai_x86, vai_amd64, vai_ppc32;
sewardj17c7f952005-12-15 14:02:34 +000070 VexTranslateArgs vta;
sewardjced9fe52004-07-07 11:55:36 +000071
72 if (argc != 2) {
73 fprintf(stderr, "usage: vex file.org\n");
74 exit(1);
75 }
76 f = fopen(argv[1], "r");
77 if (!f) {
78 fprintf(stderr, "can't open `%s'\n", argv[1]);
79 exit(1);
80 }
81
sewardjb5bf2e02004-10-25 13:06:17 +000082 /* Run with default params. However, we can't allow bb chasing
83 since that causes the front end to get segfaults when it tries
sewardj5bd4d162004-11-10 13:02:48 +000084 to read code outside the initial BB we hand it. So when calling
85 LibVEX_Translate, send in a chase-into predicate that always
86 returns False. */
sewardjb5bf2e02004-10-25 13:06:17 +000087 LibVEX_default_VexControl ( &vcon );
sewardjb4952402004-10-26 13:24:50 +000088 vcon.iropt_level = 2;
sewardjc279b3f2005-03-16 18:10:45 +000089 vcon.guest_max_insns = 50;
sewardjb5bf2e02004-10-25 13:06:17 +000090
sewardjced9fe52004-07-07 11:55:36 +000091 LibVEX_Init ( &failure_exit, &log_bytes,
sewardj1f40a0a2004-07-21 12:28:07 +000092 1, /* debug_paranoia */
sewardjabe017e2004-10-29 23:42:36 +000093 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +000094 &vcon );
sewardjced9fe52004-07-07 11:55:36 +000095
sewardjea64e142004-07-22 16:47:21 +000096
sewardjced9fe52004-07-07 11:55:36 +000097 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +000098
sewardjced9fe52004-07-07 11:55:36 +000099 fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +0000100 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +0000101 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +0000102
103 if (n_bbs_done == TEST_N_BBS) break;
104 n_bbs_done++;
105
sewardjced9fe52004-07-07 11:55:36 +0000106 /* first line is: . bb-number bb-addr n-bytes */
107 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
108 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000109 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000110 assert(orig_nbytes >= 1);
111 assert(!feof(f));
112 fgets(linebuf, N_LINEBUF,f);
113 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000114
sewardjced9fe52004-07-07 11:55:36 +0000115 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000116 if (verbose)
sewardj07a54cc2005-02-04 21:18:55 +0000117 printf("============ Basic Block %d, Done %d, "
sewardj4459baa2004-09-10 20:00:46 +0000118 "Start %x, nbytes %2d ============",
sewardj07a54cc2005-02-04 21:18:55 +0000119 bb_number, n_bbs_done-1, orig_addr, orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000120
sewardjced9fe52004-07-07 11:55:36 +0000121 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
122 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000123 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
124 origbuf[i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000125 }
126
sewardj9e6491a2005-07-02 19:24:10 +0000127 LibVEX_default_VexArchInfo(&vai_x86);
128 vai_x86.subarch = VexSubArchX86_sse1;
129
130 LibVEX_default_VexArchInfo(&vai_amd64);
131 vai_amd64.subarch = VexSubArch_NONE;
132
133 LibVEX_default_VexArchInfo(&vai_ppc32);
sewardj059601a2005-11-13 00:53:05 +0000134 vai_ppc32.subarch = VexSubArchPPC32_VFI;
sewardj9e6491a2005-07-02 19:24:10 +0000135 vai_ppc32.ppc32_cache_line_szB = 128;
sewardj02ef7162005-06-30 12:50:50 +0000136
sewardj17c7f952005-12-15 14:02:34 +0000137 /* ----- Set up args for LibVEX_Translate ----- */
sewardj9e6491a2005-07-02 19:24:10 +0000138#if 1 /* ppc32 -> ppc32 */
sewardj17c7f952005-12-15 14:02:34 +0000139 vta.arch_guest = VexArchPPC32;
140 vta.archinfo_guest = vai_ppc32;
141 vta.arch_host = VexArchPPC32;
142 vta.archinfo_host = vai_ppc32;
sewardj07a54cc2005-02-04 21:18:55 +0000143#endif
sewardjc279b3f2005-03-16 18:10:45 +0000144#if 0 /* amd64 -> amd64 */
sewardj17c7f952005-12-15 14:02:34 +0000145 vta.arch_guest = VexArchAMD64;
146 vta.archinfo_guest = vai_amd64;
147 vta.arch_host = VexArchAMD64;
148 vta.archinfo_host = vai_amd64;
sewardj07a54cc2005-02-04 21:18:55 +0000149#endif
sewardj9e6491a2005-07-02 19:24:10 +0000150#if 0 /* x86 -> x86 */
sewardj17c7f952005-12-15 14:02:34 +0000151 vta.arch_guest = VexArchX86;
152 vta.archinfo_guest = vai_x86;
153 vta.arch_host = VexArchX86;
154 vta.archinfo_host = vai_x86;
sewardjc279b3f2005-03-16 18:10:45 +0000155#endif
sewardj17c7f952005-12-15 14:02:34 +0000156 vta.guest_bytes = origbuf;
157 vta.guest_bytes_addr = (Addr64)orig_addr;
158 vta.guest_bytes_addr_noredir = (Addr64)orig_addr;
159 vta.chase_into_ok = chase_into_not_ok;
160 vta.guest_extents = &vge;
161 vta.host_bytes = transbuf;
162 vta.host_bytes_size = N_TRANSBUF;
163 vta.host_bytes_used = &trans_used;
sewardj9e7448b2004-11-18 13:44:15 +0000164#if 1 /* no instrumentation */
sewardj17c7f952005-12-15 14:02:34 +0000165 vta.instrument1 = NULL;
166 vta.instrument2 = NULL;
sewardj9e7448b2004-11-18 13:44:15 +0000167#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000168#if 0 /* addrcheck */
sewardj17c7f952005-12-15 14:02:34 +0000169 vta.instrument1 = ac_instrument;
170 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000171#endif
sewardj9e7448b2004-11-18 13:44:15 +0000172#if 0 /* memcheck */
sewardj17c7f952005-12-15 14:02:34 +0000173 vta.instrument1 = mc_instrument;
174 vta.instrument2 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000175#endif
sewardj17c7f952005-12-15 14:02:34 +0000176 vta.do_self_check = False;
177 vta.traceflags = TEST_FLAGS;
178#if 1 /* x86, amd64 hosts */
179 vta.dispatch = (void*)0x12345678;
180#else /* ppc32, ppc64 hosts */
181 vta.dispatch = NULL;
182#endif
183
184 for (i = 0; i < TEST_N_ITERS; i++)
185 tres = LibVEX_Translate ( &vta );
sewardjabe017e2004-10-29 23:42:36 +0000186
sewardjd887b862005-01-17 18:34:34 +0000187 if (tres != VexTransOK)
sewardj4459baa2004-09-10 20:00:46 +0000188 printf("\ntres = %d\n", (Int)tres);
sewardjd887b862005-01-17 18:34:34 +0000189 assert(tres == VexTransOK);
sewardj72c72812005-01-19 11:49:45 +0000190 assert(vge.n_used == 1);
191 assert((UInt)(vge.len[0]) == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000192
sewardj4459baa2004-09-10 20:00:46 +0000193 sum = 0;
194 for (i = 0; i < trans_used; i++)
195 sum += (UInt)transbuf[i];
sewardjde8c9872005-03-25 13:48:55 +0000196 printf ( " %6.2f ... %u\n",
197 (double)trans_used / (double)vge.len[0], sum );
sewardjced9fe52004-07-07 11:55:36 +0000198 }
199
200 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000201 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000202 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000203
sewardjce605f92004-07-05 14:39:15 +0000204 return 0;
205}
sewardj9b1004e2004-10-30 22:25:40 +0000206
207//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000208//////////////////////////////////////////////////////////////////////
209//////////////////////////////////////////////////////////////////////
210//////////////////////////////////////////////////////////////////////
211//////////////////////////////////////////////////////////////////////
212//////////////////////////////////////////////////////////////////////
213//////////////////////////////////////////////////////////////////////
214//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000215
sewardj1ea1b612005-03-26 13:02:20 +0000216#if 0 /* UNUSED */
217
sewardj9b1004e2004-10-30 22:25:40 +0000218static
sewardjde8a5ae2004-11-06 14:20:54 +0000219__attribute((noreturn))
sewardjde8c9872005-03-25 13:48:55 +0000220void panic ( HChar* s )
sewardj9b1004e2004-10-30 22:25:40 +0000221{
222 printf("\npanic: %s\n", s);
223 failure_exit();
224}
225
226static
sewardj9578a8b2004-11-04 19:44:48 +0000227IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000228{
229/* Use this rather than eg. -1 because it's a UInt. */
230#define INVALID_DATA_SIZE 999999
231
232 Int i;
233 Int sz;
234 IRCallee* helper;
235 IRStmt* st;
236 IRExpr* data;
237 IRExpr* addr;
238 Bool needSz;
239
240 /* Set up BB */
241 IRBB* bb = emptyIRBB();
242 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
243 bb->next = dopyIRExpr(bb_in->next);
244 bb->jumpkind = bb_in->jumpkind;
245
246 /* No loads to consider in ->next. */
sewardj496a58d2005-03-20 18:44:44 +0000247 assert(isIRAtom(bb_in->next));
sewardj9b1004e2004-10-30 22:25:40 +0000248
249 for (i = 0; i < bb_in->stmts_used; i++) {
250 st = bb_in->stmts[i];
251 if (!st) continue;
252
253 switch (st->tag) {
254
255 case Ist_Tmp:
256 data = st->Ist.Tmp.data;
257 if (data->tag == Iex_LDle) {
258 addr = data->Iex.LDle.addr;
259 sz = sizeofIRType(data->Iex.LDle.ty);
260 needSz = False;
261 switch (sz) {
262 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000263 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000264 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000265 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000266 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000267 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000268 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000269 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000270 needSz = True; break;
271 }
272 if (needSz) {
273 addStmtToIRBB(
274 bb,
275 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000276 unsafeIRDirty_0_N( helper->regparms,
277 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000278 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
279 ));
280 } else {
281 addStmtToIRBB(
282 bb,
283 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000284 unsafeIRDirty_0_N( helper->regparms,
285 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000286 mkIRExprVec_1(addr) )
287 ));
288 }
289 }
290 break;
291
292 case Ist_STle:
293 data = st->Ist.STle.data;
294 addr = st->Ist.STle.addr;
sewardj496a58d2005-03-20 18:44:44 +0000295 assert(isIRAtom(data));
296 assert(isIRAtom(addr));
sewardj9b1004e2004-10-30 22:25:40 +0000297 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
298 needSz = False;
299 switch (sz) {
300 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000301 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000302 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000303 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000304 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000305 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000306 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000307 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000308 needSz = True; break;
309 }
310 if (needSz) {
311 addStmtToIRBB(
312 bb,
313 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000314 unsafeIRDirty_0_N( helper->regparms,
315 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000316 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
317 ));
318 } else {
319 addStmtToIRBB(
320 bb,
321 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000322 unsafeIRDirty_0_N( helper->regparms,
323 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000324 mkIRExprVec_1(addr) )
325 ));
326 }
327 break;
328
329 case Ist_Put:
sewardj496a58d2005-03-20 18:44:44 +0000330 assert(isIRAtom(st->Ist.Put.data));
sewardj9b1004e2004-10-30 22:25:40 +0000331 break;
332
333 case Ist_PutI:
sewardj496a58d2005-03-20 18:44:44 +0000334 assert(isIRAtom(st->Ist.PutI.ix));
335 assert(isIRAtom(st->Ist.PutI.data));
sewardj9b1004e2004-10-30 22:25:40 +0000336 break;
337
338 case Ist_Exit:
sewardj496a58d2005-03-20 18:44:44 +0000339 assert(isIRAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000340 break;
341
342 case Ist_Dirty:
343 /* If the call doesn't interact with memory, we ain't
344 interested. */
345 if (st->Ist.Dirty.details->mFx == Ifx_None)
346 break;
347 goto unhandled;
348
349 default:
350 unhandled:
351 printf("\n");
352 ppIRStmt(st);
353 printf("\n");
354 panic("addrcheck: unhandled IRStmt");
355 }
356
357 addStmtToIRBB( bb, dopyIRStmt(st));
358 }
359
360 return bb;
361}
cerionaee45242005-03-17 14:03:36 +0000362#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +0000363
364//////////////////////////////////////////////////////////////////////
365//////////////////////////////////////////////////////////////////////
366//////////////////////////////////////////////////////////////////////
367//////////////////////////////////////////////////////////////////////
368//////////////////////////////////////////////////////////////////////
369//////////////////////////////////////////////////////////////////////
370//////////////////////////////////////////////////////////////////////
371//////////////////////////////////////////////////////////////////////
372
sewardj1ea1b612005-03-26 13:02:20 +0000373#if 0 /* UNUSED */
374
sewardj69f9e3e2004-12-30 02:05:34 +0000375#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000376#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000377#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000378#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000379#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000380
cerionaee45242005-03-17 14:03:36 +0000381
sewardjde8c9872005-03-25 13:48:55 +0000382static void MC_helperc_complain_undef ( void );
383static void MC_helperc_LOADV8 ( void );
384static void MC_helperc_LOADV4 ( void );
385static void MC_helperc_LOADV2 ( void );
386static void MC_helperc_LOADV1 ( void );
sewardj1ea1b612005-03-26 13:02:20 +0000387static void MC_helperc_STOREV8( void );
388static void MC_helperc_STOREV4( void );
389static void MC_helperc_STOREV2( void );
390static void MC_helperc_STOREV1( void );
sewardjde8c9872005-03-25 13:48:55 +0000391static void MC_helperc_value_check0_fail( void );
392static void MC_helperc_value_check1_fail( void );
393static void MC_helperc_value_check4_fail( void );
394
395static void MC_helperc_complain_undef ( void ) { }
396static void MC_helperc_LOADV8 ( void ) { }
397static void MC_helperc_LOADV4 ( void ) { }
398static void MC_helperc_LOADV2 ( void ) { }
399static void MC_helperc_LOADV1 ( void ) { }
sewardj1ea1b612005-03-26 13:02:20 +0000400static void MC_helperc_STOREV8( void ) { }
401static void MC_helperc_STOREV4( void ) { }
402static void MC_helperc_STOREV2( void ) { }
403static void MC_helperc_STOREV1( void ) { }
sewardjde8c9872005-03-25 13:48:55 +0000404static void MC_helperc_value_check0_fail( void ) { }
405static void MC_helperc_value_check1_fail( void ) { }
406static void MC_helperc_value_check4_fail( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000407
408
sewardj3598ef92004-11-11 02:13:30 +0000409/*--------------------------------------------------------------------*/
410/*--- Instrument IR to perform memory checking operations. ---*/
411/*--- mc_translate.c ---*/
412/*--------------------------------------------------------------------*/
413
414/*
415 This file is part of MemCheck, a heavyweight Valgrind tool for
416 detecting memory errors.
417
418 Copyright (C) 2000-2004 Julian Seward
419 jseward@acm.org
420
421 This program is free software; you can redistribute it and/or
422 modify it under the terms of the GNU General Public License as
423 published by the Free Software Foundation; either version 2 of the
424 License, or (at your option) any later version.
425
426 This program is distributed in the hope that it will be useful, but
427 WITHOUT ANY WARRANTY; without even the implied warranty of
428 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
429 General Public License for more details.
430
431 You should have received a copy of the GNU General Public License
432 along with this program; if not, write to the Free Software
433 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
434 02111-1307, USA.
435
436 The GNU General Public License is contained in the file COPYING.
437*/
438
439//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000440
441
442/*------------------------------------------------------------*/
443/*--- Forward decls ---*/
444/*------------------------------------------------------------*/
445
446struct _MCEnv;
447
448static IRType shadowType ( IRType ty );
449static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
450
451
452/*------------------------------------------------------------*/
453/*--- Memcheck running state, and tmp management. ---*/
454/*------------------------------------------------------------*/
455
456/* Carries around state during memcheck instrumentation. */
457typedef
458 struct _MCEnv {
459 /* MODIFIED: the bb being constructed. IRStmts are added. */
460 IRBB* bb;
461
462 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
463 original temps to their current their current shadow temp.
464 Initially all entries are IRTemp_INVALID. Entries are added
465 lazily since many original temps are not used due to
466 optimisation prior to instrumentation. Note that floating
467 point original tmps are shadowed by integer tmps of the same
468 size, and Bit-typed original tmps are shadowed by the type
469 Ity_I8. See comment below. */
470 IRTemp* tmpMap;
471 Int n_originalTmps; /* for range checking */
472
473 /* READONLY: the guest layout. This indicates which parts of
474 the guest state should be regarded as 'always defined'. */
475 VexGuestLayout* layout;
476 /* READONLY: the host word type. Needed for constructing
477 arguments of type 'HWord' to be passed to helper functions.
478 Ity_I32 or Ity_I64 only. */
479 IRType hWordTy;
480 }
481 MCEnv;
482
483/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
484 demand), as they are encountered. This is for two reasons.
485
486 (1) (less important reason): Many original tmps are unused due to
487 initial IR optimisation, and we do not want to spaces in tables
488 tracking them.
489
490 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
491 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000492 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000493 It is necessary to support making multiple assignments to a shadow
494 -- specifically, after testing a shadow for definedness, it needs
495 to be made defined. But IR's SSA property disallows this.
496
497 (2) (more important reason): Therefore, when a shadow needs to get
498 a new value, a new temporary is created, the value is assigned to
499 that, and the tmpMap is updated to reflect the new binding.
500
501 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000502 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000503 there's a read-before-write error in the original tmps. The IR
504 sanity checker should catch all such anomalies, however.
505*/
506
507/* Find the tmp currently shadowing the given original tmp. If none
508 so far exists, allocate one. */
509static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
510{
sewardj69f9e3e2004-12-30 02:05:34 +0000511 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000512 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000513 mce->tmpMap[orig]
514 = newIRTemp(mce->bb->tyenv,
515 shadowType(mce->bb->tyenv->types[orig]));
516 }
517 return mce->tmpMap[orig];
518}
519
520/* Allocate a new shadow for the given original tmp. This means any
521 previous shadow is abandoned. This is needed because it is
522 necessary to give a new value to a shadow once it has been tested
523 for undefinedness, but unfortunately IR's SSA property disallows
524 this. Instead we must abandon the old shadow, allocate a new one
525 and use that instead. */
526static void newShadowTmp ( MCEnv* mce, IRTemp orig )
527{
sewardj69f9e3e2004-12-30 02:05:34 +0000528 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000529 mce->tmpMap[orig]
530 = newIRTemp(mce->bb->tyenv,
531 shadowType(mce->bb->tyenv->types[orig]));
532}
533
534
535/*------------------------------------------------------------*/
536/*--- IRAtoms -- a subset of IRExprs ---*/
537/*------------------------------------------------------------*/
538
539/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj496a58d2005-03-20 18:44:44 +0000540 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardjde8a5ae2004-11-06 14:20:54 +0000541 input, most of this code deals in atoms. Usefully, a value atom
542 always has a V-value which is also an atom: constants are shadowed
543 by constants, and temps are shadowed by the corresponding shadow
544 temporary. */
545
546typedef IRExpr IRAtom;
547
548/* (used for sanity checks only): is this an atom which looks
549 like it's from original code? */
550static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
551{
552 if (a1->tag == Iex_Const)
553 return True;
554 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
555 return True;
556 return False;
557}
558
559/* (used for sanity checks only): is this an atom which looks
560 like it's from shadow code? */
561static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
562{
563 if (a1->tag == Iex_Const)
564 return True;
565 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
566 return True;
567 return False;
568}
569
570/* (used for sanity checks only): check that both args are atoms and
571 are identically-kinded. */
572static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
573{
574 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
575 return True;
576 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
577 return True;
578 return False;
579}
580
581
582/*------------------------------------------------------------*/
583/*--- Type management ---*/
584/*------------------------------------------------------------*/
585
586/* Shadow state is always accessed using integer types. This returns
587 an integer type with the same size (as per sizeofIRType) as the
588 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000589 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000590
591static IRType shadowType ( IRType ty )
592{
593 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000594 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000595 case Ity_I8:
596 case Ity_I16:
597 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000598 case Ity_I64: return ty;
599 case Ity_F32: return Ity_I32;
600 case Ity_F64: return Ity_I64;
601 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000602 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000603 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000604 }
605}
606
607/* Produce a 'defined' value of the given shadow type. Should only be
608 supplied shadow types (Bit/I8/I16/I32/UI64). */
609static IRExpr* definedOfType ( IRType ty ) {
610 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000611 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
612 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
613 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
614 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
615 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
616 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
617 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000618 }
619}
620
621
622/*------------------------------------------------------------*/
623/*--- Constructing IR fragments ---*/
624/*------------------------------------------------------------*/
625
626/* assign value to tmp */
627#define assign(_bb,_tmp,_expr) \
628 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
629
630/* add stmt to a bb */
631#define stmt(_bb,_stmt) \
632 addStmtToIRBB((_bb), (_stmt))
633
634/* build various kinds of expressions */
635#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
636#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
637#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
638#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
639#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
640#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000641#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardjde8a5ae2004-11-06 14:20:54 +0000642#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
643
644/* bind the given expression to a new temporary, and return the
645 temporary. This effectively converts an arbitrary expression into
646 an atom. */
647static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
648 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
649 assign(mce->bb, t, e);
650 return mkexpr(t);
651}
652
653
654/*------------------------------------------------------------*/
655/*--- Constructing definedness primitive ops ---*/
656/*------------------------------------------------------------*/
657
658/* --------- Defined-if-either-defined --------- */
659
660static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000661 tl_assert(isShadowAtom(mce,a1));
662 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000663 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
664}
665
666static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000667 tl_assert(isShadowAtom(mce,a1));
668 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000669 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
670}
671
672static IRAtom* mkDifD32 ( 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_I32, binop(Iop_And32, a1, a2));
676}
677
sewardj69f9e3e2004-12-30 02:05:34 +0000678static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
679 tl_assert(isShadowAtom(mce,a1));
680 tl_assert(isShadowAtom(mce,a2));
681 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
682}
683
sewardjf0c1c582005-02-07 23:47:38 +0000684static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000685 tl_assert(isShadowAtom(mce,a1));
686 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000687 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000688}
689
sewardjde8a5ae2004-11-06 14:20:54 +0000690/* --------- Undefined-if-either-undefined --------- */
691
692static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000693 tl_assert(isShadowAtom(mce,a1));
694 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000695 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
696}
697
698static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000699 tl_assert(isShadowAtom(mce,a1));
700 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000701 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
702}
703
704static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000705 tl_assert(isShadowAtom(mce,a1));
706 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000707 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
708}
709
710static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000711 tl_assert(isShadowAtom(mce,a1));
712 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000713 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
714}
715
sewardjf0c1c582005-02-07 23:47:38 +0000716static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000717 tl_assert(isShadowAtom(mce,a1));
718 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000719 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000720}
721
722static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000723 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000724 case Ity_I8: return mkUifU8(mce, a1, a2);
725 case Ity_I16: return mkUifU16(mce, a1, a2);
726 case Ity_I32: return mkUifU32(mce, a1, a2);
727 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardjf0c1c582005-02-07 23:47:38 +0000728 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000729 default:
730 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000731 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000732 }
733}
734
735/* --------- The Left-family of operations. --------- */
736
737static IRAtom* mkLeft8 ( 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_I8,
741 binop(Iop_Or8, a1,
742 assignNew(mce, Ity_I8,
743 /* unop(Iop_Neg8, a1)))); */
744 binop(Iop_Sub8, mkU8(0), a1) )));
745}
746
747static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000748 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000749 /* It's safe to duplicate a1 since it's only an atom */
750 return assignNew(mce, Ity_I16,
751 binop(Iop_Or16, a1,
752 assignNew(mce, Ity_I16,
753 /* unop(Iop_Neg16, a1)))); */
754 binop(Iop_Sub16, mkU16(0), a1) )));
755}
756
757static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000758 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000759 /* It's safe to duplicate a1 since it's only an atom */
760 return assignNew(mce, Ity_I32,
761 binop(Iop_Or32, a1,
762 assignNew(mce, Ity_I32,
763 /* unop(Iop_Neg32, a1)))); */
764 binop(Iop_Sub32, mkU32(0), a1) )));
765}
766
767/* --------- 'Improvement' functions for AND/OR. --------- */
768
769/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
770 defined (0); all other -> undefined (1).
771*/
772static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
773{
sewardj69f9e3e2004-12-30 02:05:34 +0000774 tl_assert(isOriginalAtom(mce, data));
775 tl_assert(isShadowAtom(mce, vbits));
776 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000777 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
778}
779
sewardj3598ef92004-11-11 02:13:30 +0000780static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
781{
sewardj69f9e3e2004-12-30 02:05:34 +0000782 tl_assert(isOriginalAtom(mce, data));
783 tl_assert(isShadowAtom(mce, vbits));
784 tl_assert(sameKindedAtoms(data, vbits));
sewardj3598ef92004-11-11 02:13:30 +0000785 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
786}
787
sewardjde8a5ae2004-11-06 14:20:54 +0000788static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
789{
sewardj69f9e3e2004-12-30 02:05:34 +0000790 tl_assert(isOriginalAtom(mce, data));
791 tl_assert(isShadowAtom(mce, vbits));
792 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000793 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
794}
795
sewardj69f9e3e2004-12-30 02:05:34 +0000796static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
797{
798 tl_assert(isOriginalAtom(mce, data));
799 tl_assert(isShadowAtom(mce, vbits));
800 tl_assert(sameKindedAtoms(data, vbits));
801 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
802}
803
sewardjf0c1c582005-02-07 23:47:38 +0000804static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000805{
806 tl_assert(isOriginalAtom(mce, data));
807 tl_assert(isShadowAtom(mce, vbits));
808 tl_assert(sameKindedAtoms(data, vbits));
sewardjf0c1c582005-02-07 23:47:38 +0000809 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj69f9e3e2004-12-30 02:05:34 +0000810}
811
sewardjde8a5ae2004-11-06 14:20:54 +0000812/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
813 defined (0); all other -> undefined (1).
814*/
815static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
816{
sewardj69f9e3e2004-12-30 02:05:34 +0000817 tl_assert(isOriginalAtom(mce, data));
818 tl_assert(isShadowAtom(mce, vbits));
819 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000820 return assignNew(
821 mce, Ity_I8,
822 binop(Iop_Or8,
823 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
824 vbits) );
825}
826
827static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
828{
sewardj69f9e3e2004-12-30 02:05:34 +0000829 tl_assert(isOriginalAtom(mce, data));
830 tl_assert(isShadowAtom(mce, vbits));
831 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000832 return assignNew(
833 mce, Ity_I16,
834 binop(Iop_Or16,
835 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
836 vbits) );
837}
838
839static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
840{
sewardj69f9e3e2004-12-30 02:05:34 +0000841 tl_assert(isOriginalAtom(mce, data));
842 tl_assert(isShadowAtom(mce, vbits));
843 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000844 return assignNew(
845 mce, Ity_I32,
846 binop(Iop_Or32,
847 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
848 vbits) );
849}
850
sewardj69f9e3e2004-12-30 02:05:34 +0000851static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
852{
853 tl_assert(isOriginalAtom(mce, data));
854 tl_assert(isShadowAtom(mce, vbits));
855 tl_assert(sameKindedAtoms(data, vbits));
856 return assignNew(
857 mce, Ity_I64,
858 binop(Iop_Or64,
859 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
860 vbits) );
861}
862
sewardjf0c1c582005-02-07 23:47:38 +0000863static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000864{
865 tl_assert(isOriginalAtom(mce, data));
866 tl_assert(isShadowAtom(mce, vbits));
867 tl_assert(sameKindedAtoms(data, vbits));
868 return assignNew(
869 mce, Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +0000870 binop(Iop_OrV128,
871 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj69f9e3e2004-12-30 02:05:34 +0000872 vbits) );
873}
874
sewardjde8a5ae2004-11-06 14:20:54 +0000875/* --------- Pessimising casts. --------- */
876
877static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
878{
sewardj8fc93742004-11-22 11:29:33 +0000879 IRType ty;
880 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000881 /* Note, dst_ty is a shadow type, not an original type. */
882 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000883 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000884 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
885 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000886 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000887 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000888 tmp1 = vbits;
889 break;
890 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000891 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000892 break;
893 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000894 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000895 break;
896 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000897 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000898 break;
899 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000900 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000901 break;
902 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000903 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000904 }
sewardj69f9e3e2004-12-30 02:05:34 +0000905 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000906 /* Now widen up to the dst type. */
907 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000908 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000909 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000910 case Ity_I8:
911 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000912 case Ity_I16:
913 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
914 case Ity_I32:
915 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
916 case Ity_I64:
917 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000918 case Ity_V128:
919 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardjf0c1c582005-02-07 23:47:38 +0000920 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000921 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000922 default:
923 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000924 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +0000925 }
926}
927
928
929/*------------------------------------------------------------*/
930/*--- Emit a test and complaint if something is undefined. ---*/
931/*------------------------------------------------------------*/
932
933/* Set the annotations on a dirty helper to indicate that the stack
934 pointer and instruction pointers might be read. This is the
935 behaviour of all 'emit-a-complaint' style functions we might
936 call. */
937
938static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
939 di->nFxState = 2;
940 di->fxState[0].fx = Ifx_Read;
941 di->fxState[0].offset = mce->layout->offset_SP;
942 di->fxState[0].size = mce->layout->sizeof_SP;
943 di->fxState[1].fx = Ifx_Read;
944 di->fxState[1].offset = mce->layout->offset_IP;
945 di->fxState[1].size = mce->layout->sizeof_IP;
946}
947
948
949/* Check the supplied **original** atom for undefinedness, and emit a
950 complaint if so. Once that happens, mark it as defined. This is
951 possible because the atom is either a tmp or literal. If it's a
952 tmp, it will be shadowed by a tmp, and so we can set the shadow to
953 be defined. In fact as mentioned above, we will have to allocate a
954 new tmp to carry the new 'defined' shadow value, and update the
955 original->tmp mapping accordingly; we cannot simply assign a new
956 value to an existing shadow tmp as this breaks SSAness -- resulting
957 in the post-instrumentation sanity checker spluttering in disapproval.
958*/
959static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
960{
sewardj8fc93742004-11-22 11:29:33 +0000961 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +0000962 IRType ty;
963 Int sz;
sewardj8fc93742004-11-22 11:29:33 +0000964 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +0000965 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +0000966
sewardjde8a5ae2004-11-06 14:20:54 +0000967 /* Since the original expression is atomic, there's no duplicated
968 work generated by making multiple V-expressions for it. So we
969 don't really care about the possibility that someone else may
970 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +0000971 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +0000972 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +0000973 tl_assert(isShadowAtom(mce, vatom));
974 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +0000975
sewardj8fc93742004-11-22 11:29:33 +0000976 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +0000977
978 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +0000979 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +0000980
sewardj8fc93742004-11-22 11:29:33 +0000981 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +0000982 /* cond will be 0 if all defined, and 1 if any not defined. */
983
sewardj3598ef92004-11-11 02:13:30 +0000984 switch (sz) {
985 case 0:
986 di = unsafeIRDirty_0_N( 0/*regparms*/,
987 "MC_(helperc_value_check0_fail)",
988 &MC_(helperc_value_check0_fail),
989 mkIRExprVec_0()
990 );
991 break;
992 case 1:
993 di = unsafeIRDirty_0_N( 0/*regparms*/,
994 "MC_(helperc_value_check1_fail)",
995 &MC_(helperc_value_check1_fail),
996 mkIRExprVec_0()
997 );
998 break;
999 case 4:
1000 di = unsafeIRDirty_0_N( 0/*regparms*/,
1001 "MC_(helperc_value_check4_fail)",
1002 &MC_(helperc_value_check4_fail),
1003 mkIRExprVec_0()
1004 );
1005 break;
1006 default:
1007 di = unsafeIRDirty_0_N( 1/*regparms*/,
1008 "MC_(helperc_complain_undef)",
1009 &MC_(helperc_complain_undef),
1010 mkIRExprVec_1( mkIRExpr_HWord( sz ))
1011 );
1012 break;
1013 }
sewardjde8a5ae2004-11-06 14:20:54 +00001014 di->guard = cond;
1015 setHelperAnns( mce, di );
1016 stmt( mce->bb, IRStmt_Dirty(di));
1017
1018 /* Set the shadow tmp to be defined. First, update the
1019 orig->shadow tmp mapping to reflect the fact that this shadow is
1020 getting a new value. */
sewardj496a58d2005-03-20 18:44:44 +00001021 tl_assert(isIRAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001022 /* sameKindedAtoms ... */
1023 if (vatom->tag == Iex_Tmp) {
sewardj69f9e3e2004-12-30 02:05:34 +00001024 tl_assert(atom->tag == Iex_Tmp);
sewardjde8a5ae2004-11-06 14:20:54 +00001025 newShadowTmp(mce, atom->Iex.Tmp.tmp);
1026 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
1027 definedOfType(ty));
1028 }
1029}
1030
1031
1032/*------------------------------------------------------------*/
1033/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
1034/*------------------------------------------------------------*/
1035
1036/* Examine the always-defined sections declared in layout to see if
1037 the (offset,size) section is within one. Note, is is an error to
1038 partially fall into such a region: (offset,size) should either be
1039 completely in such a region or completely not-in such a region.
1040*/
1041static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1042{
1043 Int minoffD, maxoffD, i;
1044 Int minoff = offset;
1045 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001046 tl_assert((minoff & ~0xFFFF) == 0);
1047 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001048
1049 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1050 minoffD = mce->layout->alwaysDefd[i].offset;
1051 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001052 tl_assert((minoffD & ~0xFFFF) == 0);
1053 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001054
1055 if (maxoff < minoffD || maxoffD < minoff)
1056 continue; /* no overlap */
1057 if (minoff >= minoffD && maxoff <= maxoffD)
1058 return True; /* completely contained in an always-defd section */
1059
sewardj69f9e3e2004-12-30 02:05:34 +00001060 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001061 }
1062 return False; /* could not find any containing section */
1063}
1064
1065
1066/* Generate into bb suitable actions to shadow this Put. If the state
1067 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001068 supplied V bits to the shadow state. We can pass in either an
1069 original atom or a V-atom, but not both. In the former case the
1070 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001071*/
1072static
sewardj3598ef92004-11-11 02:13:30 +00001073void do_shadow_PUT ( MCEnv* mce, Int offset,
1074 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001075{
sewardj8fc93742004-11-22 11:29:33 +00001076 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001077 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001078 tl_assert(!vatom);
1079 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001080 vatom = expr2vbits( mce, atom );
1081 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001082 tl_assert(vatom);
1083 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001084 }
1085
sewardj8fc93742004-11-22 11:29:33 +00001086 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001087 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001088 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1089 /* later: no ... */
1090 /* emit code to emit a complaint if any of the vbits are 1. */
1091 /* complainIfUndefined(mce, atom); */
1092 } else {
1093 /* Do a plain shadow Put. */
1094 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1095 }
1096}
1097
1098
1099/* Return an expression which contains the V bits corresponding to the
1100 given GETI (passed in in pieces).
1101*/
1102static
1103void do_shadow_PUTI ( MCEnv* mce,
1104 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
1105{
sewardj8fc93742004-11-22 11:29:33 +00001106 IRAtom* vatom;
1107 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001108 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001109
sewardj69f9e3e2004-12-30 02:05:34 +00001110 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001111 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001112 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001113 ty = descr->elemTy;
1114 tyS = shadowType(ty);
1115 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001116 tl_assert(ty != Ity_I1);
1117 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001118 complainIfUndefined(mce,ix);
1119 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1120 /* later: no ... */
1121 /* emit code to emit a complaint if any of the vbits are 1. */
1122 /* complainIfUndefined(mce, atom); */
1123 } else {
1124 /* Do a cloned version of the Put that refers to the shadow
1125 area. */
1126 IRArray* new_descr
1127 = mkIRArray( descr->base + mce->layout->total_sizeB,
1128 tyS, descr->nElems);
1129 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1130 }
1131}
1132
1133
1134/* Return an expression which contains the V bits corresponding to the
1135 given GET (passed in in pieces).
1136*/
1137static
1138IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1139{
1140 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001141 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001142 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1143 /* Always defined, return all zeroes of the relevant type */
1144 return definedOfType(tyS);
1145 } else {
1146 /* return a cloned version of the Get that refers to the shadow
1147 area. */
1148 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1149 }
1150}
1151
1152
1153/* Return an expression which contains the V bits corresponding to the
1154 given GETI (passed in in pieces).
1155*/
1156static
1157IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
1158{
1159 IRType ty = descr->elemTy;
1160 IRType tyS = shadowType(ty);
1161 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001162 tl_assert(ty != Ity_I1);
1163 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001164 complainIfUndefined(mce,ix);
1165 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1166 /* Always defined, return all zeroes of the relevant type */
1167 return definedOfType(tyS);
1168 } else {
1169 /* return a cloned version of the Get that refers to the shadow
1170 area. */
1171 IRArray* new_descr
1172 = mkIRArray( descr->base + mce->layout->total_sizeB,
1173 tyS, descr->nElems);
1174 return IRExpr_GetI( new_descr, ix, bias );
1175 }
1176}
1177
1178
1179/*------------------------------------------------------------*/
1180/*--- Generating approximations for unknown operations, ---*/
1181/*--- using lazy-propagate semantics ---*/
1182/*------------------------------------------------------------*/
1183
1184/* Lazy propagation of undefinedness from two values, resulting in the
1185 specified shadow type.
1186*/
1187static
1188IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1189{
1190 /* force everything via 32-bit intermediaries. */
1191 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001192 tl_assert(isShadowAtom(mce,va1));
1193 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001194 at = mkPCastTo(mce, Ity_I32, va1);
1195 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1196 at = mkPCastTo(mce, finalVty, at);
1197 return at;
1198}
1199
1200
1201/* Do the lazy propagation game from a null-terminated vector of
1202 atoms. This is presumably the arguments to a helper call, so the
1203 IRCallee info is also supplied in order that we can know which
1204 arguments should be ignored (via the .mcx_mask field).
1205*/
1206static
1207IRAtom* mkLazyN ( MCEnv* mce,
1208 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1209{
1210 Int i;
1211 IRAtom* here;
1212 IRAtom* curr = definedOfType(Ity_I32);
1213 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001214 tl_assert(i < 32);
1215 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001216 /* Only take notice of this arg if the callee's mc-exclusion
1217 mask does not say it is to be excluded. */
1218 if (cee->mcx_mask & (1<<i)) {
1219 /* the arg is to be excluded from definedness checking. Do
1220 nothing. */
1221 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1222 } else {
1223 /* calculate the arg's definedness, and pessimistically merge
1224 it in. */
1225 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1226 curr = mkUifU32(mce, here, curr);
1227 }
1228 }
1229 return mkPCastTo(mce, finalVtype, curr );
1230}
1231
1232
1233/*------------------------------------------------------------*/
1234/*--- Generating expensive sequences for exact carry-chain ---*/
1235/*--- propagation in add/sub and related operations. ---*/
1236/*------------------------------------------------------------*/
1237
1238static
1239IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1240 IRAtom* aa, IRAtom* bb )
1241{
sewardj69f9e3e2004-12-30 02:05:34 +00001242 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001243 IRType ty;
1244 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001245
sewardj69f9e3e2004-12-30 02:05:34 +00001246 tl_assert(isShadowAtom(mce,qaa));
1247 tl_assert(isShadowAtom(mce,qbb));
1248 tl_assert(isOriginalAtom(mce,aa));
1249 tl_assert(isOriginalAtom(mce,bb));
1250 tl_assert(sameKindedAtoms(qaa,aa));
1251 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001252
sewardj8fc93742004-11-22 11:29:33 +00001253 ty = Ity_I32;
1254 opAND = Iop_And32;
1255 opOR = Iop_Or32;
1256 opXOR = Iop_Xor32;
1257 opNOT = Iop_Not32;
1258 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001259
1260 // a_min = aa & ~qaa
1261 a_min = assignNew(mce,ty,
1262 binop(opAND, aa,
1263 assignNew(mce,ty, unop(opNOT, qaa))));
1264
1265 // b_min = bb & ~qbb
1266 b_min = assignNew(mce,ty,
1267 binop(opAND, bb,
1268 assignNew(mce,ty, unop(opNOT, qbb))));
1269
1270 // a_max = aa | qaa
1271 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1272
1273 // b_max = bb | qbb
1274 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1275
1276 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1277 return
1278 assignNew(mce,ty,
1279 binop( opOR,
1280 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1281 assignNew(mce,ty,
1282 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1283 assignNew(mce,ty, binop(opADD, a_max, b_max))
1284 )
1285 )
1286 )
1287 );
1288}
1289
1290
1291/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001292/*--- Helpers for dealing with vector primops. ---*/
1293/*------------------------------------------------------------*/
1294
1295/* Vector pessimisation -- pessimise within each lane individually. */
1296
1297static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1298{
1299 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1300}
1301
1302static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1303{
1304 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1305}
1306
1307static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1308{
1309 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1310}
1311
1312static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1313{
1314 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1315}
1316
1317
1318/* Here's a simple scheme capable of handling ops derived from SSE1
1319 code and while only generating ops that can be efficiently
1320 implemented in SSE1. */
1321
1322/* All-lanes versions are straightforward:
1323
sewardjf0c1c582005-02-07 23:47:38 +00001324 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj69f9e3e2004-12-30 02:05:34 +00001325
1326 unary32Fx4(x,y) ==> PCast32x4(x#)
1327
1328 Lowest-lane-only versions are more complex:
1329
sewardjf0c1c582005-02-07 23:47:38 +00001330 binary32F0x4(x,y) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001331 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001332 PCast32(V128to32(UifUV128(x#,y#)))
sewardj69f9e3e2004-12-30 02:05:34 +00001333 )
1334
1335 This is perhaps not so obvious. In particular, it's faster to
sewardjf0c1c582005-02-07 23:47:38 +00001336 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj69f9e3e2004-12-30 02:05:34 +00001337 obvious scheme of taking the bottom 32 bits of each operand
1338 and doing a 32-bit UifU. Basically since UifU is fast and
1339 chopping lanes off vector values is slow.
1340
1341 Finally:
1342
sewardjf0c1c582005-02-07 23:47:38 +00001343 unary32F0x4(x) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001344 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001345 PCast32(V128to32(x#))
sewardj69f9e3e2004-12-30 02:05:34 +00001346 )
1347
1348 Where:
1349
1350 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1351 PCast32x4(v#) = CmpNEZ32x4(v#)
1352*/
1353
1354static
1355IRAtom* binary32Fx4 ( 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);
sewardj69f9e3e2004-12-30 02:05:34 +00001361 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1362 return at;
1363}
1364
1365static
1366IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1367{
1368 IRAtom* at;
1369 tl_assert(isShadowAtom(mce, vatomX));
1370 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1371 return at;
1372}
1373
1374static
1375IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1376{
1377 IRAtom* at;
1378 tl_assert(isShadowAtom(mce, vatomX));
1379 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001380 at = mkUifUV128(mce, vatomX, vatomY);
1381 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001382 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001383 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001384 return at;
1385}
1386
1387static
1388IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1389{
1390 IRAtom* at;
1391 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001392 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001393 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001394 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001395 return at;
1396}
1397
1398/* --- ... and ... 64Fx2 versions of the same ... --- */
1399
1400static
1401IRAtom* binary64Fx2 ( 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);
sewardj69f9e3e2004-12-30 02:05:34 +00001407 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1408 return at;
1409}
1410
1411static
1412IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1413{
1414 IRAtom* at;
1415 tl_assert(isShadowAtom(mce, vatomX));
1416 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1417 return at;
1418}
1419
1420static
1421IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1422{
1423 IRAtom* at;
1424 tl_assert(isShadowAtom(mce, vatomX));
1425 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001426 at = mkUifUV128(mce, vatomX, vatomY);
1427 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001428 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001429 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001430 return at;
1431}
1432
1433static
1434IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1435{
1436 IRAtom* at;
1437 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001438 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001439 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001440 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001441 return at;
1442}
1443
1444/* --- --- Vector saturated narrowing --- --- */
1445
1446/* This is quite subtle. What to do is simple:
1447
1448 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1449
1450 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1451
1452 Why this is right is not so simple. Consider a lane in the args,
1453 vatom1 or 2, doesn't matter.
1454
1455 After the PCast, that lane is all 0s (defined) or all
1456 1s(undefined).
1457
1458 Both signed and unsigned saturating narrowing of all 0s produces
1459 all 0s, which is what we want.
1460
1461 The all-1s case is more complex. Unsigned narrowing interprets an
1462 all-1s input as the largest unsigned integer, and so produces all
1463 1s as a result since that is the largest unsigned value at the
1464 smaller width.
1465
1466 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1467 to -1, so we still wind up with all 1s at the smaller width.
1468
1469 So: In short, pessimise the args, then apply the original narrowing
1470 op.
1471*/
1472static
sewardjf0c1c582005-02-07 23:47:38 +00001473IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardj69f9e3e2004-12-30 02:05:34 +00001474 IRAtom* vatom1, IRAtom* vatom2)
1475{
1476 IRAtom *at1, *at2, *at3;
1477 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1478 switch (narrow_op) {
1479 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1480 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1481 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardjf0c1c582005-02-07 23:47:38 +00001482 default: VG_(tool_panic)("vectorNarrowV128");
sewardj69f9e3e2004-12-30 02:05:34 +00001483 }
1484 tl_assert(isShadowAtom(mce,vatom1));
1485 tl_assert(isShadowAtom(mce,vatom2));
1486 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1487 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1488 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1489 return at3;
1490}
1491
1492
1493/* --- --- Vector integer arithmetic --- --- */
1494
1495/* Simple ... UifU the args and per-lane pessimise the results. */
1496static
1497IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1498{
1499 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001500 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001501 at = mkPCast8x16(mce, at);
1502 return at;
1503}
1504
1505static
1506IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1507{
1508 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001509 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001510 at = mkPCast16x8(mce, at);
1511 return at;
1512}
1513
1514static
1515IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1516{
1517 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001518 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001519 at = mkPCast32x4(mce, at);
1520 return at;
1521}
1522
1523static
1524IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1525{
1526 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001527 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001528 at = mkPCast64x2(mce, at);
1529 return at;
1530}
1531
1532
1533/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001534/*--- Generate shadow values from all kinds of IRExprs. ---*/
1535/*------------------------------------------------------------*/
1536
1537static
1538IRAtom* expr2vbits_Binop ( MCEnv* mce,
1539 IROp op,
1540 IRAtom* atom1, IRAtom* atom2 )
1541{
1542 IRType and_or_ty;
1543 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1544 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1545 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1546
1547 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1548 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1549
sewardj69f9e3e2004-12-30 02:05:34 +00001550 tl_assert(isOriginalAtom(mce,atom1));
1551 tl_assert(isOriginalAtom(mce,atom2));
1552 tl_assert(isShadowAtom(mce,vatom1));
1553 tl_assert(isShadowAtom(mce,vatom2));
1554 tl_assert(sameKindedAtoms(atom1,vatom1));
1555 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001556 switch (op) {
1557
sewardjf0c1c582005-02-07 23:47:38 +00001558 /* V128-bit SIMD (SSE2-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001559
1560 case Iop_ShrN16x8:
1561 case Iop_ShrN32x4:
1562 case Iop_ShrN64x2:
1563 case Iop_SarN16x8:
1564 case Iop_SarN32x4:
1565 case Iop_ShlN16x8:
1566 case Iop_ShlN32x4:
1567 case Iop_ShlN64x2:
1568 /* Same scheme as with all other shifts. */
1569 complainIfUndefined(mce, atom2);
1570 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1571
1572 case Iop_QSub8Ux16:
1573 case Iop_QSub8Sx16:
1574 case Iop_Sub8x16:
1575 case Iop_Min8Ux16:
1576 case Iop_Max8Ux16:
1577 case Iop_CmpGT8Sx16:
1578 case Iop_CmpEQ8x16:
1579 case Iop_Avg8Ux16:
1580 case Iop_QAdd8Ux16:
1581 case Iop_QAdd8Sx16:
1582 case Iop_Add8x16:
1583 return binary8Ix16(mce, vatom1, vatom2);
1584
1585 case Iop_QSub16Ux8:
1586 case Iop_QSub16Sx8:
1587 case Iop_Sub16x8:
1588 case Iop_Mul16x8:
1589 case Iop_MulHi16Sx8:
1590 case Iop_MulHi16Ux8:
1591 case Iop_Min16Sx8:
1592 case Iop_Max16Sx8:
1593 case Iop_CmpGT16Sx8:
1594 case Iop_CmpEQ16x8:
1595 case Iop_Avg16Ux8:
1596 case Iop_QAdd16Ux8:
1597 case Iop_QAdd16Sx8:
1598 case Iop_Add16x8:
1599 return binary16Ix8(mce, vatom1, vatom2);
1600
1601 case Iop_Sub32x4:
1602 case Iop_CmpGT32Sx4:
1603 case Iop_CmpEQ32x4:
1604 case Iop_Add32x4:
1605 return binary32Ix4(mce, vatom1, vatom2);
1606
1607 case Iop_Sub64x2:
1608 case Iop_Add64x2:
1609 return binary64Ix2(mce, vatom1, vatom2);
1610
1611 case Iop_QNarrow32Sx4:
1612 case Iop_QNarrow16Sx8:
1613 case Iop_QNarrow16Ux8:
sewardjf0c1c582005-02-07 23:47:38 +00001614 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001615
1616 case Iop_Sub64Fx2:
1617 case Iop_Mul64Fx2:
1618 case Iop_Min64Fx2:
1619 case Iop_Max64Fx2:
1620 case Iop_Div64Fx2:
1621 case Iop_CmpLT64Fx2:
1622 case Iop_CmpLE64Fx2:
1623 case Iop_CmpEQ64Fx2:
1624 case Iop_Add64Fx2:
1625 return binary64Fx2(mce, vatom1, vatom2);
1626
1627 case Iop_Sub64F0x2:
1628 case Iop_Mul64F0x2:
1629 case Iop_Min64F0x2:
1630 case Iop_Max64F0x2:
1631 case Iop_Div64F0x2:
1632 case Iop_CmpLT64F0x2:
1633 case Iop_CmpLE64F0x2:
1634 case Iop_CmpEQ64F0x2:
1635 case Iop_Add64F0x2:
1636 return binary64F0x2(mce, vatom1, vatom2);
1637
sewardjf0c1c582005-02-07 23:47:38 +00001638 /* V128-bit SIMD (SSE1-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001639
1640 case Iop_Sub32Fx4:
1641 case Iop_Mul32Fx4:
1642 case Iop_Min32Fx4:
1643 case Iop_Max32Fx4:
1644 case Iop_Div32Fx4:
1645 case Iop_CmpLT32Fx4:
1646 case Iop_CmpLE32Fx4:
1647 case Iop_CmpEQ32Fx4:
1648 case Iop_Add32Fx4:
1649 return binary32Fx4(mce, vatom1, vatom2);
1650
1651 case Iop_Sub32F0x4:
1652 case Iop_Mul32F0x4:
1653 case Iop_Min32F0x4:
1654 case Iop_Max32F0x4:
1655 case Iop_Div32F0x4:
1656 case Iop_CmpLT32F0x4:
1657 case Iop_CmpLE32F0x4:
1658 case Iop_CmpEQ32F0x4:
1659 case Iop_Add32F0x4:
1660 return binary32F0x4(mce, vatom1, vatom2);
1661
sewardjf0c1c582005-02-07 23:47:38 +00001662 /* V128-bit data-steering */
1663 case Iop_SetV128lo32:
1664 case Iop_SetV128lo64:
1665 case Iop_64HLtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001666 case Iop_InterleaveLO64x2:
1667 case Iop_InterleaveLO32x4:
1668 case Iop_InterleaveLO16x8:
1669 case Iop_InterleaveLO8x16:
1670 case Iop_InterleaveHI64x2:
1671 case Iop_InterleaveHI32x4:
1672 case Iop_InterleaveHI16x8:
1673 case Iop_InterleaveHI8x16:
1674 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1675
1676 /* Scalar floating point */
1677
sewardj3598ef92004-11-11 02:13:30 +00001678 case Iop_RoundF64:
1679 case Iop_F64toI64:
sewardj69f9e3e2004-12-30 02:05:34 +00001680 case Iop_I64toF64:
1681 /* First arg is I32 (rounding mode), second is F64 or I64
1682 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001683 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1684
1685 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1686 /* Takes two F64 args. */
sewardjde8a5ae2004-11-06 14:20:54 +00001687 case Iop_F64toI32:
sewardj69f9e3e2004-12-30 02:05:34 +00001688 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001689 /* First arg is I32 (rounding mode), second is F64 (data). */
1690 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1691
1692 case Iop_F64toI16:
1693 /* First arg is I32 (rounding mode), second is F64 (data). */
1694 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1695
sewardj3598ef92004-11-11 02:13:30 +00001696 case Iop_ScaleF64:
1697 case Iop_Yl2xF64:
1698 case Iop_Yl2xp1F64:
1699 case Iop_PRemF64:
1700 case Iop_AtanF64:
1701 case Iop_AddF64:
1702 case Iop_DivF64:
1703 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001704 case Iop_MulF64:
1705 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1706
sewardj3598ef92004-11-11 02:13:30 +00001707 case Iop_CmpF64:
1708 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1709
sewardjde8a5ae2004-11-06 14:20:54 +00001710 /* non-FP after here */
1711
1712 case Iop_DivModU64to32:
1713 case Iop_DivModS64to32:
1714 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1715
sewardj3598ef92004-11-11 02:13:30 +00001716 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001717 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001718 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001719 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001720
1721 case Iop_MullS32:
1722 case Iop_MullU32: {
1723 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1724 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1725 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1726 }
1727
sewardj3598ef92004-11-11 02:13:30 +00001728 case Iop_MullS16:
1729 case Iop_MullU16: {
1730 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1731 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1732 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1733 }
1734
1735 case Iop_MullS8:
1736 case Iop_MullU8: {
1737 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1738 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1739 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1740 }
1741
sewardjde8a5ae2004-11-06 14:20:54 +00001742 case Iop_Add32:
1743# if 0
1744 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1745# endif
1746 case Iop_Sub32:
1747 case Iop_Mul32:
1748 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1749
sewardj3598ef92004-11-11 02:13:30 +00001750 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001751 case Iop_Add16:
1752 case Iop_Sub16:
1753 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1754
1755 case Iop_Sub8:
1756 case Iop_Add8:
1757 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1758
1759 case Iop_CmpLE32S: case Iop_CmpLE32U:
1760 case Iop_CmpLT32U: case Iop_CmpLT32S:
1761 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001762 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001763
sewardj3598ef92004-11-11 02:13:30 +00001764 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001765 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001766
1767 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001768 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001769
1770 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1771 /* Complain if the shift amount is undefined. Then simply
1772 shift the first arg's V bits by the real shift amount. */
1773 complainIfUndefined(mce, atom2);
1774 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1775
sewardj69f9e3e2004-12-30 02:05:34 +00001776 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001777 /* Same scheme as with 32-bit shifts. */
1778 complainIfUndefined(mce, atom2);
1779 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1780
sewardj3598ef92004-11-11 02:13:30 +00001781 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001782 /* Same scheme as with 32-bit shifts. */
1783 complainIfUndefined(mce, atom2);
1784 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1785
1786 case Iop_Shl64: case Iop_Shr64:
1787 /* Same scheme as with 32-bit shifts. */
1788 complainIfUndefined(mce, atom2);
1789 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1790
sewardjf0c1c582005-02-07 23:47:38 +00001791 case Iop_AndV128:
1792 uifu = mkUifUV128; difd = mkDifDV128;
1793 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001794 case Iop_And64:
1795 uifu = mkUifU64; difd = mkDifD64;
1796 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001797 case Iop_And32:
1798 uifu = mkUifU32; difd = mkDifD32;
1799 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001800 case Iop_And16:
1801 uifu = mkUifU16; difd = mkDifD16;
1802 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001803 case Iop_And8:
1804 uifu = mkUifU8; difd = mkDifD8;
1805 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1806
sewardjf0c1c582005-02-07 23:47:38 +00001807 case Iop_OrV128:
1808 uifu = mkUifUV128; difd = mkDifDV128;
1809 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001810 case Iop_Or64:
1811 uifu = mkUifU64; difd = mkDifD64;
1812 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001813 case Iop_Or32:
1814 uifu = mkUifU32; difd = mkDifD32;
1815 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1816 case Iop_Or16:
1817 uifu = mkUifU16; difd = mkDifD16;
1818 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1819 case Iop_Or8:
1820 uifu = mkUifU8; difd = mkDifD8;
1821 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1822
1823 do_And_Or:
1824 return
1825 assignNew(
1826 mce,
1827 and_or_ty,
1828 difd(mce, uifu(mce, vatom1, vatom2),
1829 difd(mce, improve(mce, atom1, vatom1),
1830 improve(mce, atom2, vatom2) ) ) );
1831
1832 case Iop_Xor8:
1833 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001834 case Iop_Xor16:
1835 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001836 case Iop_Xor32:
1837 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001838 case Iop_Xor64:
1839 return mkUifU64(mce, vatom1, vatom2);
sewardjf0c1c582005-02-07 23:47:38 +00001840 case Iop_XorV128:
1841 return mkUifUV128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001842
1843 default:
1844 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001845 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001846 }
1847}
1848
1849
1850static
1851IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1852{
1853 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001854 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001855 switch (op) {
1856
sewardj69f9e3e2004-12-30 02:05:34 +00001857 case Iop_Sqrt64Fx2:
1858 return unary64Fx2(mce, vatom);
1859
1860 case Iop_Sqrt64F0x2:
1861 return unary64F0x2(mce, vatom);
1862
1863 case Iop_Sqrt32Fx4:
1864 case Iop_RSqrt32Fx4:
1865 case Iop_Recip32Fx4:
1866 return unary32Fx4(mce, vatom);
1867
1868 case Iop_Sqrt32F0x4:
1869 case Iop_RSqrt32F0x4:
1870 case Iop_Recip32F0x4:
1871 return unary32F0x4(mce, vatom);
1872
sewardjf0c1c582005-02-07 23:47:38 +00001873 case Iop_32UtoV128:
1874 case Iop_64UtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001875 return assignNew(mce, Ity_V128, unop(op, vatom));
1876
sewardjde8a5ae2004-11-06 14:20:54 +00001877 case Iop_F32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001878 case Iop_I32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001879 case Iop_NegF64:
1880 case Iop_SinF64:
1881 case Iop_CosF64:
1882 case Iop_TanF64:
1883 case Iop_SqrtF64:
1884 case Iop_AbsF64:
1885 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001886 return mkPCastTo(mce, Ity_I64, vatom);
1887
sewardj3598ef92004-11-11 02:13:30 +00001888 case Iop_Clz32:
1889 case Iop_Ctz32:
1890 return mkPCastTo(mce, Ity_I32, vatom);
1891
1892 case Iop_32Sto64:
1893 case Iop_32Uto64:
sewardjf0c1c582005-02-07 23:47:38 +00001894 case Iop_V128to64:
1895 case Iop_V128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001896 return assignNew(mce, Ity_I64, unop(op, vatom));
1897
sewardjde8a5ae2004-11-06 14:20:54 +00001898 case Iop_64to32:
1899 case Iop_64HIto32:
1900 case Iop_1Uto32:
1901 case Iop_8Uto32:
1902 case Iop_16Uto32:
1903 case Iop_16Sto32:
1904 case Iop_8Sto32:
1905 return assignNew(mce, Ity_I32, unop(op, vatom));
1906
1907 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001908 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001909 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001910 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001911 return assignNew(mce, Ity_I16, unop(op, vatom));
1912
1913 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001914 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001915 case Iop_32to8:
1916 return assignNew(mce, Ity_I8, unop(op, vatom));
1917
1918 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001919 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001920
sewardj3598ef92004-11-11 02:13:30 +00001921 case Iop_ReinterpF64asI64:
1922 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001923 case Iop_ReinterpI32asF32:
sewardjf0c1c582005-02-07 23:47:38 +00001924 case Iop_NotV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001925 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00001926 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001927 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001928 case Iop_Not8:
1929 case Iop_Not1:
1930 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001931
sewardjde8a5ae2004-11-06 14:20:54 +00001932 default:
1933 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001934 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00001935 }
1936}
1937
1938
sewardj69f9e3e2004-12-30 02:05:34 +00001939/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00001940static
sewardj69f9e3e2004-12-30 02:05:34 +00001941IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001942{
1943 void* helper;
sewardjde8c9872005-03-25 13:48:55 +00001944 HChar* hname;
sewardjde8a5ae2004-11-06 14:20:54 +00001945 IRDirty* di;
1946 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00001947 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001948
sewardj69f9e3e2004-12-30 02:05:34 +00001949 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00001950
1951 /* First, emit a definedness test for the address. This also sets
1952 the address (shadow) to 'defined' following the test. */
1953 complainIfUndefined( mce, addr );
1954
1955 /* Now cook up a call to the relevant helper function, to read the
1956 data V bits from shadow memory. */
1957 ty = shadowType(ty);
1958 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001959 case Ity_I64: helper = &MC_(helperc_LOADV8);
1960 hname = "MC_(helperc_LOADV8)";
1961 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001962 case Ity_I32: helper = &MC_(helperc_LOADV4);
1963 hname = "MC_(helperc_LOADV4)";
1964 break;
1965 case Ity_I16: helper = &MC_(helperc_LOADV2);
1966 hname = "MC_(helperc_LOADV2)";
1967 break;
1968 case Ity_I8: helper = &MC_(helperc_LOADV1);
1969 hname = "MC_(helperc_LOADV1)";
1970 break;
1971 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001972 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00001973 }
1974
sewardj3598ef92004-11-11 02:13:30 +00001975 /* Generate the actual address into addrAct. */
1976 if (bias == 0) {
1977 addrAct = addr;
1978 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001979 IROp mkAdd;
1980 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00001981 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00001982 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
1983 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1984 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00001985 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1986 }
1987
sewardjde8a5ae2004-11-06 14:20:54 +00001988 /* We need to have a place to park the V bits we're just about to
1989 read. */
1990 datavbits = newIRTemp(mce->bb->tyenv, ty);
1991 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00001992 1/*regparms*/, hname, helper,
1993 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00001994 setHelperAnns( mce, di );
1995 stmt( mce->bb, IRStmt_Dirty(di) );
1996
1997 return mkexpr(datavbits);
1998}
1999
2000
2001static
sewardj69f9e3e2004-12-30 02:05:34 +00002002IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
2003{
2004 IRAtom *v64hi, *v64lo;
2005 switch (shadowType(ty)) {
2006 case Ity_I8:
2007 case Ity_I16:
2008 case Ity_I32:
2009 case Ity_I64:
2010 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
2011 case Ity_V128:
2012 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
2013 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
2014 return assignNew( mce,
2015 Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +00002016 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj69f9e3e2004-12-30 02:05:34 +00002017 default:
2018 VG_(tool_panic)("expr2vbits_LDle");
2019 }
2020}
2021
2022
2023static
sewardjde8a5ae2004-11-06 14:20:54 +00002024IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00002025 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00002026{
2027 IRAtom *vbitsC, *vbits0, *vbitsX;
2028 IRType ty;
2029 /* Given Mux0X(cond,expr0,exprX), generate
2030 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2031 That is, steer the V bits like the originals, but trash the
2032 result if the steering value is undefined. This gives
2033 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00002034 tl_assert(isOriginalAtom(mce, cond));
2035 tl_assert(isOriginalAtom(mce, expr0));
2036 tl_assert(isOriginalAtom(mce, exprX));
sewardjde8a5ae2004-11-06 14:20:54 +00002037
2038 vbitsC = expr2vbits(mce, cond);
2039 vbits0 = expr2vbits(mce, expr0);
2040 vbitsX = expr2vbits(mce, exprX);
2041 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2042
2043 return
2044 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2045 mkPCastTo(mce, ty, vbitsC) );
2046}
2047
2048/* --------- This is the main expression-handling function. --------- */
2049
2050static
2051IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2052{
2053 switch (e->tag) {
2054
2055 case Iex_Get:
2056 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2057
2058 case Iex_GetI:
2059 return shadow_GETI( mce, e->Iex.GetI.descr,
2060 e->Iex.GetI.ix, e->Iex.GetI.bias );
2061
2062 case Iex_Tmp:
2063 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
2064
2065 case Iex_Const:
2066 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2067
2068 case Iex_Binop:
2069 return expr2vbits_Binop(
2070 mce,
2071 e->Iex.Binop.op,
2072 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2073 );
2074
2075 case Iex_Unop:
2076 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2077
2078 case Iex_LDle:
sewardj3598ef92004-11-11 02:13:30 +00002079 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
2080 e->Iex.LDle.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002081
2082 case Iex_CCall:
2083 return mkLazyN( mce, e->Iex.CCall.args,
2084 e->Iex.CCall.retty,
2085 e->Iex.CCall.cee );
2086
2087 case Iex_Mux0X:
2088 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2089 e->Iex.Mux0X.exprX);
2090
2091 default:
2092 VG_(printf)("\n");
2093 ppIRExpr(e);
2094 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002095 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002096 }
2097}
2098
2099/*------------------------------------------------------------*/
2100/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2101/*------------------------------------------------------------*/
2102
2103/* Widen a value to the host word size. */
2104
2105static
2106IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2107{
sewardj69f9e3e2004-12-30 02:05:34 +00002108 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002109
sewardj8fc93742004-11-22 11:29:33 +00002110 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002111 tl_assert(isShadowAtom(mce,vatom));
2112
2113 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2114 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002115
sewardjde8a5ae2004-11-06 14:20:54 +00002116 if (tyH == Ity_I32) {
2117 switch (ty) {
2118 case Ity_I32: return vatom;
2119 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2120 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2121 default: goto unhandled;
2122 }
2123 } else {
2124 goto unhandled;
2125 }
2126 unhandled:
2127 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002128 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002129}
2130
2131
sewardj3598ef92004-11-11 02:13:30 +00002132/* Generate a shadow store. addr is always the original address atom.
2133 You can pass in either originals or V-bits for the data atom, but
2134 obviously not both. */
2135
sewardjde8a5ae2004-11-06 14:20:54 +00002136static
sewardj3598ef92004-11-11 02:13:30 +00002137void do_shadow_STle ( MCEnv* mce,
2138 IRAtom* addr, UInt bias,
2139 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002140{
sewardj69f9e3e2004-12-30 02:05:34 +00002141 IROp mkAdd;
2142 IRType ty, tyAddr;
2143 IRDirty *di, *diLo64, *diHi64;
2144 IRAtom *addrAct, *addrLo64, *addrHi64;
2145 IRAtom *vdataLo64, *vdataHi64;
2146 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002147 void* helper = NULL;
2148 Char* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002149
2150 tyAddr = mce->hWordTy;
2151 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2152 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2153
2154 di = diLo64 = diHi64 = NULL;
2155 eBias = eBias0 = eBias8 = NULL;
2156 addrAct = addrLo64 = addrHi64 = NULL;
2157 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002158
sewardj3598ef92004-11-11 02:13:30 +00002159 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002160 tl_assert(!vdata);
2161 tl_assert(isOriginalAtom(mce, data));
2162 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002163 vdata = expr2vbits( mce, data );
2164 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002165 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002166 }
sewardjde8a5ae2004-11-06 14:20:54 +00002167
sewardj69f9e3e2004-12-30 02:05:34 +00002168 tl_assert(isOriginalAtom(mce,addr));
2169 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002170
2171 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002172
2173 /* First, emit a definedness test for the address. This also sets
2174 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002175 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002176
sewardj69f9e3e2004-12-30 02:05:34 +00002177 /* Now decide which helper function to call to write the data V
2178 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002179 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002180 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002181 case Ity_I64: helper = &MC_(helperc_STOREV8);
2182 hname = "MC_(helperc_STOREV8)";
2183 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002184 case Ity_I32: helper = &MC_(helperc_STOREV4);
2185 hname = "MC_(helperc_STOREV4)";
2186 break;
2187 case Ity_I16: helper = &MC_(helperc_STOREV2);
2188 hname = "MC_(helperc_STOREV2)";
2189 break;
2190 case Ity_I8: helper = &MC_(helperc_STOREV1);
2191 hname = "MC_(helperc_STOREV1)";
2192 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002193 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002194 }
2195
sewardj69f9e3e2004-12-30 02:05:34 +00002196 if (ty == Ity_V128) {
2197
sewardjf0c1c582005-02-07 23:47:38 +00002198 /* V128-bit case */
sewardj69f9e3e2004-12-30 02:05:34 +00002199 /* See comment in next clause re 64-bit regparms */
2200 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2201 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
sewardjf0c1c582005-02-07 23:47:38 +00002202 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002203 diLo64 = unsafeIRDirty_0_N(
2204 1/*regparms*/, hname, helper,
2205 mkIRExprVec_2( addrLo64, vdataLo64 ));
2206
2207 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2208 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
sewardjf0c1c582005-02-07 23:47:38 +00002209 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002210 diHi64 = unsafeIRDirty_0_N(
2211 1/*regparms*/, hname, helper,
2212 mkIRExprVec_2( addrHi64, vdataHi64 ));
2213
2214 setHelperAnns( mce, diLo64 );
2215 setHelperAnns( mce, diHi64 );
2216 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2217 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2218
sewardj3598ef92004-11-11 02:13:30 +00002219 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002220
2221 /* 8/16/32/64-bit cases */
2222 /* Generate the actual address into addrAct. */
2223 if (bias == 0) {
2224 addrAct = addr;
2225 } else {
2226 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2227 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2228 }
2229
2230 if (ty == Ity_I64) {
2231 /* We can't do this with regparm 2 on 32-bit platforms, since
2232 the back ends aren't clever enough to handle 64-bit
2233 regparm args. Therefore be different. */
2234 di = unsafeIRDirty_0_N(
2235 1/*regparms*/, hname, helper,
2236 mkIRExprVec_2( addrAct, vdata ));
2237 } else {
2238 di = unsafeIRDirty_0_N(
2239 2/*regparms*/, hname, helper,
2240 mkIRExprVec_2( addrAct,
2241 zwidenToHostWord( mce, vdata )));
2242 }
2243 setHelperAnns( mce, di );
2244 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002245 }
2246
sewardjde8a5ae2004-11-06 14:20:54 +00002247}
2248
2249
sewardj3598ef92004-11-11 02:13:30 +00002250/* Do lazy pessimistic propagation through a dirty helper call, by
2251 looking at the annotations on it. This is the most complex part of
2252 Memcheck. */
2253
2254static IRType szToITy ( Int n )
2255{
2256 switch (n) {
2257 case 1: return Ity_I8;
2258 case 2: return Ity_I16;
2259 case 4: return Ity_I32;
2260 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002261 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002262 }
2263}
2264
2265static
2266void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2267{
sewardj69f9e3e2004-12-30 02:05:34 +00002268 Int i, n, offset, toDo, gSz, gOff;
2269 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002270 IRType tyAddr, tySrc, tyDst;
2271 IRTemp dst;
2272
2273 /* First check the guard. */
2274 complainIfUndefined(mce, d->guard);
2275
2276 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002277 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002278
2279 /* Inputs: unmasked args */
2280 for (i = 0; d->args[i]; i++) {
2281 if (d->cee->mcx_mask & (1<<i)) {
2282 /* ignore this arg */
2283 } else {
2284 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2285 curr = mkUifU32(mce, here, curr);
2286 }
2287 }
2288
2289 /* Inputs: guest state that we read. */
2290 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002291 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002292 if (d->fxState[i].fx == Ifx_Write)
2293 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002294
2295 /* Ignore any sections marked as 'always defined'. */
2296 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2297 if (0)
2298 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2299 d->fxState[i].offset, d->fxState[i].size );
2300 continue;
2301 }
2302
sewardj3598ef92004-11-11 02:13:30 +00002303 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002304 consider it. If larger than 8 bytes, deal with it in 8-byte
2305 chunks. */
2306 gSz = d->fxState[i].size;
2307 gOff = d->fxState[i].offset;
2308 tl_assert(gSz > 0);
2309 while (True) {
2310 if (gSz == 0) break;
2311 n = gSz <= 8 ? gSz : 8;
2312 /* update 'curr' with UifU of the state slice
2313 gOff .. gOff+n-1 */
2314 tySrc = szToITy( n );
2315 src = assignNew( mce, tySrc,
2316 shadow_GET(mce, gOff, tySrc ) );
2317 here = mkPCastTo( mce, Ity_I32, src );
2318 curr = mkUifU32(mce, here, curr);
2319 gSz -= n;
2320 gOff += n;
2321 }
2322
sewardj3598ef92004-11-11 02:13:30 +00002323 }
2324
2325 /* Inputs: memory. First set up some info needed regardless of
2326 whether we're doing reads or writes. */
2327 tyAddr = Ity_INVALID;
2328
2329 if (d->mFx != Ifx_None) {
2330 /* Because we may do multiple shadow loads/stores from the same
2331 base address, it's best to do a single test of its
2332 definedness right now. Post-instrumentation optimisation
2333 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002334 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002335 complainIfUndefined(mce, d->mAddr);
2336
2337 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002338 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2339 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002340 }
2341
2342 /* Deal with memory inputs (reads or modifies) */
2343 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2344 offset = 0;
2345 toDo = d->mSize;
2346 /* chew off 32-bit chunks */
2347 while (toDo >= 4) {
2348 here = mkPCastTo(
2349 mce, Ity_I32,
2350 expr2vbits_LDle ( mce, Ity_I32,
2351 d->mAddr, d->mSize - toDo )
2352 );
2353 curr = mkUifU32(mce, here, curr);
2354 toDo -= 4;
2355 }
2356 /* chew off 16-bit chunks */
2357 while (toDo >= 2) {
2358 here = mkPCastTo(
2359 mce, Ity_I32,
2360 expr2vbits_LDle ( mce, Ity_I16,
2361 d->mAddr, d->mSize - toDo )
2362 );
2363 curr = mkUifU32(mce, here, curr);
2364 toDo -= 2;
2365 }
sewardj69f9e3e2004-12-30 02:05:34 +00002366 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002367 }
2368
2369 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2370 all the inputs to the helper. Now we need to re-distribute the
2371 results to all destinations. */
2372
2373 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002374 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002375 dst = findShadowTmp(mce, d->tmp);
2376 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2377 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2378 }
2379
2380 /* Outputs: guest state that we write or modify. */
2381 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002382 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002383 if (d->fxState[i].fx == Ifx_Read)
2384 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002385 /* Ignore any sections marked as 'always defined'. */
2386 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2387 continue;
2388 /* This state element is written or modified. So we need to
2389 consider it. If larger than 8 bytes, deal with it in 8-byte
2390 chunks. */
2391 gSz = d->fxState[i].size;
2392 gOff = d->fxState[i].offset;
2393 tl_assert(gSz > 0);
2394 while (True) {
2395 if (gSz == 0) break;
2396 n = gSz <= 8 ? gSz : 8;
2397 /* Write suitably-casted 'curr' to the state slice
2398 gOff .. gOff+n-1 */
2399 tyDst = szToITy( n );
2400 do_shadow_PUT( mce, gOff,
2401 NULL, /* original atom */
2402 mkPCastTo( mce, tyDst, curr ) );
2403 gSz -= n;
2404 gOff += n;
2405 }
sewardj3598ef92004-11-11 02:13:30 +00002406 }
2407
2408 /* Outputs: memory that we write or modify. */
2409 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2410 offset = 0;
2411 toDo = d->mSize;
2412 /* chew off 32-bit chunks */
2413 while (toDo >= 4) {
2414 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2415 NULL, /* original data */
2416 mkPCastTo( mce, Ity_I32, curr ) );
2417 toDo -= 4;
2418 }
2419 /* chew off 16-bit chunks */
2420 while (toDo >= 2) {
2421 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2422 NULL, /* original data */
2423 mkPCastTo( mce, Ity_I16, curr ) );
2424 toDo -= 2;
2425 }
sewardj69f9e3e2004-12-30 02:05:34 +00002426 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002427 }
2428
2429}
2430
2431
sewardjde8a5ae2004-11-06 14:20:54 +00002432/*------------------------------------------------------------*/
2433/*--- Memcheck main ---*/
2434/*------------------------------------------------------------*/
2435
sewardj3598ef92004-11-11 02:13:30 +00002436static Bool isBogusAtom ( IRAtom* at )
2437{
2438 ULong n = 0;
2439 IRConst* con;
sewardj496a58d2005-03-20 18:44:44 +00002440 tl_assert(isIRAtom(at));
sewardj3598ef92004-11-11 02:13:30 +00002441 if (at->tag == Iex_Tmp)
2442 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002443 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002444 con = at->Iex.Const.con;
2445 switch (con->tag) {
2446 case Ico_U8: n = (ULong)con->Ico.U8; break;
2447 case Ico_U16: n = (ULong)con->Ico.U16; break;
2448 case Ico_U32: n = (ULong)con->Ico.U32; break;
2449 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002450 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002451 }
2452 /* VG_(printf)("%llx\n", n); */
2453 return (n == 0xFEFEFEFF
2454 || n == 0x80808080
2455 || n == 0x1010101
2456 || n == 1010100);
2457}
2458
2459static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2460{
2461 Int i;
2462 IRExpr* e;
2463 switch (st->tag) {
2464 case Ist_Tmp:
2465 e = st->Ist.Tmp.data;
2466 switch (e->tag) {
2467 case Iex_Get:
2468 case Iex_Tmp:
2469 return False;
2470 case Iex_Unop:
2471 return isBogusAtom(e->Iex.Unop.arg);
2472 case Iex_Binop:
2473 return isBogusAtom(e->Iex.Binop.arg1)
2474 || isBogusAtom(e->Iex.Binop.arg2);
2475 case Iex_Mux0X:
2476 return isBogusAtom(e->Iex.Mux0X.cond)
2477 || isBogusAtom(e->Iex.Mux0X.expr0)
2478 || isBogusAtom(e->Iex.Mux0X.exprX);
2479 case Iex_LDle:
2480 return isBogusAtom(e->Iex.LDle.addr);
2481 case Iex_CCall:
2482 for (i = 0; e->Iex.CCall.args[i]; i++)
2483 if (isBogusAtom(e->Iex.CCall.args[i]))
2484 return True;
2485 return False;
2486 default:
2487 goto unhandled;
2488 }
2489 case Ist_Put:
2490 return isBogusAtom(st->Ist.Put.data);
2491 case Ist_STle:
2492 return isBogusAtom(st->Ist.STle.addr)
2493 || isBogusAtom(st->Ist.STle.data);
2494 case Ist_Exit:
sewardj1ea1b612005-03-26 13:02:20 +00002495 return isBogusAtom(st->Ist.Exit.guard);
sewardj3598ef92004-11-11 02:13:30 +00002496 default:
2497 unhandled:
2498 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002499 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002500 }
2501}
sewardj3598ef92004-11-11 02:13:30 +00002502
sewardj1ea1b612005-03-26 13:02:20 +00002503IRBB* mc_instrument ( IRBB* bb_in, VexGuestLayout* layout,
2504 IRType gWordTy, IRType hWordTy )
sewardjde8a5ae2004-11-06 14:20:54 +00002505{
sewardj3598ef92004-11-11 02:13:30 +00002506 Bool verboze = False; //True;
2507
2508 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002509
2510 Int i, j, first_stmt;
2511 IRStmt* st;
2512 MCEnv mce;
2513
2514 /* Set up BB */
2515 IRBB* bb = emptyIRBB();
2516 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
2517 bb->next = dopyIRExpr(bb_in->next);
2518 bb->jumpkind = bb_in->jumpkind;
2519
2520 /* Set up the running environment. Only .bb is modified as we go
2521 along. */
2522 mce.bb = bb;
2523 mce.layout = layout;
2524 mce.n_originalTmps = bb->tyenv->types_used;
2525 mce.hWordTy = hWordTy;
2526 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2527 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002528 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002529
2530 /* Iterate over the stmts. */
2531
2532 for (i = 0; i < bb_in->stmts_used; i++) {
2533 st = bb_in->stmts[i];
2534 if (!st) continue;
2535
sewardj69f9e3e2004-12-30 02:05:34 +00002536 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002537
2538 /*
2539 if (!hasBogusLiterals) {
2540 hasBogusLiterals = checkForBogusLiterals(st);
2541 if (hasBogusLiterals) {
2542 VG_(printf)("bogus: ");
2543 ppIRStmt(st);
2544 VG_(printf)("\n");
2545 }
2546 }
2547 */
sewardjde8a5ae2004-11-06 14:20:54 +00002548 first_stmt = bb->stmts_used;
2549
2550 if (verboze) {
2551 ppIRStmt(st);
2552 VG_(printf)("\n\n");
2553 }
2554
2555 switch (st->tag) {
2556
2557 case Ist_Tmp:
2558 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
2559 expr2vbits( &mce, st->Ist.Tmp.data) );
2560 break;
2561
2562 case Ist_Put:
2563 do_shadow_PUT( &mce,
2564 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002565 st->Ist.Put.data,
2566 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002567 break;
2568
2569 case Ist_PutI:
2570 do_shadow_PUTI( &mce,
2571 st->Ist.PutI.descr,
2572 st->Ist.PutI.ix,
2573 st->Ist.PutI.bias,
2574 st->Ist.PutI.data );
2575 break;
2576
2577 case Ist_STle:
sewardj3598ef92004-11-11 02:13:30 +00002578 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
2579 st->Ist.STle.data,
2580 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002581 break;
2582
2583 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002584 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002585 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002586 break;
2587
2588 case Ist_Dirty:
2589 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002590 break;
2591
sewardj1ea1b612005-03-26 13:02:20 +00002592 case Ist_IMark:
2593 case Ist_NoOp:
2594 break;
2595
sewardjde8a5ae2004-11-06 14:20:54 +00002596 default:
2597 VG_(printf)("\n");
2598 ppIRStmt(st);
2599 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002600 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002601
2602 } /* switch (st->tag) */
2603
2604 if (verboze) {
2605 for (j = first_stmt; j < bb->stmts_used; j++) {
2606 VG_(printf)(" ");
2607 ppIRStmt(bb->stmts[j]);
2608 VG_(printf)("\n");
2609 }
2610 VG_(printf)("\n");
2611 }
2612
2613 addStmtToIRBB(bb, st);
2614
2615 }
2616
2617 /* Now we need to complain if the jump target is undefined. */
2618 first_stmt = bb->stmts_used;
2619
2620 if (verboze) {
2621 VG_(printf)("bb->next = ");
2622 ppIRExpr(bb->next);
2623 VG_(printf)("\n\n");
2624 }
2625
2626 complainIfUndefined( &mce, bb->next );
2627
2628 if (verboze) {
2629 for (j = first_stmt; j < bb->stmts_used; j++) {
2630 VG_(printf)(" ");
2631 ppIRStmt(bb->stmts[j]);
2632 VG_(printf)("\n");
2633 }
2634 VG_(printf)("\n");
2635 }
2636
2637 return bb;
2638}
cerionaee45242005-03-17 14:03:36 +00002639#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002640
2641/*--------------------------------------------------------------------*/
2642/*--- end mc_translate.c ---*/
2643/*--------------------------------------------------------------------*/