blob: 449c4c33e3667c0aa707495bbc6bb56c019d781c [file] [log] [blame]
sewardjc97096c2004-06-30 09:28:04 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
4/*--- This file (test_main.c) is ---*/
5/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
6/*--- ---*/
7/*---------------------------------------------------------------*/
8
9#include <stdio.h>
10#include <stdlib.h>
sewardjced9fe52004-07-07 11:55:36 +000011#include <assert.h>
sewardj9b1004e2004-10-30 22:25:40 +000012#include <string.h>
sewardjc97096c2004-06-30 09:28:04 +000013
sewardjced9fe52004-07-07 11:55:36 +000014#include "libvex_basictypes.h"
15#include "libvex.h"
sewardjc97096c2004-06-30 09:28:04 +000016
sewardjabe017e2004-10-29 23:42:36 +000017#include "test_main.h"
18
19
sewardjc97096c2004-06-30 09:28:04 +000020/*---------------------------------------------------------------*/
21/*--- Test ---*/
22/*---------------------------------------------------------------*/
23
sewardjce605f92004-07-05 14:39:15 +000024
sewardj2b515872004-07-05 20:50:45 +000025__attribute__ ((noreturn))
sewardj41f43bc2004-07-08 14:23:22 +000026static
sewardjce605f92004-07-05 14:39:15 +000027void failure_exit ( void )
28{
29 fprintf(stdout, "VEX did failure_exit. Bye.\n");
30 exit(1);
31}
32
sewardj41f43bc2004-07-08 14:23:22 +000033static
sewardjce605f92004-07-05 14:39:15 +000034void log_bytes ( Char* bytes, Int nbytes )
35{
36 fwrite ( bytes, 1, nbytes, stdout );
37}
38
sewardjced9fe52004-07-07 11:55:36 +000039#define N_LINEBUF 10000
sewardj41f43bc2004-07-08 14:23:22 +000040static Char linebuf[N_LINEBUF];
sewardjced9fe52004-07-07 11:55:36 +000041
sewardjf05537e2004-10-14 01:08:12 +000042#define N_ORIGBUF 1000
sewardj4459baa2004-09-10 20:00:46 +000043#define N_TRANSBUF 5000
sewardjced9fe52004-07-07 11:55:36 +000044
sewardj4459baa2004-09-10 20:00:46 +000045static UChar origbuf[N_ORIGBUF];
46static UChar transbuf[N_TRANSBUF];
sewardjced9fe52004-07-07 11:55:36 +000047
sewardj1f40a0a2004-07-21 12:28:07 +000048static Bool verbose = True;
sewardjced9fe52004-07-07 11:55:36 +000049
sewardj9b1004e2004-10-30 22:25:40 +000050/* Forwards */
sewardj9578a8b2004-11-04 19:44:48 +000051static IRBB* ac_instrument ( IRBB*, VexGuestLayout*, IRType );
sewardjde8a5ae2004-11-06 14:20:54 +000052static IRBB* mc_instrument ( IRBB*, VexGuestLayout*, IRType );
sewardj9b1004e2004-10-30 22:25:40 +000053
sewardj5bd4d162004-11-10 13:02:48 +000054static Bool chase_into_not_ok ( Addr64 dst ) { return False; }
sewardj9b1004e2004-10-30 22:25:40 +000055
sewardjced9fe52004-07-07 11:55:36 +000056int main ( int argc, char** argv )
sewardjce605f92004-07-05 14:39:15 +000057{
sewardjced9fe52004-07-07 11:55:36 +000058 FILE* f;
59 Int i;
sewardj4459baa2004-09-10 20:00:46 +000060 UInt u, sum;
sewardjced9fe52004-07-07 11:55:36 +000061 Addr32 orig_addr;
sewardjabe017e2004-10-29 23:42:36 +000062 Int bb_number, n_bbs_done = 0;
sewardj72c72812005-01-19 11:49:45 +000063 Int orig_nbytes, trans_used;
sewardjd887b862005-01-17 18:34:34 +000064 VexTranslateResult tres;
sewardjb5bf2e02004-10-25 13:06:17 +000065 VexControl vcon;
sewardj72c72812005-01-19 11:49:45 +000066 VexGuestExtents vge;
sewardjced9fe52004-07-07 11:55:36 +000067
68 if (argc != 2) {
69 fprintf(stderr, "usage: vex file.org\n");
70 exit(1);
71 }
72 f = fopen(argv[1], "r");
73 if (!f) {
74 fprintf(stderr, "can't open `%s'\n", argv[1]);
75 exit(1);
76 }
77
sewardjb5bf2e02004-10-25 13:06:17 +000078 /* Run with default params. However, we can't allow bb chasing
79 since that causes the front end to get segfaults when it tries
sewardj5bd4d162004-11-10 13:02:48 +000080 to read code outside the initial BB we hand it. So when calling
81 LibVEX_Translate, send in a chase-into predicate that always
82 returns False. */
sewardjb5bf2e02004-10-25 13:06:17 +000083 LibVEX_default_VexControl ( &vcon );
sewardjb4952402004-10-26 13:24:50 +000084 vcon.iropt_level = 2;
sewardj07a54cc2005-02-04 21:18:55 +000085 vcon.guest_max_insns = 55;
sewardjb5bf2e02004-10-25 13:06:17 +000086
sewardjced9fe52004-07-07 11:55:36 +000087 LibVEX_Init ( &failure_exit, &log_bytes,
sewardj1f40a0a2004-07-21 12:28:07 +000088 1, /* debug_paranoia */
sewardjabe017e2004-10-29 23:42:36 +000089 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +000090 &vcon );
sewardjced9fe52004-07-07 11:55:36 +000091
sewardjea64e142004-07-22 16:47:21 +000092
sewardjced9fe52004-07-07 11:55:36 +000093 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +000094
sewardjced9fe52004-07-07 11:55:36 +000095 fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +000096 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +000097 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +000098
99 if (n_bbs_done == TEST_N_BBS) break;
100 n_bbs_done++;
101
sewardjced9fe52004-07-07 11:55:36 +0000102 /* first line is: . bb-number bb-addr n-bytes */
103 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
104 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000105 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000106 assert(orig_nbytes >= 1);
107 assert(!feof(f));
108 fgets(linebuf, N_LINEBUF,f);
109 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000110
sewardjced9fe52004-07-07 11:55:36 +0000111 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000112 if (verbose)
sewardj07a54cc2005-02-04 21:18:55 +0000113 printf("============ Basic Block %d, Done %d, "
sewardj4459baa2004-09-10 20:00:46 +0000114 "Start %x, nbytes %2d ============",
sewardj07a54cc2005-02-04 21:18:55 +0000115 bb_number, n_bbs_done-1, orig_addr, orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000116
sewardjced9fe52004-07-07 11:55:36 +0000117 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
118 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000119 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
120 origbuf[i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000121 }
122
sewardjabe017e2004-10-29 23:42:36 +0000123 for (i = 0; i < TEST_N_ITERS; i++)
124 tres
125 = LibVEX_Translate (
sewardj07a54cc2005-02-04 21:18:55 +0000126#if 0 /* ppc32 -> x86 */
127 VexArchPPC32, VexSubArchPPC32_noAV,
sewardjc3263ee2004-12-29 17:48:22 +0000128 VexArchX86, VexSubArchX86_sse2,
sewardj07a54cc2005-02-04 21:18:55 +0000129#endif
130#if 1 /* amd64 -> amd64 */
131 VexArchAMD64, VexSubArch_NONE,
132 VexArchAMD64, VexSubArch_NONE,
133#endif
134
sewardj5bd4d162004-11-10 13:02:48 +0000135 origbuf, (Addr64)orig_addr, chase_into_not_ok,
sewardj72c72812005-01-19 11:49:45 +0000136 &vge,
sewardjabe017e2004-10-29 23:42:36 +0000137 transbuf, N_TRANSBUF, &trans_used,
sewardj9e7448b2004-11-18 13:44:15 +0000138#if 1 /* no instrumentation */
139 NULL, /* instrument1 */
140 NULL, /* instrument2 */
141 False, /* cleanup after instrument */
142#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000143#if 0 /* addrcheck */
144 ac_instrument, /* instrument1 */
145 NULL, /* instrument2 */
146 False, /* cleanup after instrument */
147#endif
sewardj9e7448b2004-11-18 13:44:15 +0000148#if 0 /* memcheck */
sewardjde8a5ae2004-11-06 14:20:54 +0000149 mc_instrument, /* instrument1 */
150 NULL, /* instrument2 */
sewardj69f9e3e2004-12-30 02:05:34 +0000151 True, /* cleanup after instrument */
sewardjde8a5ae2004-11-06 14:20:54 +0000152#endif
sewardjabe017e2004-10-29 23:42:36 +0000153 NULL, /* access checker */
154 TEST_FLAGS
155 );
156
sewardjd887b862005-01-17 18:34:34 +0000157 if (tres != VexTransOK)
sewardj4459baa2004-09-10 20:00:46 +0000158 printf("\ntres = %d\n", (Int)tres);
sewardjd887b862005-01-17 18:34:34 +0000159 assert(tres == VexTransOK);
sewardj72c72812005-01-19 11:49:45 +0000160 assert(vge.n_used == 1);
161 assert((UInt)(vge.len[0]) == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000162
sewardj4459baa2004-09-10 20:00:46 +0000163 sum = 0;
164 for (i = 0; i < trans_used; i++)
165 sum += (UInt)transbuf[i];
sewardj72c72812005-01-19 11:49:45 +0000166 printf ( " %6.2f ... %d\n", (double)trans_used / (double)vge.len[0], sum );
sewardjced9fe52004-07-07 11:55:36 +0000167 }
168
169 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000170 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000171 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000172
sewardjce605f92004-07-05 14:39:15 +0000173 return 0;
174}
sewardj9b1004e2004-10-30 22:25:40 +0000175
176//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000177//////////////////////////////////////////////////////////////////////
178//////////////////////////////////////////////////////////////////////
179//////////////////////////////////////////////////////////////////////
180//////////////////////////////////////////////////////////////////////
181//////////////////////////////////////////////////////////////////////
182//////////////////////////////////////////////////////////////////////
183//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000184
185static
sewardjde8a5ae2004-11-06 14:20:54 +0000186__attribute((noreturn))
sewardj9b1004e2004-10-30 22:25:40 +0000187void panic ( Char* s )
188{
189 printf("\npanic: %s\n", s);
190 failure_exit();
191}
192
193static
sewardj9578a8b2004-11-04 19:44:48 +0000194IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000195{
196/* Use this rather than eg. -1 because it's a UInt. */
197#define INVALID_DATA_SIZE 999999
198
199 Int i;
200 Int sz;
201 IRCallee* helper;
202 IRStmt* st;
203 IRExpr* data;
204 IRExpr* addr;
205 Bool needSz;
206
207 /* Set up BB */
208 IRBB* bb = emptyIRBB();
209 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
210 bb->next = dopyIRExpr(bb_in->next);
211 bb->jumpkind = bb_in->jumpkind;
212
213 /* No loads to consider in ->next. */
214 assert(isAtom(bb_in->next));
215
216 for (i = 0; i < bb_in->stmts_used; i++) {
217 st = bb_in->stmts[i];
218 if (!st) continue;
219
220 switch (st->tag) {
221
222 case Ist_Tmp:
223 data = st->Ist.Tmp.data;
224 if (data->tag == Iex_LDle) {
225 addr = data->Iex.LDle.addr;
226 sz = sizeofIRType(data->Iex.LDle.ty);
227 needSz = False;
228 switch (sz) {
229 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000230 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000231 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000232 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000233 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000234 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000235 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000236 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000237 needSz = True; break;
238 }
239 if (needSz) {
240 addStmtToIRBB(
241 bb,
242 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000243 unsafeIRDirty_0_N( helper->regparms,
244 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000245 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
246 ));
247 } else {
248 addStmtToIRBB(
249 bb,
250 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000251 unsafeIRDirty_0_N( helper->regparms,
252 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000253 mkIRExprVec_1(addr) )
254 ));
255 }
256 }
257 break;
258
259 case Ist_STle:
260 data = st->Ist.STle.data;
261 addr = st->Ist.STle.addr;
262 assert(isAtom(data));
263 assert(isAtom(addr));
264 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
265 needSz = False;
266 switch (sz) {
267 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000268 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000269 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000270 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000271 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000272 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000273 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000274 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000275 needSz = True; break;
276 }
277 if (needSz) {
278 addStmtToIRBB(
279 bb,
280 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000281 unsafeIRDirty_0_N( helper->regparms,
282 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000283 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
284 ));
285 } else {
286 addStmtToIRBB(
287 bb,
288 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000289 unsafeIRDirty_0_N( helper->regparms,
290 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000291 mkIRExprVec_1(addr) )
292 ));
293 }
294 break;
295
296 case Ist_Put:
297 assert(isAtom(st->Ist.Put.data));
298 break;
299
300 case Ist_PutI:
sewardjeeac8412004-11-02 00:26:55 +0000301 assert(isAtom(st->Ist.PutI.ix));
sewardj9b1004e2004-10-30 22:25:40 +0000302 assert(isAtom(st->Ist.PutI.data));
303 break;
304
305 case Ist_Exit:
sewardj0276d4b2004-11-15 15:30:21 +0000306 assert(isAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000307 break;
308
309 case Ist_Dirty:
310 /* If the call doesn't interact with memory, we ain't
311 interested. */
312 if (st->Ist.Dirty.details->mFx == Ifx_None)
313 break;
314 goto unhandled;
315
316 default:
317 unhandled:
318 printf("\n");
319 ppIRStmt(st);
320 printf("\n");
321 panic("addrcheck: unhandled IRStmt");
322 }
323
324 addStmtToIRBB( bb, dopyIRStmt(st));
325 }
326
327 return bb;
328}
sewardjde8a5ae2004-11-06 14:20:54 +0000329
330//////////////////////////////////////////////////////////////////////
331//////////////////////////////////////////////////////////////////////
332//////////////////////////////////////////////////////////////////////
333//////////////////////////////////////////////////////////////////////
334//////////////////////////////////////////////////////////////////////
335//////////////////////////////////////////////////////////////////////
336//////////////////////////////////////////////////////////////////////
337//////////////////////////////////////////////////////////////////////
338
sewardj69f9e3e2004-12-30 02:05:34 +0000339#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000340#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000341#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000342#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000343#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000344
345void MC_helperc_complain_undef ( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000346void MC_helperc_LOADV8 ( void ) { }
sewardjde8a5ae2004-11-06 14:20:54 +0000347void MC_helperc_LOADV4 ( void ) { }
348void MC_helperc_LOADV2 ( void ) { }
349void MC_helperc_LOADV1 ( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000350void MC_helperc_STOREV8( void ) { }
sewardjde8a5ae2004-11-06 14:20:54 +0000351void MC_helperc_STOREV4( void ) { }
352void MC_helperc_STOREV2( void ) { }
353void MC_helperc_STOREV1( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000354void MC_helperc_value_check0_fail( void ) { }
355void MC_helperc_value_check1_fail( void ) { }
356void MC_helperc_value_check4_fail( void ) { }
357
358
sewardj3598ef92004-11-11 02:13:30 +0000359/*--------------------------------------------------------------------*/
360/*--- Instrument IR to perform memory checking operations. ---*/
361/*--- mc_translate.c ---*/
362/*--------------------------------------------------------------------*/
363
364/*
365 This file is part of MemCheck, a heavyweight Valgrind tool for
366 detecting memory errors.
367
368 Copyright (C) 2000-2004 Julian Seward
369 jseward@acm.org
370
371 This program is free software; you can redistribute it and/or
372 modify it under the terms of the GNU General Public License as
373 published by the Free Software Foundation; either version 2 of the
374 License, or (at your option) any later version.
375
376 This program is distributed in the hope that it will be useful, but
377 WITHOUT ANY WARRANTY; without even the implied warranty of
378 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
379 General Public License for more details.
380
381 You should have received a copy of the GNU General Public License
382 along with this program; if not, write to the Free Software
383 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
384 02111-1307, USA.
385
386 The GNU General Public License is contained in the file COPYING.
387*/
388
389//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000390
391
392/*------------------------------------------------------------*/
393/*--- Forward decls ---*/
394/*------------------------------------------------------------*/
395
396struct _MCEnv;
397
398static IRType shadowType ( IRType ty );
399static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
400
401
402/*------------------------------------------------------------*/
403/*--- Memcheck running state, and tmp management. ---*/
404/*------------------------------------------------------------*/
405
406/* Carries around state during memcheck instrumentation. */
407typedef
408 struct _MCEnv {
409 /* MODIFIED: the bb being constructed. IRStmts are added. */
410 IRBB* bb;
411
412 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
413 original temps to their current their current shadow temp.
414 Initially all entries are IRTemp_INVALID. Entries are added
415 lazily since many original temps are not used due to
416 optimisation prior to instrumentation. Note that floating
417 point original tmps are shadowed by integer tmps of the same
418 size, and Bit-typed original tmps are shadowed by the type
419 Ity_I8. See comment below. */
420 IRTemp* tmpMap;
421 Int n_originalTmps; /* for range checking */
422
423 /* READONLY: the guest layout. This indicates which parts of
424 the guest state should be regarded as 'always defined'. */
425 VexGuestLayout* layout;
426 /* READONLY: the host word type. Needed for constructing
427 arguments of type 'HWord' to be passed to helper functions.
428 Ity_I32 or Ity_I64 only. */
429 IRType hWordTy;
430 }
431 MCEnv;
432
433/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
434 demand), as they are encountered. This is for two reasons.
435
436 (1) (less important reason): Many original tmps are unused due to
437 initial IR optimisation, and we do not want to spaces in tables
438 tracking them.
439
440 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
441 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000442 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000443 It is necessary to support making multiple assignments to a shadow
444 -- specifically, after testing a shadow for definedness, it needs
445 to be made defined. But IR's SSA property disallows this.
446
447 (2) (more important reason): Therefore, when a shadow needs to get
448 a new value, a new temporary is created, the value is assigned to
449 that, and the tmpMap is updated to reflect the new binding.
450
451 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000452 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000453 there's a read-before-write error in the original tmps. The IR
454 sanity checker should catch all such anomalies, however.
455*/
456
457/* Find the tmp currently shadowing the given original tmp. If none
458 so far exists, allocate one. */
459static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
460{
sewardj69f9e3e2004-12-30 02:05:34 +0000461 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000462 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000463 mce->tmpMap[orig]
464 = newIRTemp(mce->bb->tyenv,
465 shadowType(mce->bb->tyenv->types[orig]));
466 }
467 return mce->tmpMap[orig];
468}
469
470/* Allocate a new shadow for the given original tmp. This means any
471 previous shadow is abandoned. This is needed because it is
472 necessary to give a new value to a shadow once it has been tested
473 for undefinedness, but unfortunately IR's SSA property disallows
474 this. Instead we must abandon the old shadow, allocate a new one
475 and use that instead. */
476static void newShadowTmp ( MCEnv* mce, IRTemp orig )
477{
sewardj69f9e3e2004-12-30 02:05:34 +0000478 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000479 mce->tmpMap[orig]
480 = newIRTemp(mce->bb->tyenv,
481 shadowType(mce->bb->tyenv->types[orig]));
482}
483
484
485/*------------------------------------------------------------*/
486/*--- IRAtoms -- a subset of IRExprs ---*/
487/*------------------------------------------------------------*/
488
489/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
490 isAtom() in libvex_ir.h. Because this instrumenter expects flat
491 input, most of this code deals in atoms. Usefully, a value atom
492 always has a V-value which is also an atom: constants are shadowed
493 by constants, and temps are shadowed by the corresponding shadow
494 temporary. */
495
496typedef IRExpr IRAtom;
497
498/* (used for sanity checks only): is this an atom which looks
499 like it's from original code? */
500static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
501{
502 if (a1->tag == Iex_Const)
503 return True;
504 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
505 return True;
506 return False;
507}
508
509/* (used for sanity checks only): is this an atom which looks
510 like it's from shadow code? */
511static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
512{
513 if (a1->tag == Iex_Const)
514 return True;
515 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
516 return True;
517 return False;
518}
519
520/* (used for sanity checks only): check that both args are atoms and
521 are identically-kinded. */
522static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
523{
524 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
525 return True;
526 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
527 return True;
528 return False;
529}
530
531
532/*------------------------------------------------------------*/
533/*--- Type management ---*/
534/*------------------------------------------------------------*/
535
536/* Shadow state is always accessed using integer types. This returns
537 an integer type with the same size (as per sizeofIRType) as the
538 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000539 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000540
541static IRType shadowType ( IRType ty )
542{
543 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000544 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000545 case Ity_I8:
546 case Ity_I16:
547 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000548 case Ity_I64: return ty;
549 case Ity_F32: return Ity_I32;
550 case Ity_F64: return Ity_I64;
551 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000552 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000553 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000554 }
555}
556
557/* Produce a 'defined' value of the given shadow type. Should only be
558 supplied shadow types (Bit/I8/I16/I32/UI64). */
559static IRExpr* definedOfType ( IRType ty ) {
560 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000561 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
562 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
563 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
564 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
565 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
566 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
567 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000568 }
569}
570
571
572/*------------------------------------------------------------*/
573/*--- Constructing IR fragments ---*/
574/*------------------------------------------------------------*/
575
576/* assign value to tmp */
577#define assign(_bb,_tmp,_expr) \
578 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
579
580/* add stmt to a bb */
581#define stmt(_bb,_stmt) \
582 addStmtToIRBB((_bb), (_stmt))
583
584/* build various kinds of expressions */
585#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
586#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
587#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
588#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
589#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
590#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000591#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardjde8a5ae2004-11-06 14:20:54 +0000592#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
593
594/* bind the given expression to a new temporary, and return the
595 temporary. This effectively converts an arbitrary expression into
596 an atom. */
597static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
598 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
599 assign(mce->bb, t, e);
600 return mkexpr(t);
601}
602
603
604/*------------------------------------------------------------*/
605/*--- Constructing definedness primitive ops ---*/
606/*------------------------------------------------------------*/
607
608/* --------- Defined-if-either-defined --------- */
609
610static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000611 tl_assert(isShadowAtom(mce,a1));
612 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000613 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
614}
615
616static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000617 tl_assert(isShadowAtom(mce,a1));
618 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000619 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
620}
621
622static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000623 tl_assert(isShadowAtom(mce,a1));
624 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000625 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
626}
627
sewardj69f9e3e2004-12-30 02:05:34 +0000628static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
629 tl_assert(isShadowAtom(mce,a1));
630 tl_assert(isShadowAtom(mce,a2));
631 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
632}
633
634static IRAtom* mkDifD128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
635 tl_assert(isShadowAtom(mce,a1));
636 tl_assert(isShadowAtom(mce,a2));
637 return assignNew(mce, Ity_V128, binop(Iop_And128, a1, a2));
638}
639
sewardjde8a5ae2004-11-06 14:20:54 +0000640/* --------- Undefined-if-either-undefined --------- */
641
642static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000643 tl_assert(isShadowAtom(mce,a1));
644 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000645 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
646}
647
648static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000649 tl_assert(isShadowAtom(mce,a1));
650 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000651 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
652}
653
654static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000655 tl_assert(isShadowAtom(mce,a1));
656 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000657 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
658}
659
660static IRAtom* mkUifU64 ( 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_I64, binop(Iop_Or64, a1, a2));
664}
665
sewardj69f9e3e2004-12-30 02:05:34 +0000666static IRAtom* mkUifU128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
667 tl_assert(isShadowAtom(mce,a1));
668 tl_assert(isShadowAtom(mce,a2));
669 return assignNew(mce, Ity_V128, binop(Iop_Or128, a1, a2));
670}
671
672static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000673 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000674 case Ity_I8: return mkUifU8(mce, a1, a2);
675 case Ity_I16: return mkUifU16(mce, a1, a2);
676 case Ity_I32: return mkUifU32(mce, a1, a2);
677 case Ity_I64: return mkUifU64(mce, a1, a2);
678 case Ity_V128: return mkUifU128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000679 default:
680 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000681 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000682 }
683}
684
685/* --------- The Left-family of operations. --------- */
686
687static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000688 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000689 /* It's safe to duplicate a1 since it's only an atom */
690 return assignNew(mce, Ity_I8,
691 binop(Iop_Or8, a1,
692 assignNew(mce, Ity_I8,
693 /* unop(Iop_Neg8, a1)))); */
694 binop(Iop_Sub8, mkU8(0), a1) )));
695}
696
697static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000698 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000699 /* It's safe to duplicate a1 since it's only an atom */
700 return assignNew(mce, Ity_I16,
701 binop(Iop_Or16, a1,
702 assignNew(mce, Ity_I16,
703 /* unop(Iop_Neg16, a1)))); */
704 binop(Iop_Sub16, mkU16(0), a1) )));
705}
706
707static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000708 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000709 /* It's safe to duplicate a1 since it's only an atom */
710 return assignNew(mce, Ity_I32,
711 binop(Iop_Or32, a1,
712 assignNew(mce, Ity_I32,
713 /* unop(Iop_Neg32, a1)))); */
714 binop(Iop_Sub32, mkU32(0), a1) )));
715}
716
717/* --------- 'Improvement' functions for AND/OR. --------- */
718
719/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
720 defined (0); all other -> undefined (1).
721*/
722static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
723{
sewardj69f9e3e2004-12-30 02:05:34 +0000724 tl_assert(isOriginalAtom(mce, data));
725 tl_assert(isShadowAtom(mce, vbits));
726 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000727 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
728}
729
sewardj3598ef92004-11-11 02:13:30 +0000730static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
731{
sewardj69f9e3e2004-12-30 02:05:34 +0000732 tl_assert(isOriginalAtom(mce, data));
733 tl_assert(isShadowAtom(mce, vbits));
734 tl_assert(sameKindedAtoms(data, vbits));
sewardj3598ef92004-11-11 02:13:30 +0000735 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
736}
737
sewardjde8a5ae2004-11-06 14:20:54 +0000738static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
739{
sewardj69f9e3e2004-12-30 02:05:34 +0000740 tl_assert(isOriginalAtom(mce, data));
741 tl_assert(isShadowAtom(mce, vbits));
742 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000743 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
744}
745
sewardj69f9e3e2004-12-30 02:05:34 +0000746static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
747{
748 tl_assert(isOriginalAtom(mce, data));
749 tl_assert(isShadowAtom(mce, vbits));
750 tl_assert(sameKindedAtoms(data, vbits));
751 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
752}
753
754static IRAtom* mkImproveAND128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
755{
756 tl_assert(isOriginalAtom(mce, data));
757 tl_assert(isShadowAtom(mce, vbits));
758 tl_assert(sameKindedAtoms(data, vbits));
759 return assignNew(mce, Ity_V128, binop(Iop_Or128, data, vbits));
760}
761
sewardjde8a5ae2004-11-06 14:20:54 +0000762/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
763 defined (0); all other -> undefined (1).
764*/
765static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
766{
sewardj69f9e3e2004-12-30 02:05:34 +0000767 tl_assert(isOriginalAtom(mce, data));
768 tl_assert(isShadowAtom(mce, vbits));
769 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000770 return assignNew(
771 mce, Ity_I8,
772 binop(Iop_Or8,
773 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
774 vbits) );
775}
776
777static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
778{
sewardj69f9e3e2004-12-30 02:05:34 +0000779 tl_assert(isOriginalAtom(mce, data));
780 tl_assert(isShadowAtom(mce, vbits));
781 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000782 return assignNew(
783 mce, Ity_I16,
784 binop(Iop_Or16,
785 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
786 vbits) );
787}
788
789static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
790{
sewardj69f9e3e2004-12-30 02:05:34 +0000791 tl_assert(isOriginalAtom(mce, data));
792 tl_assert(isShadowAtom(mce, vbits));
793 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000794 return assignNew(
795 mce, Ity_I32,
796 binop(Iop_Or32,
797 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
798 vbits) );
799}
800
sewardj69f9e3e2004-12-30 02:05:34 +0000801static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
802{
803 tl_assert(isOriginalAtom(mce, data));
804 tl_assert(isShadowAtom(mce, vbits));
805 tl_assert(sameKindedAtoms(data, vbits));
806 return assignNew(
807 mce, Ity_I64,
808 binop(Iop_Or64,
809 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
810 vbits) );
811}
812
813static IRAtom* mkImproveOR128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
814{
815 tl_assert(isOriginalAtom(mce, data));
816 tl_assert(isShadowAtom(mce, vbits));
817 tl_assert(sameKindedAtoms(data, vbits));
818 return assignNew(
819 mce, Ity_V128,
820 binop(Iop_Or128,
821 assignNew(mce, Ity_V128, unop(Iop_Not128, data)),
822 vbits) );
823}
824
sewardjde8a5ae2004-11-06 14:20:54 +0000825/* --------- Pessimising casts. --------- */
826
827static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
828{
sewardj8fc93742004-11-22 11:29:33 +0000829 IRType ty;
830 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000831 /* Note, dst_ty is a shadow type, not an original type. */
832 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000833 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000834 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
835 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000836 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000837 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000838 tmp1 = vbits;
839 break;
840 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000841 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000842 break;
843 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000844 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000845 break;
846 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000847 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000848 break;
849 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000850 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000851 break;
852 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000853 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000854 }
sewardj69f9e3e2004-12-30 02:05:34 +0000855 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000856 /* Now widen up to the dst type. */
857 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000858 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000859 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000860 case Ity_I8:
861 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000862 case Ity_I16:
863 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
864 case Ity_I32:
865 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
866 case Ity_I64:
867 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000868 case Ity_V128:
869 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
870 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLto128, tmp1, tmp1));
871 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000872 default:
873 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000874 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +0000875 }
876}
877
878
879/*------------------------------------------------------------*/
880/*--- Emit a test and complaint if something is undefined. ---*/
881/*------------------------------------------------------------*/
882
883/* Set the annotations on a dirty helper to indicate that the stack
884 pointer and instruction pointers might be read. This is the
885 behaviour of all 'emit-a-complaint' style functions we might
886 call. */
887
888static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
889 di->nFxState = 2;
890 di->fxState[0].fx = Ifx_Read;
891 di->fxState[0].offset = mce->layout->offset_SP;
892 di->fxState[0].size = mce->layout->sizeof_SP;
893 di->fxState[1].fx = Ifx_Read;
894 di->fxState[1].offset = mce->layout->offset_IP;
895 di->fxState[1].size = mce->layout->sizeof_IP;
896}
897
898
899/* Check the supplied **original** atom for undefinedness, and emit a
900 complaint if so. Once that happens, mark it as defined. This is
901 possible because the atom is either a tmp or literal. If it's a
902 tmp, it will be shadowed by a tmp, and so we can set the shadow to
903 be defined. In fact as mentioned above, we will have to allocate a
904 new tmp to carry the new 'defined' shadow value, and update the
905 original->tmp mapping accordingly; we cannot simply assign a new
906 value to an existing shadow tmp as this breaks SSAness -- resulting
907 in the post-instrumentation sanity checker spluttering in disapproval.
908*/
909static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
910{
sewardj8fc93742004-11-22 11:29:33 +0000911 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +0000912 IRType ty;
913 Int sz;
sewardj8fc93742004-11-22 11:29:33 +0000914 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +0000915 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +0000916
sewardjde8a5ae2004-11-06 14:20:54 +0000917 /* Since the original expression is atomic, there's no duplicated
918 work generated by making multiple V-expressions for it. So we
919 don't really care about the possibility that someone else may
920 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +0000921 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +0000922 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +0000923 tl_assert(isShadowAtom(mce, vatom));
924 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +0000925
sewardj8fc93742004-11-22 11:29:33 +0000926 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +0000927
928 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +0000929 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +0000930
sewardj8fc93742004-11-22 11:29:33 +0000931 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +0000932 /* cond will be 0 if all defined, and 1 if any not defined. */
933
sewardj3598ef92004-11-11 02:13:30 +0000934 switch (sz) {
935 case 0:
936 di = unsafeIRDirty_0_N( 0/*regparms*/,
937 "MC_(helperc_value_check0_fail)",
938 &MC_(helperc_value_check0_fail),
939 mkIRExprVec_0()
940 );
941 break;
942 case 1:
943 di = unsafeIRDirty_0_N( 0/*regparms*/,
944 "MC_(helperc_value_check1_fail)",
945 &MC_(helperc_value_check1_fail),
946 mkIRExprVec_0()
947 );
948 break;
949 case 4:
950 di = unsafeIRDirty_0_N( 0/*regparms*/,
951 "MC_(helperc_value_check4_fail)",
952 &MC_(helperc_value_check4_fail),
953 mkIRExprVec_0()
954 );
955 break;
956 default:
957 di = unsafeIRDirty_0_N( 1/*regparms*/,
958 "MC_(helperc_complain_undef)",
959 &MC_(helperc_complain_undef),
960 mkIRExprVec_1( mkIRExpr_HWord( sz ))
961 );
962 break;
963 }
sewardjde8a5ae2004-11-06 14:20:54 +0000964 di->guard = cond;
965 setHelperAnns( mce, di );
966 stmt( mce->bb, IRStmt_Dirty(di));
967
968 /* Set the shadow tmp to be defined. First, update the
969 orig->shadow tmp mapping to reflect the fact that this shadow is
970 getting a new value. */
sewardj69f9e3e2004-12-30 02:05:34 +0000971 tl_assert(isAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +0000972 /* sameKindedAtoms ... */
973 if (vatom->tag == Iex_Tmp) {
sewardj69f9e3e2004-12-30 02:05:34 +0000974 tl_assert(atom->tag == Iex_Tmp);
sewardjde8a5ae2004-11-06 14:20:54 +0000975 newShadowTmp(mce, atom->Iex.Tmp.tmp);
976 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
977 definedOfType(ty));
978 }
979}
980
981
982/*------------------------------------------------------------*/
983/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
984/*------------------------------------------------------------*/
985
986/* Examine the always-defined sections declared in layout to see if
987 the (offset,size) section is within one. Note, is is an error to
988 partially fall into such a region: (offset,size) should either be
989 completely in such a region or completely not-in such a region.
990*/
991static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
992{
993 Int minoffD, maxoffD, i;
994 Int minoff = offset;
995 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +0000996 tl_assert((minoff & ~0xFFFF) == 0);
997 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +0000998
999 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1000 minoffD = mce->layout->alwaysDefd[i].offset;
1001 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001002 tl_assert((minoffD & ~0xFFFF) == 0);
1003 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001004
1005 if (maxoff < minoffD || maxoffD < minoff)
1006 continue; /* no overlap */
1007 if (minoff >= minoffD && maxoff <= maxoffD)
1008 return True; /* completely contained in an always-defd section */
1009
sewardj69f9e3e2004-12-30 02:05:34 +00001010 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001011 }
1012 return False; /* could not find any containing section */
1013}
1014
1015
1016/* Generate into bb suitable actions to shadow this Put. If the state
1017 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001018 supplied V bits to the shadow state. We can pass in either an
1019 original atom or a V-atom, but not both. In the former case the
1020 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001021*/
1022static
sewardj3598ef92004-11-11 02:13:30 +00001023void do_shadow_PUT ( MCEnv* mce, Int offset,
1024 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001025{
sewardj8fc93742004-11-22 11:29:33 +00001026 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001027 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001028 tl_assert(!vatom);
1029 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001030 vatom = expr2vbits( mce, atom );
1031 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001032 tl_assert(vatom);
1033 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001034 }
1035
sewardj8fc93742004-11-22 11:29:33 +00001036 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001037 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001038 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1039 /* later: no ... */
1040 /* emit code to emit a complaint if any of the vbits are 1. */
1041 /* complainIfUndefined(mce, atom); */
1042 } else {
1043 /* Do a plain shadow Put. */
1044 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1045 }
1046}
1047
1048
1049/* Return an expression which contains the V bits corresponding to the
1050 given GETI (passed in in pieces).
1051*/
1052static
1053void do_shadow_PUTI ( MCEnv* mce,
1054 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
1055{
sewardj8fc93742004-11-22 11:29:33 +00001056 IRAtom* vatom;
1057 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001058 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001059
sewardj69f9e3e2004-12-30 02:05:34 +00001060 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001061 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001062 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001063 ty = descr->elemTy;
1064 tyS = shadowType(ty);
1065 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001066 tl_assert(ty != Ity_I1);
1067 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001068 complainIfUndefined(mce,ix);
1069 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1070 /* later: no ... */
1071 /* emit code to emit a complaint if any of the vbits are 1. */
1072 /* complainIfUndefined(mce, atom); */
1073 } else {
1074 /* Do a cloned version of the Put that refers to the shadow
1075 area. */
1076 IRArray* new_descr
1077 = mkIRArray( descr->base + mce->layout->total_sizeB,
1078 tyS, descr->nElems);
1079 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1080 }
1081}
1082
1083
1084/* Return an expression which contains the V bits corresponding to the
1085 given GET (passed in in pieces).
1086*/
1087static
1088IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1089{
1090 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001091 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001092 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1093 /* Always defined, return all zeroes of the relevant type */
1094 return definedOfType(tyS);
1095 } else {
1096 /* return a cloned version of the Get that refers to the shadow
1097 area. */
1098 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1099 }
1100}
1101
1102
1103/* Return an expression which contains the V bits corresponding to the
1104 given GETI (passed in in pieces).
1105*/
1106static
1107IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
1108{
1109 IRType ty = descr->elemTy;
1110 IRType tyS = shadowType(ty);
1111 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001112 tl_assert(ty != Ity_I1);
1113 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001114 complainIfUndefined(mce,ix);
1115 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1116 /* Always defined, return all zeroes of the relevant type */
1117 return definedOfType(tyS);
1118 } else {
1119 /* return a cloned version of the Get that refers to the shadow
1120 area. */
1121 IRArray* new_descr
1122 = mkIRArray( descr->base + mce->layout->total_sizeB,
1123 tyS, descr->nElems);
1124 return IRExpr_GetI( new_descr, ix, bias );
1125 }
1126}
1127
1128
1129/*------------------------------------------------------------*/
1130/*--- Generating approximations for unknown operations, ---*/
1131/*--- using lazy-propagate semantics ---*/
1132/*------------------------------------------------------------*/
1133
1134/* Lazy propagation of undefinedness from two values, resulting in the
1135 specified shadow type.
1136*/
1137static
1138IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1139{
1140 /* force everything via 32-bit intermediaries. */
1141 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001142 tl_assert(isShadowAtom(mce,va1));
1143 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001144 at = mkPCastTo(mce, Ity_I32, va1);
1145 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1146 at = mkPCastTo(mce, finalVty, at);
1147 return at;
1148}
1149
1150
1151/* Do the lazy propagation game from a null-terminated vector of
1152 atoms. This is presumably the arguments to a helper call, so the
1153 IRCallee info is also supplied in order that we can know which
1154 arguments should be ignored (via the .mcx_mask field).
1155*/
1156static
1157IRAtom* mkLazyN ( MCEnv* mce,
1158 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1159{
1160 Int i;
1161 IRAtom* here;
1162 IRAtom* curr = definedOfType(Ity_I32);
1163 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001164 tl_assert(i < 32);
1165 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001166 /* Only take notice of this arg if the callee's mc-exclusion
1167 mask does not say it is to be excluded. */
1168 if (cee->mcx_mask & (1<<i)) {
1169 /* the arg is to be excluded from definedness checking. Do
1170 nothing. */
1171 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1172 } else {
1173 /* calculate the arg's definedness, and pessimistically merge
1174 it in. */
1175 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1176 curr = mkUifU32(mce, here, curr);
1177 }
1178 }
1179 return mkPCastTo(mce, finalVtype, curr );
1180}
1181
1182
1183/*------------------------------------------------------------*/
1184/*--- Generating expensive sequences for exact carry-chain ---*/
1185/*--- propagation in add/sub and related operations. ---*/
1186/*------------------------------------------------------------*/
1187
1188static
1189IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1190 IRAtom* aa, IRAtom* bb )
1191{
sewardj69f9e3e2004-12-30 02:05:34 +00001192 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001193 IRType ty;
1194 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001195
sewardj69f9e3e2004-12-30 02:05:34 +00001196 tl_assert(isShadowAtom(mce,qaa));
1197 tl_assert(isShadowAtom(mce,qbb));
1198 tl_assert(isOriginalAtom(mce,aa));
1199 tl_assert(isOriginalAtom(mce,bb));
1200 tl_assert(sameKindedAtoms(qaa,aa));
1201 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001202
sewardj8fc93742004-11-22 11:29:33 +00001203 ty = Ity_I32;
1204 opAND = Iop_And32;
1205 opOR = Iop_Or32;
1206 opXOR = Iop_Xor32;
1207 opNOT = Iop_Not32;
1208 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001209
1210 // a_min = aa & ~qaa
1211 a_min = assignNew(mce,ty,
1212 binop(opAND, aa,
1213 assignNew(mce,ty, unop(opNOT, qaa))));
1214
1215 // b_min = bb & ~qbb
1216 b_min = assignNew(mce,ty,
1217 binop(opAND, bb,
1218 assignNew(mce,ty, unop(opNOT, qbb))));
1219
1220 // a_max = aa | qaa
1221 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1222
1223 // b_max = bb | qbb
1224 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1225
1226 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1227 return
1228 assignNew(mce,ty,
1229 binop( opOR,
1230 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1231 assignNew(mce,ty,
1232 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1233 assignNew(mce,ty, binop(opADD, a_max, b_max))
1234 )
1235 )
1236 )
1237 );
1238}
1239
1240
1241/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001242/*--- Helpers for dealing with vector primops. ---*/
1243/*------------------------------------------------------------*/
1244
1245/* Vector pessimisation -- pessimise within each lane individually. */
1246
1247static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1248{
1249 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1250}
1251
1252static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1253{
1254 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1255}
1256
1257static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1258{
1259 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1260}
1261
1262static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1263{
1264 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1265}
1266
1267
1268/* Here's a simple scheme capable of handling ops derived from SSE1
1269 code and while only generating ops that can be efficiently
1270 implemented in SSE1. */
1271
1272/* All-lanes versions are straightforward:
1273
1274 binary32Fx4(x,y) ==> PCast32x4(UifU128(x#,y#))
1275
1276 unary32Fx4(x,y) ==> PCast32x4(x#)
1277
1278 Lowest-lane-only versions are more complex:
1279
1280 binary32F0x4(x,y) ==> Set128lo32(
1281 x#,
1282 PCast32(128to32(UifU128(x#,y#)))
1283 )
1284
1285 This is perhaps not so obvious. In particular, it's faster to
1286 do a 128-bit UifU and then take the bottom 32 bits than the more
1287 obvious scheme of taking the bottom 32 bits of each operand
1288 and doing a 32-bit UifU. Basically since UifU is fast and
1289 chopping lanes off vector values is slow.
1290
1291 Finally:
1292
1293 unary32F0x4(x) ==> Set128lo32(
1294 x#,
1295 PCast32(128to32(x#))
1296 )
1297
1298 Where:
1299
1300 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1301 PCast32x4(v#) = CmpNEZ32x4(v#)
1302*/
1303
1304static
1305IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1306{
1307 IRAtom* at;
1308 tl_assert(isShadowAtom(mce, vatomX));
1309 tl_assert(isShadowAtom(mce, vatomY));
1310 at = mkUifU128(mce, vatomX, vatomY);
1311 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1312 return at;
1313}
1314
1315static
1316IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1317{
1318 IRAtom* at;
1319 tl_assert(isShadowAtom(mce, vatomX));
1320 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1321 return at;
1322}
1323
1324static
1325IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1326{
1327 IRAtom* at;
1328 tl_assert(isShadowAtom(mce, vatomX));
1329 tl_assert(isShadowAtom(mce, vatomY));
1330 at = mkUifU128(mce, vatomX, vatomY);
1331 at = assignNew(mce, Ity_I32, unop(Iop_128to32, at));
1332 at = mkPCastTo(mce, Ity_I32, at);
1333 at = assignNew(mce, Ity_V128, binop(Iop_Set128lo32, vatomX, at));
1334 return at;
1335}
1336
1337static
1338IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1339{
1340 IRAtom* at;
1341 tl_assert(isShadowAtom(mce, vatomX));
1342 at = assignNew(mce, Ity_I32, unop(Iop_128to32, vatomX));
1343 at = mkPCastTo(mce, Ity_I32, at);
1344 at = assignNew(mce, Ity_V128, binop(Iop_Set128lo32, vatomX, at));
1345 return at;
1346}
1347
1348/* --- ... and ... 64Fx2 versions of the same ... --- */
1349
1350static
1351IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1352{
1353 IRAtom* at;
1354 tl_assert(isShadowAtom(mce, vatomX));
1355 tl_assert(isShadowAtom(mce, vatomY));
1356 at = mkUifU128(mce, vatomX, vatomY);
1357 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1358 return at;
1359}
1360
1361static
1362IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1363{
1364 IRAtom* at;
1365 tl_assert(isShadowAtom(mce, vatomX));
1366 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1367 return at;
1368}
1369
1370static
1371IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1372{
1373 IRAtom* at;
1374 tl_assert(isShadowAtom(mce, vatomX));
1375 tl_assert(isShadowAtom(mce, vatomY));
1376 at = mkUifU128(mce, vatomX, vatomY);
1377 at = assignNew(mce, Ity_I64, unop(Iop_128to64, at));
1378 at = mkPCastTo(mce, Ity_I64, at);
1379 at = assignNew(mce, Ity_V128, binop(Iop_Set128lo64, vatomX, at));
1380 return at;
1381}
1382
1383static
1384IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1385{
1386 IRAtom* at;
1387 tl_assert(isShadowAtom(mce, vatomX));
1388 at = assignNew(mce, Ity_I64, unop(Iop_128to64, vatomX));
1389 at = mkPCastTo(mce, Ity_I64, at);
1390 at = assignNew(mce, Ity_V128, binop(Iop_Set128lo64, vatomX, at));
1391 return at;
1392}
1393
1394/* --- --- Vector saturated narrowing --- --- */
1395
1396/* This is quite subtle. What to do is simple:
1397
1398 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1399
1400 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1401
1402 Why this is right is not so simple. Consider a lane in the args,
1403 vatom1 or 2, doesn't matter.
1404
1405 After the PCast, that lane is all 0s (defined) or all
1406 1s(undefined).
1407
1408 Both signed and unsigned saturating narrowing of all 0s produces
1409 all 0s, which is what we want.
1410
1411 The all-1s case is more complex. Unsigned narrowing interprets an
1412 all-1s input as the largest unsigned integer, and so produces all
1413 1s as a result since that is the largest unsigned value at the
1414 smaller width.
1415
1416 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1417 to -1, so we still wind up with all 1s at the smaller width.
1418
1419 So: In short, pessimise the args, then apply the original narrowing
1420 op.
1421*/
1422static
1423IRAtom* vectorNarrow128 ( MCEnv* mce, IROp narrow_op,
1424 IRAtom* vatom1, IRAtom* vatom2)
1425{
1426 IRAtom *at1, *at2, *at3;
1427 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1428 switch (narrow_op) {
1429 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1430 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1431 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
1432 default: VG_(tool_panic)("vectorNarrow128");
1433 }
1434 tl_assert(isShadowAtom(mce,vatom1));
1435 tl_assert(isShadowAtom(mce,vatom2));
1436 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1437 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1438 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1439 return at3;
1440}
1441
1442
1443/* --- --- Vector integer arithmetic --- --- */
1444
1445/* Simple ... UifU the args and per-lane pessimise the results. */
1446static
1447IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1448{
1449 IRAtom* at;
1450 at = mkUifU128(mce, vatom1, vatom2);
1451 at = mkPCast8x16(mce, at);
1452 return at;
1453}
1454
1455static
1456IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1457{
1458 IRAtom* at;
1459 at = mkUifU128(mce, vatom1, vatom2);
1460 at = mkPCast16x8(mce, at);
1461 return at;
1462}
1463
1464static
1465IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1466{
1467 IRAtom* at;
1468 at = mkUifU128(mce, vatom1, vatom2);
1469 at = mkPCast32x4(mce, at);
1470 return at;
1471}
1472
1473static
1474IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1475{
1476 IRAtom* at;
1477 at = mkUifU128(mce, vatom1, vatom2);
1478 at = mkPCast64x2(mce, at);
1479 return at;
1480}
1481
1482
1483/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001484/*--- Generate shadow values from all kinds of IRExprs. ---*/
1485/*------------------------------------------------------------*/
1486
1487static
1488IRAtom* expr2vbits_Binop ( MCEnv* mce,
1489 IROp op,
1490 IRAtom* atom1, IRAtom* atom2 )
1491{
1492 IRType and_or_ty;
1493 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1494 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1495 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1496
1497 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1498 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1499
sewardj69f9e3e2004-12-30 02:05:34 +00001500 tl_assert(isOriginalAtom(mce,atom1));
1501 tl_assert(isOriginalAtom(mce,atom2));
1502 tl_assert(isShadowAtom(mce,vatom1));
1503 tl_assert(isShadowAtom(mce,vatom2));
1504 tl_assert(sameKindedAtoms(atom1,vatom1));
1505 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001506 switch (op) {
1507
sewardj69f9e3e2004-12-30 02:05:34 +00001508 /* 128-bit SIMD (SSE2-esque) */
1509
1510 case Iop_ShrN16x8:
1511 case Iop_ShrN32x4:
1512 case Iop_ShrN64x2:
1513 case Iop_SarN16x8:
1514 case Iop_SarN32x4:
1515 case Iop_ShlN16x8:
1516 case Iop_ShlN32x4:
1517 case Iop_ShlN64x2:
1518 /* Same scheme as with all other shifts. */
1519 complainIfUndefined(mce, atom2);
1520 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1521
1522 case Iop_QSub8Ux16:
1523 case Iop_QSub8Sx16:
1524 case Iop_Sub8x16:
1525 case Iop_Min8Ux16:
1526 case Iop_Max8Ux16:
1527 case Iop_CmpGT8Sx16:
1528 case Iop_CmpEQ8x16:
1529 case Iop_Avg8Ux16:
1530 case Iop_QAdd8Ux16:
1531 case Iop_QAdd8Sx16:
1532 case Iop_Add8x16:
1533 return binary8Ix16(mce, vatom1, vatom2);
1534
1535 case Iop_QSub16Ux8:
1536 case Iop_QSub16Sx8:
1537 case Iop_Sub16x8:
1538 case Iop_Mul16x8:
1539 case Iop_MulHi16Sx8:
1540 case Iop_MulHi16Ux8:
1541 case Iop_Min16Sx8:
1542 case Iop_Max16Sx8:
1543 case Iop_CmpGT16Sx8:
1544 case Iop_CmpEQ16x8:
1545 case Iop_Avg16Ux8:
1546 case Iop_QAdd16Ux8:
1547 case Iop_QAdd16Sx8:
1548 case Iop_Add16x8:
1549 return binary16Ix8(mce, vatom1, vatom2);
1550
1551 case Iop_Sub32x4:
1552 case Iop_CmpGT32Sx4:
1553 case Iop_CmpEQ32x4:
1554 case Iop_Add32x4:
1555 return binary32Ix4(mce, vatom1, vatom2);
1556
1557 case Iop_Sub64x2:
1558 case Iop_Add64x2:
1559 return binary64Ix2(mce, vatom1, vatom2);
1560
1561 case Iop_QNarrow32Sx4:
1562 case Iop_QNarrow16Sx8:
1563 case Iop_QNarrow16Ux8:
1564 return vectorNarrow128(mce, op, vatom1, vatom2);
1565
1566 case Iop_Sub64Fx2:
1567 case Iop_Mul64Fx2:
1568 case Iop_Min64Fx2:
1569 case Iop_Max64Fx2:
1570 case Iop_Div64Fx2:
1571 case Iop_CmpLT64Fx2:
1572 case Iop_CmpLE64Fx2:
1573 case Iop_CmpEQ64Fx2:
1574 case Iop_Add64Fx2:
1575 return binary64Fx2(mce, vatom1, vatom2);
1576
1577 case Iop_Sub64F0x2:
1578 case Iop_Mul64F0x2:
1579 case Iop_Min64F0x2:
1580 case Iop_Max64F0x2:
1581 case Iop_Div64F0x2:
1582 case Iop_CmpLT64F0x2:
1583 case Iop_CmpLE64F0x2:
1584 case Iop_CmpEQ64F0x2:
1585 case Iop_Add64F0x2:
1586 return binary64F0x2(mce, vatom1, vatom2);
1587
1588 /* 128-bit SIMD (SSE1-esque) */
1589
1590 case Iop_Sub32Fx4:
1591 case Iop_Mul32Fx4:
1592 case Iop_Min32Fx4:
1593 case Iop_Max32Fx4:
1594 case Iop_Div32Fx4:
1595 case Iop_CmpLT32Fx4:
1596 case Iop_CmpLE32Fx4:
1597 case Iop_CmpEQ32Fx4:
1598 case Iop_Add32Fx4:
1599 return binary32Fx4(mce, vatom1, vatom2);
1600
1601 case Iop_Sub32F0x4:
1602 case Iop_Mul32F0x4:
1603 case Iop_Min32F0x4:
1604 case Iop_Max32F0x4:
1605 case Iop_Div32F0x4:
1606 case Iop_CmpLT32F0x4:
1607 case Iop_CmpLE32F0x4:
1608 case Iop_CmpEQ32F0x4:
1609 case Iop_Add32F0x4:
1610 return binary32F0x4(mce, vatom1, vatom2);
1611
1612 /* 128-bit data-steering */
1613 case Iop_Set128lo32:
1614 case Iop_Set128lo64:
1615 case Iop_64HLto128:
1616 case Iop_InterleaveLO64x2:
1617 case Iop_InterleaveLO32x4:
1618 case Iop_InterleaveLO16x8:
1619 case Iop_InterleaveLO8x16:
1620 case Iop_InterleaveHI64x2:
1621 case Iop_InterleaveHI32x4:
1622 case Iop_InterleaveHI16x8:
1623 case Iop_InterleaveHI8x16:
1624 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1625
1626 /* Scalar floating point */
1627
sewardj3598ef92004-11-11 02:13:30 +00001628 case Iop_RoundF64:
1629 case Iop_F64toI64:
sewardj69f9e3e2004-12-30 02:05:34 +00001630 case Iop_I64toF64:
1631 /* First arg is I32 (rounding mode), second is F64 or I64
1632 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001633 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1634
1635 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1636 /* Takes two F64 args. */
sewardjde8a5ae2004-11-06 14:20:54 +00001637 case Iop_F64toI32:
sewardj69f9e3e2004-12-30 02:05:34 +00001638 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001639 /* First arg is I32 (rounding mode), second is F64 (data). */
1640 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1641
1642 case Iop_F64toI16:
1643 /* First arg is I32 (rounding mode), second is F64 (data). */
1644 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1645
sewardj3598ef92004-11-11 02:13:30 +00001646 case Iop_ScaleF64:
1647 case Iop_Yl2xF64:
1648 case Iop_Yl2xp1F64:
1649 case Iop_PRemF64:
1650 case Iop_AtanF64:
1651 case Iop_AddF64:
1652 case Iop_DivF64:
1653 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001654 case Iop_MulF64:
1655 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1656
sewardj3598ef92004-11-11 02:13:30 +00001657 case Iop_CmpF64:
1658 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1659
sewardjde8a5ae2004-11-06 14:20:54 +00001660 /* non-FP after here */
1661
1662 case Iop_DivModU64to32:
1663 case Iop_DivModS64to32:
1664 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1665
sewardj3598ef92004-11-11 02:13:30 +00001666 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001667 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001668 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001669 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001670
1671 case Iop_MullS32:
1672 case Iop_MullU32: {
1673 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1674 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1675 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1676 }
1677
sewardj3598ef92004-11-11 02:13:30 +00001678 case Iop_MullS16:
1679 case Iop_MullU16: {
1680 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1681 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1682 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1683 }
1684
1685 case Iop_MullS8:
1686 case Iop_MullU8: {
1687 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1688 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1689 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1690 }
1691
sewardjde8a5ae2004-11-06 14:20:54 +00001692 case Iop_Add32:
1693# if 0
1694 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1695# endif
1696 case Iop_Sub32:
1697 case Iop_Mul32:
1698 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1699
sewardj3598ef92004-11-11 02:13:30 +00001700 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001701 case Iop_Add16:
1702 case Iop_Sub16:
1703 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1704
1705 case Iop_Sub8:
1706 case Iop_Add8:
1707 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1708
1709 case Iop_CmpLE32S: case Iop_CmpLE32U:
1710 case Iop_CmpLT32U: case Iop_CmpLT32S:
1711 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001712 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001713
sewardj3598ef92004-11-11 02:13:30 +00001714 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001715 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001716
1717 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001718 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001719
1720 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1721 /* Complain if the shift amount is undefined. Then simply
1722 shift the first arg's V bits by the real shift amount. */
1723 complainIfUndefined(mce, atom2);
1724 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1725
sewardj69f9e3e2004-12-30 02:05:34 +00001726 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001727 /* Same scheme as with 32-bit shifts. */
1728 complainIfUndefined(mce, atom2);
1729 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1730
sewardj3598ef92004-11-11 02:13:30 +00001731 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001732 /* Same scheme as with 32-bit shifts. */
1733 complainIfUndefined(mce, atom2);
1734 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1735
1736 case Iop_Shl64: case Iop_Shr64:
1737 /* Same scheme as with 32-bit shifts. */
1738 complainIfUndefined(mce, atom2);
1739 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1740
sewardj69f9e3e2004-12-30 02:05:34 +00001741 case Iop_And128:
1742 uifu = mkUifU128; difd = mkDifD128;
1743 and_or_ty = Ity_V128; improve = mkImproveAND128; goto do_And_Or;
1744 case Iop_And64:
1745 uifu = mkUifU64; difd = mkDifD64;
1746 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001747 case Iop_And32:
1748 uifu = mkUifU32; difd = mkDifD32;
1749 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001750 case Iop_And16:
1751 uifu = mkUifU16; difd = mkDifD16;
1752 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001753 case Iop_And8:
1754 uifu = mkUifU8; difd = mkDifD8;
1755 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1756
sewardj69f9e3e2004-12-30 02:05:34 +00001757 case Iop_Or128:
1758 uifu = mkUifU128; difd = mkDifD128;
1759 and_or_ty = Ity_V128; improve = mkImproveOR128; goto do_And_Or;
1760 case Iop_Or64:
1761 uifu = mkUifU64; difd = mkDifD64;
1762 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001763 case Iop_Or32:
1764 uifu = mkUifU32; difd = mkDifD32;
1765 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1766 case Iop_Or16:
1767 uifu = mkUifU16; difd = mkDifD16;
1768 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1769 case Iop_Or8:
1770 uifu = mkUifU8; difd = mkDifD8;
1771 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1772
1773 do_And_Or:
1774 return
1775 assignNew(
1776 mce,
1777 and_or_ty,
1778 difd(mce, uifu(mce, vatom1, vatom2),
1779 difd(mce, improve(mce, atom1, vatom1),
1780 improve(mce, atom2, vatom2) ) ) );
1781
1782 case Iop_Xor8:
1783 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001784 case Iop_Xor16:
1785 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001786 case Iop_Xor32:
1787 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001788 case Iop_Xor64:
1789 return mkUifU64(mce, vatom1, vatom2);
1790 case Iop_Xor128:
1791 return mkUifU128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001792
1793 default:
1794 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001795 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001796 }
1797}
1798
1799
1800static
1801IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1802{
1803 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001804 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001805 switch (op) {
1806
sewardj69f9e3e2004-12-30 02:05:34 +00001807 case Iop_Sqrt64Fx2:
1808 return unary64Fx2(mce, vatom);
1809
1810 case Iop_Sqrt64F0x2:
1811 return unary64F0x2(mce, vatom);
1812
1813 case Iop_Sqrt32Fx4:
1814 case Iop_RSqrt32Fx4:
1815 case Iop_Recip32Fx4:
1816 return unary32Fx4(mce, vatom);
1817
1818 case Iop_Sqrt32F0x4:
1819 case Iop_RSqrt32F0x4:
1820 case Iop_Recip32F0x4:
1821 return unary32F0x4(mce, vatom);
1822
1823 case Iop_32Uto128:
1824 case Iop_64Uto128:
1825 return assignNew(mce, Ity_V128, unop(op, vatom));
1826
sewardjde8a5ae2004-11-06 14:20:54 +00001827 case Iop_F32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001828 case Iop_I32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001829 case Iop_NegF64:
1830 case Iop_SinF64:
1831 case Iop_CosF64:
1832 case Iop_TanF64:
1833 case Iop_SqrtF64:
1834 case Iop_AbsF64:
1835 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001836 return mkPCastTo(mce, Ity_I64, vatom);
1837
sewardj3598ef92004-11-11 02:13:30 +00001838 case Iop_Clz32:
1839 case Iop_Ctz32:
1840 return mkPCastTo(mce, Ity_I32, vatom);
1841
1842 case Iop_32Sto64:
1843 case Iop_32Uto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001844 case Iop_128to64:
1845 case Iop_128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001846 return assignNew(mce, Ity_I64, unop(op, vatom));
1847
sewardjde8a5ae2004-11-06 14:20:54 +00001848 case Iop_64to32:
1849 case Iop_64HIto32:
1850 case Iop_1Uto32:
1851 case Iop_8Uto32:
1852 case Iop_16Uto32:
1853 case Iop_16Sto32:
1854 case Iop_8Sto32:
1855 return assignNew(mce, Ity_I32, unop(op, vatom));
1856
1857 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001858 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001859 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001860 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001861 return assignNew(mce, Ity_I16, unop(op, vatom));
1862
1863 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001864 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001865 case Iop_32to8:
1866 return assignNew(mce, Ity_I8, unop(op, vatom));
1867
1868 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001869 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001870
sewardj3598ef92004-11-11 02:13:30 +00001871 case Iop_ReinterpF64asI64:
1872 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001873 case Iop_ReinterpI32asF32:
1874 case Iop_Not128:
1875 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00001876 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001877 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001878 case Iop_Not8:
1879 case Iop_Not1:
1880 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001881
sewardjde8a5ae2004-11-06 14:20:54 +00001882 default:
1883 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001884 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00001885 }
1886}
1887
1888
sewardj69f9e3e2004-12-30 02:05:34 +00001889/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00001890static
sewardj69f9e3e2004-12-30 02:05:34 +00001891IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001892{
1893 void* helper;
1894 Char* hname;
1895 IRDirty* di;
1896 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00001897 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001898
sewardj69f9e3e2004-12-30 02:05:34 +00001899 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00001900
1901 /* First, emit a definedness test for the address. This also sets
1902 the address (shadow) to 'defined' following the test. */
1903 complainIfUndefined( mce, addr );
1904
1905 /* Now cook up a call to the relevant helper function, to read the
1906 data V bits from shadow memory. */
1907 ty = shadowType(ty);
1908 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001909 case Ity_I64: helper = &MC_(helperc_LOADV8);
1910 hname = "MC_(helperc_LOADV8)";
1911 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001912 case Ity_I32: helper = &MC_(helperc_LOADV4);
1913 hname = "MC_(helperc_LOADV4)";
1914 break;
1915 case Ity_I16: helper = &MC_(helperc_LOADV2);
1916 hname = "MC_(helperc_LOADV2)";
1917 break;
1918 case Ity_I8: helper = &MC_(helperc_LOADV1);
1919 hname = "MC_(helperc_LOADV1)";
1920 break;
1921 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001922 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00001923 }
1924
sewardj3598ef92004-11-11 02:13:30 +00001925 /* Generate the actual address into addrAct. */
1926 if (bias == 0) {
1927 addrAct = addr;
1928 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001929 IROp mkAdd;
1930 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00001931 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00001932 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
1933 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1934 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00001935 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1936 }
1937
sewardjde8a5ae2004-11-06 14:20:54 +00001938 /* We need to have a place to park the V bits we're just about to
1939 read. */
1940 datavbits = newIRTemp(mce->bb->tyenv, ty);
1941 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00001942 1/*regparms*/, hname, helper,
1943 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00001944 setHelperAnns( mce, di );
1945 stmt( mce->bb, IRStmt_Dirty(di) );
1946
1947 return mkexpr(datavbits);
1948}
1949
1950
1951static
sewardj69f9e3e2004-12-30 02:05:34 +00001952IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
1953{
1954 IRAtom *v64hi, *v64lo;
1955 switch (shadowType(ty)) {
1956 case Ity_I8:
1957 case Ity_I16:
1958 case Ity_I32:
1959 case Ity_I64:
1960 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
1961 case Ity_V128:
1962 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
1963 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
1964 return assignNew( mce,
1965 Ity_V128,
1966 binop(Iop_64HLto128, v64hi, v64lo));
1967 default:
1968 VG_(tool_panic)("expr2vbits_LDle");
1969 }
1970}
1971
1972
1973static
sewardjde8a5ae2004-11-06 14:20:54 +00001974IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00001975 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00001976{
1977 IRAtom *vbitsC, *vbits0, *vbitsX;
1978 IRType ty;
1979 /* Given Mux0X(cond,expr0,exprX), generate
1980 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
1981 That is, steer the V bits like the originals, but trash the
1982 result if the steering value is undefined. This gives
1983 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00001984 tl_assert(isOriginalAtom(mce, cond));
1985 tl_assert(isOriginalAtom(mce, expr0));
1986 tl_assert(isOriginalAtom(mce, exprX));
sewardjde8a5ae2004-11-06 14:20:54 +00001987
1988 vbitsC = expr2vbits(mce, cond);
1989 vbits0 = expr2vbits(mce, expr0);
1990 vbitsX = expr2vbits(mce, exprX);
1991 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
1992
1993 return
1994 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
1995 mkPCastTo(mce, ty, vbitsC) );
1996}
1997
1998/* --------- This is the main expression-handling function. --------- */
1999
2000static
2001IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2002{
2003 switch (e->tag) {
2004
2005 case Iex_Get:
2006 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2007
2008 case Iex_GetI:
2009 return shadow_GETI( mce, e->Iex.GetI.descr,
2010 e->Iex.GetI.ix, e->Iex.GetI.bias );
2011
2012 case Iex_Tmp:
2013 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
2014
2015 case Iex_Const:
2016 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2017
2018 case Iex_Binop:
2019 return expr2vbits_Binop(
2020 mce,
2021 e->Iex.Binop.op,
2022 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2023 );
2024
2025 case Iex_Unop:
2026 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2027
2028 case Iex_LDle:
sewardj3598ef92004-11-11 02:13:30 +00002029 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
2030 e->Iex.LDle.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002031
2032 case Iex_CCall:
2033 return mkLazyN( mce, e->Iex.CCall.args,
2034 e->Iex.CCall.retty,
2035 e->Iex.CCall.cee );
2036
2037 case Iex_Mux0X:
2038 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2039 e->Iex.Mux0X.exprX);
2040
2041 default:
2042 VG_(printf)("\n");
2043 ppIRExpr(e);
2044 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002045 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002046 }
2047}
2048
2049/*------------------------------------------------------------*/
2050/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2051/*------------------------------------------------------------*/
2052
2053/* Widen a value to the host word size. */
2054
2055static
2056IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2057{
sewardj69f9e3e2004-12-30 02:05:34 +00002058 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002059
sewardj8fc93742004-11-22 11:29:33 +00002060 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002061 tl_assert(isShadowAtom(mce,vatom));
2062
2063 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2064 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002065
sewardjde8a5ae2004-11-06 14:20:54 +00002066 if (tyH == Ity_I32) {
2067 switch (ty) {
2068 case Ity_I32: return vatom;
2069 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2070 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2071 default: goto unhandled;
2072 }
2073 } else {
2074 goto unhandled;
2075 }
2076 unhandled:
2077 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002078 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002079}
2080
2081
sewardj3598ef92004-11-11 02:13:30 +00002082/* Generate a shadow store. addr is always the original address atom.
2083 You can pass in either originals or V-bits for the data atom, but
2084 obviously not both. */
2085
sewardjde8a5ae2004-11-06 14:20:54 +00002086static
sewardj3598ef92004-11-11 02:13:30 +00002087void do_shadow_STle ( MCEnv* mce,
2088 IRAtom* addr, UInt bias,
2089 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002090{
sewardj69f9e3e2004-12-30 02:05:34 +00002091 IROp mkAdd;
2092 IRType ty, tyAddr;
2093 IRDirty *di, *diLo64, *diHi64;
2094 IRAtom *addrAct, *addrLo64, *addrHi64;
2095 IRAtom *vdataLo64, *vdataHi64;
2096 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002097 void* helper = NULL;
2098 Char* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002099
2100 tyAddr = mce->hWordTy;
2101 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2102 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2103
2104 di = diLo64 = diHi64 = NULL;
2105 eBias = eBias0 = eBias8 = NULL;
2106 addrAct = addrLo64 = addrHi64 = NULL;
2107 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002108
sewardj3598ef92004-11-11 02:13:30 +00002109 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002110 tl_assert(!vdata);
2111 tl_assert(isOriginalAtom(mce, data));
2112 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002113 vdata = expr2vbits( mce, data );
2114 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002115 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002116 }
sewardjde8a5ae2004-11-06 14:20:54 +00002117
sewardj69f9e3e2004-12-30 02:05:34 +00002118 tl_assert(isOriginalAtom(mce,addr));
2119 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002120
2121 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002122
2123 /* First, emit a definedness test for the address. This also sets
2124 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002125 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002126
sewardj69f9e3e2004-12-30 02:05:34 +00002127 /* Now decide which helper function to call to write the data V
2128 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002129 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002130 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002131 case Ity_I64: helper = &MC_(helperc_STOREV8);
2132 hname = "MC_(helperc_STOREV8)";
2133 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002134 case Ity_I32: helper = &MC_(helperc_STOREV4);
2135 hname = "MC_(helperc_STOREV4)";
2136 break;
2137 case Ity_I16: helper = &MC_(helperc_STOREV2);
2138 hname = "MC_(helperc_STOREV2)";
2139 break;
2140 case Ity_I8: helper = &MC_(helperc_STOREV1);
2141 hname = "MC_(helperc_STOREV1)";
2142 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002143 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002144 }
2145
sewardj69f9e3e2004-12-30 02:05:34 +00002146 if (ty == Ity_V128) {
2147
2148 /* 128-bit case */
2149 /* See comment in next clause re 64-bit regparms */
2150 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2151 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
2152 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_128to64, vdata));
2153 diLo64 = unsafeIRDirty_0_N(
2154 1/*regparms*/, hname, helper,
2155 mkIRExprVec_2( addrLo64, vdataLo64 ));
2156
2157 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2158 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
2159 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_128HIto64, vdata));
2160 diHi64 = unsafeIRDirty_0_N(
2161 1/*regparms*/, hname, helper,
2162 mkIRExprVec_2( addrHi64, vdataHi64 ));
2163
2164 setHelperAnns( mce, diLo64 );
2165 setHelperAnns( mce, diHi64 );
2166 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2167 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2168
sewardj3598ef92004-11-11 02:13:30 +00002169 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002170
2171 /* 8/16/32/64-bit cases */
2172 /* Generate the actual address into addrAct. */
2173 if (bias == 0) {
2174 addrAct = addr;
2175 } else {
2176 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2177 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2178 }
2179
2180 if (ty == Ity_I64) {
2181 /* We can't do this with regparm 2 on 32-bit platforms, since
2182 the back ends aren't clever enough to handle 64-bit
2183 regparm args. Therefore be different. */
2184 di = unsafeIRDirty_0_N(
2185 1/*regparms*/, hname, helper,
2186 mkIRExprVec_2( addrAct, vdata ));
2187 } else {
2188 di = unsafeIRDirty_0_N(
2189 2/*regparms*/, hname, helper,
2190 mkIRExprVec_2( addrAct,
2191 zwidenToHostWord( mce, vdata )));
2192 }
2193 setHelperAnns( mce, di );
2194 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002195 }
2196
sewardjde8a5ae2004-11-06 14:20:54 +00002197}
2198
2199
sewardj3598ef92004-11-11 02:13:30 +00002200/* Do lazy pessimistic propagation through a dirty helper call, by
2201 looking at the annotations on it. This is the most complex part of
2202 Memcheck. */
2203
2204static IRType szToITy ( Int n )
2205{
2206 switch (n) {
2207 case 1: return Ity_I8;
2208 case 2: return Ity_I16;
2209 case 4: return Ity_I32;
2210 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002211 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002212 }
2213}
2214
2215static
2216void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2217{
sewardj69f9e3e2004-12-30 02:05:34 +00002218 Int i, n, offset, toDo, gSz, gOff;
2219 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002220 IRType tyAddr, tySrc, tyDst;
2221 IRTemp dst;
2222
2223 /* First check the guard. */
2224 complainIfUndefined(mce, d->guard);
2225
2226 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002227 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002228
2229 /* Inputs: unmasked args */
2230 for (i = 0; d->args[i]; i++) {
2231 if (d->cee->mcx_mask & (1<<i)) {
2232 /* ignore this arg */
2233 } else {
2234 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2235 curr = mkUifU32(mce, here, curr);
2236 }
2237 }
2238
2239 /* Inputs: guest state that we read. */
2240 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002241 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002242 if (d->fxState[i].fx == Ifx_Write)
2243 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002244
2245 /* Ignore any sections marked as 'always defined'. */
2246 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2247 if (0)
2248 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2249 d->fxState[i].offset, d->fxState[i].size );
2250 continue;
2251 }
2252
sewardj3598ef92004-11-11 02:13:30 +00002253 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002254 consider it. If larger than 8 bytes, deal with it in 8-byte
2255 chunks. */
2256 gSz = d->fxState[i].size;
2257 gOff = d->fxState[i].offset;
2258 tl_assert(gSz > 0);
2259 while (True) {
2260 if (gSz == 0) break;
2261 n = gSz <= 8 ? gSz : 8;
2262 /* update 'curr' with UifU of the state slice
2263 gOff .. gOff+n-1 */
2264 tySrc = szToITy( n );
2265 src = assignNew( mce, tySrc,
2266 shadow_GET(mce, gOff, tySrc ) );
2267 here = mkPCastTo( mce, Ity_I32, src );
2268 curr = mkUifU32(mce, here, curr);
2269 gSz -= n;
2270 gOff += n;
2271 }
2272
sewardj3598ef92004-11-11 02:13:30 +00002273 }
2274
2275 /* Inputs: memory. First set up some info needed regardless of
2276 whether we're doing reads or writes. */
2277 tyAddr = Ity_INVALID;
2278
2279 if (d->mFx != Ifx_None) {
2280 /* Because we may do multiple shadow loads/stores from the same
2281 base address, it's best to do a single test of its
2282 definedness right now. Post-instrumentation optimisation
2283 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002284 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002285 complainIfUndefined(mce, d->mAddr);
2286
2287 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002288 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2289 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002290 }
2291
2292 /* Deal with memory inputs (reads or modifies) */
2293 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2294 offset = 0;
2295 toDo = d->mSize;
2296 /* chew off 32-bit chunks */
2297 while (toDo >= 4) {
2298 here = mkPCastTo(
2299 mce, Ity_I32,
2300 expr2vbits_LDle ( mce, Ity_I32,
2301 d->mAddr, d->mSize - toDo )
2302 );
2303 curr = mkUifU32(mce, here, curr);
2304 toDo -= 4;
2305 }
2306 /* chew off 16-bit chunks */
2307 while (toDo >= 2) {
2308 here = mkPCastTo(
2309 mce, Ity_I32,
2310 expr2vbits_LDle ( mce, Ity_I16,
2311 d->mAddr, d->mSize - toDo )
2312 );
2313 curr = mkUifU32(mce, here, curr);
2314 toDo -= 2;
2315 }
sewardj69f9e3e2004-12-30 02:05:34 +00002316 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002317 }
2318
2319 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2320 all the inputs to the helper. Now we need to re-distribute the
2321 results to all destinations. */
2322
2323 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002324 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002325 dst = findShadowTmp(mce, d->tmp);
2326 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2327 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2328 }
2329
2330 /* Outputs: guest state that we write or modify. */
2331 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002332 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002333 if (d->fxState[i].fx == Ifx_Read)
2334 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002335 /* Ignore any sections marked as 'always defined'. */
2336 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2337 continue;
2338 /* This state element is written or modified. So we need to
2339 consider it. If larger than 8 bytes, deal with it in 8-byte
2340 chunks. */
2341 gSz = d->fxState[i].size;
2342 gOff = d->fxState[i].offset;
2343 tl_assert(gSz > 0);
2344 while (True) {
2345 if (gSz == 0) break;
2346 n = gSz <= 8 ? gSz : 8;
2347 /* Write suitably-casted 'curr' to the state slice
2348 gOff .. gOff+n-1 */
2349 tyDst = szToITy( n );
2350 do_shadow_PUT( mce, gOff,
2351 NULL, /* original atom */
2352 mkPCastTo( mce, tyDst, curr ) );
2353 gSz -= n;
2354 gOff += n;
2355 }
sewardj3598ef92004-11-11 02:13:30 +00002356 }
2357
2358 /* Outputs: memory that we write or modify. */
2359 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2360 offset = 0;
2361 toDo = d->mSize;
2362 /* chew off 32-bit chunks */
2363 while (toDo >= 4) {
2364 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2365 NULL, /* original data */
2366 mkPCastTo( mce, Ity_I32, curr ) );
2367 toDo -= 4;
2368 }
2369 /* chew off 16-bit chunks */
2370 while (toDo >= 2) {
2371 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2372 NULL, /* original data */
2373 mkPCastTo( mce, Ity_I16, curr ) );
2374 toDo -= 2;
2375 }
sewardj69f9e3e2004-12-30 02:05:34 +00002376 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002377 }
2378
2379}
2380
2381
sewardjde8a5ae2004-11-06 14:20:54 +00002382/*------------------------------------------------------------*/
2383/*--- Memcheck main ---*/
2384/*------------------------------------------------------------*/
2385
sewardj3598ef92004-11-11 02:13:30 +00002386#if 0 /* UNUSED */
2387static Bool isBogusAtom ( IRAtom* at )
2388{
2389 ULong n = 0;
2390 IRConst* con;
sewardj69f9e3e2004-12-30 02:05:34 +00002391 tl_assert(isAtom(at));
sewardj3598ef92004-11-11 02:13:30 +00002392 if (at->tag == Iex_Tmp)
2393 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002394 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002395 con = at->Iex.Const.con;
2396 switch (con->tag) {
2397 case Ico_U8: n = (ULong)con->Ico.U8; break;
2398 case Ico_U16: n = (ULong)con->Ico.U16; break;
2399 case Ico_U32: n = (ULong)con->Ico.U32; break;
2400 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002401 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002402 }
2403 /* VG_(printf)("%llx\n", n); */
2404 return (n == 0xFEFEFEFF
2405 || n == 0x80808080
2406 || n == 0x1010101
2407 || n == 1010100);
2408}
2409
2410static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2411{
2412 Int i;
2413 IRExpr* e;
2414 switch (st->tag) {
2415 case Ist_Tmp:
2416 e = st->Ist.Tmp.data;
2417 switch (e->tag) {
2418 case Iex_Get:
2419 case Iex_Tmp:
2420 return False;
2421 case Iex_Unop:
2422 return isBogusAtom(e->Iex.Unop.arg);
2423 case Iex_Binop:
2424 return isBogusAtom(e->Iex.Binop.arg1)
2425 || isBogusAtom(e->Iex.Binop.arg2);
2426 case Iex_Mux0X:
2427 return isBogusAtom(e->Iex.Mux0X.cond)
2428 || isBogusAtom(e->Iex.Mux0X.expr0)
2429 || isBogusAtom(e->Iex.Mux0X.exprX);
2430 case Iex_LDle:
2431 return isBogusAtom(e->Iex.LDle.addr);
2432 case Iex_CCall:
2433 for (i = 0; e->Iex.CCall.args[i]; i++)
2434 if (isBogusAtom(e->Iex.CCall.args[i]))
2435 return True;
2436 return False;
2437 default:
2438 goto unhandled;
2439 }
2440 case Ist_Put:
2441 return isBogusAtom(st->Ist.Put.data);
2442 case Ist_STle:
2443 return isBogusAtom(st->Ist.STle.addr)
2444 || isBogusAtom(st->Ist.STle.data);
2445 case Ist_Exit:
sewardj69f9e3e2004-12-30 02:05:34 +00002446 return isBogusAtom(st->Ist.Exit.cond);
sewardj3598ef92004-11-11 02:13:30 +00002447 default:
2448 unhandled:
2449 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002450 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002451 }
2452}
2453#endif /* UNUSED */
2454
2455
sewardjde8a5ae2004-11-06 14:20:54 +00002456IRBB* mc_instrument ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
2457{
sewardj3598ef92004-11-11 02:13:30 +00002458 Bool verboze = False; //True;
2459
2460 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002461
2462 Int i, j, first_stmt;
2463 IRStmt* st;
2464 MCEnv mce;
2465
2466 /* Set up BB */
2467 IRBB* bb = emptyIRBB();
2468 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
2469 bb->next = dopyIRExpr(bb_in->next);
2470 bb->jumpkind = bb_in->jumpkind;
2471
2472 /* Set up the running environment. Only .bb is modified as we go
2473 along. */
2474 mce.bb = bb;
2475 mce.layout = layout;
2476 mce.n_originalTmps = bb->tyenv->types_used;
2477 mce.hWordTy = hWordTy;
2478 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2479 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002480 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002481
2482 /* Iterate over the stmts. */
2483
2484 for (i = 0; i < bb_in->stmts_used; i++) {
2485 st = bb_in->stmts[i];
2486 if (!st) continue;
2487
sewardj69f9e3e2004-12-30 02:05:34 +00002488 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002489
2490 /*
2491 if (!hasBogusLiterals) {
2492 hasBogusLiterals = checkForBogusLiterals(st);
2493 if (hasBogusLiterals) {
2494 VG_(printf)("bogus: ");
2495 ppIRStmt(st);
2496 VG_(printf)("\n");
2497 }
2498 }
2499 */
sewardjde8a5ae2004-11-06 14:20:54 +00002500 first_stmt = bb->stmts_used;
2501
2502 if (verboze) {
2503 ppIRStmt(st);
2504 VG_(printf)("\n\n");
2505 }
2506
2507 switch (st->tag) {
2508
2509 case Ist_Tmp:
2510 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
2511 expr2vbits( &mce, st->Ist.Tmp.data) );
2512 break;
2513
2514 case Ist_Put:
2515 do_shadow_PUT( &mce,
2516 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002517 st->Ist.Put.data,
2518 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002519 break;
2520
2521 case Ist_PutI:
2522 do_shadow_PUTI( &mce,
2523 st->Ist.PutI.descr,
2524 st->Ist.PutI.ix,
2525 st->Ist.PutI.bias,
2526 st->Ist.PutI.data );
2527 break;
2528
2529 case Ist_STle:
sewardj3598ef92004-11-11 02:13:30 +00002530 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
2531 st->Ist.STle.data,
2532 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002533 break;
2534
2535 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002536 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002537 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002538 break;
2539
2540 case Ist_Dirty:
2541 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002542 break;
2543
2544 default:
2545 VG_(printf)("\n");
2546 ppIRStmt(st);
2547 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002548 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002549
2550 } /* switch (st->tag) */
2551
2552 if (verboze) {
2553 for (j = first_stmt; j < bb->stmts_used; j++) {
2554 VG_(printf)(" ");
2555 ppIRStmt(bb->stmts[j]);
2556 VG_(printf)("\n");
2557 }
2558 VG_(printf)("\n");
2559 }
2560
2561 addStmtToIRBB(bb, st);
2562
2563 }
2564
2565 /* Now we need to complain if the jump target is undefined. */
2566 first_stmt = bb->stmts_used;
2567
2568 if (verboze) {
2569 VG_(printf)("bb->next = ");
2570 ppIRExpr(bb->next);
2571 VG_(printf)("\n\n");
2572 }
2573
2574 complainIfUndefined( &mce, bb->next );
2575
2576 if (verboze) {
2577 for (j = first_stmt; j < bb->stmts_used; j++) {
2578 VG_(printf)(" ");
2579 ppIRStmt(bb->stmts[j]);
2580 VG_(printf)("\n");
2581 }
2582 VG_(printf)("\n");
2583 }
2584
2585 return bb;
2586}
2587
2588/*--------------------------------------------------------------------*/
2589/*--- end mc_translate.c ---*/
2590/*--------------------------------------------------------------------*/