blob: abb258e5199cc008398ae3353a8f061a0c4e0474 [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;
sewardjced9fe52004-07-07 11:55:36 +000063 Int orig_nbytes, trans_used, orig_used;
64 TranslateResult tres;
sewardjb5bf2e02004-10-25 13:06:17 +000065 VexControl vcon;
sewardjced9fe52004-07-07 11:55:36 +000066
67 if (argc != 2) {
68 fprintf(stderr, "usage: vex file.org\n");
69 exit(1);
70 }
71 f = fopen(argv[1], "r");
72 if (!f) {
73 fprintf(stderr, "can't open `%s'\n", argv[1]);
74 exit(1);
75 }
76
sewardjb5bf2e02004-10-25 13:06:17 +000077 /* Run with default params. However, we can't allow bb chasing
78 since that causes the front end to get segfaults when it tries
sewardj5bd4d162004-11-10 13:02:48 +000079 to read code outside the initial BB we hand it. So when calling
80 LibVEX_Translate, send in a chase-into predicate that always
81 returns False. */
sewardjb5bf2e02004-10-25 13:06:17 +000082 LibVEX_default_VexControl ( &vcon );
sewardjb4952402004-10-26 13:24:50 +000083 vcon.iropt_level = 2;
sewardjb5bf2e02004-10-25 13:06:17 +000084
sewardjced9fe52004-07-07 11:55:36 +000085 LibVEX_Init ( &failure_exit, &log_bytes,
sewardj1f40a0a2004-07-21 12:28:07 +000086 1, /* debug_paranoia */
sewardjabe017e2004-10-29 23:42:36 +000087 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +000088 &vcon );
sewardjced9fe52004-07-07 11:55:36 +000089
sewardjea64e142004-07-22 16:47:21 +000090
sewardjced9fe52004-07-07 11:55:36 +000091 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +000092
sewardjced9fe52004-07-07 11:55:36 +000093 fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +000094 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +000095 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +000096
97 if (n_bbs_done == TEST_N_BBS) break;
98 n_bbs_done++;
99
sewardjced9fe52004-07-07 11:55:36 +0000100 /* first line is: . bb-number bb-addr n-bytes */
101 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
102 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000103 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000104 assert(orig_nbytes >= 1);
105 assert(!feof(f));
106 fgets(linebuf, N_LINEBUF,f);
107 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000108
sewardjced9fe52004-07-07 11:55:36 +0000109 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000110 if (verbose)
sewardj4459baa2004-09-10 20:00:46 +0000111 printf("============ Basic Block %d, "
112 "Start %x, nbytes %2d ============",
sewardjabe017e2004-10-29 23:42:36 +0000113 n_bbs_done-1, orig_addr, orig_nbytes);
114
sewardjced9fe52004-07-07 11:55:36 +0000115 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
116 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000117 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
118 origbuf[i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000119 }
120
sewardjabe017e2004-10-29 23:42:36 +0000121 for (i = 0; i < TEST_N_ITERS; i++)
122 tres
123 = LibVEX_Translate (
sewardjc3263ee2004-12-29 17:48:22 +0000124 VexArchX86, VexSubArchX86_sse2,
125 VexArchX86, VexSubArchX86_sse2,
sewardj5bd4d162004-11-10 13:02:48 +0000126 origbuf, (Addr64)orig_addr, chase_into_not_ok,
127 &orig_used,
sewardjabe017e2004-10-29 23:42:36 +0000128 transbuf, N_TRANSBUF, &trans_used,
sewardj9e7448b2004-11-18 13:44:15 +0000129#if 1 /* no instrumentation */
130 NULL, /* instrument1 */
131 NULL, /* instrument2 */
132 False, /* cleanup after instrument */
133#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000134#if 0 /* addrcheck */
135 ac_instrument, /* instrument1 */
136 NULL, /* instrument2 */
137 False, /* cleanup after instrument */
138#endif
sewardj9e7448b2004-11-18 13:44:15 +0000139#if 0 /* memcheck */
sewardjde8a5ae2004-11-06 14:20:54 +0000140 mc_instrument, /* instrument1 */
141 NULL, /* instrument2 */
142 False, /* cleanup after instrument */
143#endif
sewardjabe017e2004-10-29 23:42:36 +0000144 NULL, /* access checker */
145 TEST_FLAGS
146 );
147
sewardj4459baa2004-09-10 20:00:46 +0000148 if (tres != TransOK)
149 printf("\ntres = %d\n", (Int)tres);
sewardjced9fe52004-07-07 11:55:36 +0000150 assert(tres == TransOK);
151 assert(orig_used == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000152
sewardj4459baa2004-09-10 20:00:46 +0000153 sum = 0;
154 for (i = 0; i < trans_used; i++)
155 sum += (UInt)transbuf[i];
156 printf ( " %6.2f ... %d\n", (double)trans_used / (double)orig_used, sum );
sewardjced9fe52004-07-07 11:55:36 +0000157 }
158
159 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000160 printf("\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000161 LibVEX_ClearTemporary(True);
sewardjced9fe52004-07-07 11:55:36 +0000162
sewardjce605f92004-07-05 14:39:15 +0000163 return 0;
164}
sewardj9b1004e2004-10-30 22:25:40 +0000165
166//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000167//////////////////////////////////////////////////////////////////////
168//////////////////////////////////////////////////////////////////////
169//////////////////////////////////////////////////////////////////////
170//////////////////////////////////////////////////////////////////////
171//////////////////////////////////////////////////////////////////////
172//////////////////////////////////////////////////////////////////////
173//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000174
175static
sewardjde8a5ae2004-11-06 14:20:54 +0000176__attribute((noreturn))
sewardj9b1004e2004-10-30 22:25:40 +0000177void panic ( Char* s )
178{
179 printf("\npanic: %s\n", s);
180 failure_exit();
181}
182
183static
sewardj9578a8b2004-11-04 19:44:48 +0000184IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000185{
186/* Use this rather than eg. -1 because it's a UInt. */
187#define INVALID_DATA_SIZE 999999
188
189 Int i;
190 Int sz;
191 IRCallee* helper;
192 IRStmt* st;
193 IRExpr* data;
194 IRExpr* addr;
195 Bool needSz;
196
197 /* Set up BB */
198 IRBB* bb = emptyIRBB();
199 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
200 bb->next = dopyIRExpr(bb_in->next);
201 bb->jumpkind = bb_in->jumpkind;
202
203 /* No loads to consider in ->next. */
204 assert(isAtom(bb_in->next));
205
206 for (i = 0; i < bb_in->stmts_used; i++) {
207 st = bb_in->stmts[i];
208 if (!st) continue;
209
210 switch (st->tag) {
211
212 case Ist_Tmp:
213 data = st->Ist.Tmp.data;
214 if (data->tag == Iex_LDle) {
215 addr = data->Iex.LDle.addr;
216 sz = sizeofIRType(data->Iex.LDle.ty);
217 needSz = False;
218 switch (sz) {
219 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000220 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000221 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000222 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000223 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000224 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000225 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000226 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000227 needSz = True; break;
228 }
229 if (needSz) {
230 addStmtToIRBB(
231 bb,
232 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000233 unsafeIRDirty_0_N( helper->regparms,
234 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000235 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
236 ));
237 } else {
238 addStmtToIRBB(
239 bb,
240 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000241 unsafeIRDirty_0_N( helper->regparms,
242 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000243 mkIRExprVec_1(addr) )
244 ));
245 }
246 }
247 break;
248
249 case Ist_STle:
250 data = st->Ist.STle.data;
251 addr = st->Ist.STle.addr;
252 assert(isAtom(data));
253 assert(isAtom(addr));
254 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
255 needSz = False;
256 switch (sz) {
257 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000258 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000259 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000260 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000261 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000262 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000263 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000264 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000265 needSz = True; break;
266 }
267 if (needSz) {
268 addStmtToIRBB(
269 bb,
270 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000271 unsafeIRDirty_0_N( helper->regparms,
272 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000273 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
274 ));
275 } else {
276 addStmtToIRBB(
277 bb,
278 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000279 unsafeIRDirty_0_N( helper->regparms,
280 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000281 mkIRExprVec_1(addr) )
282 ));
283 }
284 break;
285
286 case Ist_Put:
287 assert(isAtom(st->Ist.Put.data));
288 break;
289
290 case Ist_PutI:
sewardjeeac8412004-11-02 00:26:55 +0000291 assert(isAtom(st->Ist.PutI.ix));
sewardj9b1004e2004-10-30 22:25:40 +0000292 assert(isAtom(st->Ist.PutI.data));
293 break;
294
295 case Ist_Exit:
sewardj0276d4b2004-11-15 15:30:21 +0000296 assert(isAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000297 break;
298
299 case Ist_Dirty:
300 /* If the call doesn't interact with memory, we ain't
301 interested. */
302 if (st->Ist.Dirty.details->mFx == Ifx_None)
303 break;
304 goto unhandled;
305
306 default:
307 unhandled:
308 printf("\n");
309 ppIRStmt(st);
310 printf("\n");
311 panic("addrcheck: unhandled IRStmt");
312 }
313
314 addStmtToIRBB( bb, dopyIRStmt(st));
315 }
316
317 return bb;
318}
sewardjde8a5ae2004-11-06 14:20:54 +0000319
320//////////////////////////////////////////////////////////////////////
321//////////////////////////////////////////////////////////////////////
322//////////////////////////////////////////////////////////////////////
323//////////////////////////////////////////////////////////////////////
324//////////////////////////////////////////////////////////////////////
325//////////////////////////////////////////////////////////////////////
326//////////////////////////////////////////////////////////////////////
327//////////////////////////////////////////////////////////////////////
328
329#define sk_assert(xxx) assert(xxx)
330#define VG_(xxxx) xxxx
331#define skin_panic(zzz) panic(zzz)
332#define MC_(zzzz) MC_##zzzz
333#define SK_(zzzz) SK_##zzzz
334
335void MC_helperc_complain_undef ( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000336void MC_helperc_LOADV8 ( void ) { }
sewardjde8a5ae2004-11-06 14:20:54 +0000337void MC_helperc_LOADV4 ( void ) { }
338void MC_helperc_LOADV2 ( void ) { }
339void MC_helperc_LOADV1 ( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000340void MC_helperc_STOREV8( void ) { }
sewardjde8a5ae2004-11-06 14:20:54 +0000341void MC_helperc_STOREV4( void ) { }
342void MC_helperc_STOREV2( void ) { }
343void MC_helperc_STOREV1( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000344void MC_helperc_value_check0_fail( void ) { }
345void MC_helperc_value_check1_fail( void ) { }
346void MC_helperc_value_check4_fail( void ) { }
347
348
349
350/*--------------------------------------------------------------------*/
351/*--- Instrument IR to perform memory checking operations. ---*/
352/*--- mc_translate.c ---*/
353/*--------------------------------------------------------------------*/
354
355/*
356 This file is part of MemCheck, a heavyweight Valgrind tool for
357 detecting memory errors.
358
359 Copyright (C) 2000-2004 Julian Seward
360 jseward@acm.org
361
362 This program is free software; you can redistribute it and/or
363 modify it under the terms of the GNU General Public License as
364 published by the Free Software Foundation; either version 2 of the
365 License, or (at your option) any later version.
366
367 This program is distributed in the hope that it will be useful, but
368 WITHOUT ANY WARRANTY; without even the implied warranty of
369 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
370 General Public License for more details.
371
372 You should have received a copy of the GNU General Public License
373 along with this program; if not, write to the Free Software
374 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
375 02111-1307, USA.
376
377 The GNU General Public License is contained in the file COPYING.
378*/
379
380//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000381
382
383/*------------------------------------------------------------*/
384/*--- Forward decls ---*/
385/*------------------------------------------------------------*/
386
387struct _MCEnv;
388
389static IRType shadowType ( IRType ty );
390static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
391
392
393/*------------------------------------------------------------*/
394/*--- Memcheck running state, and tmp management. ---*/
395/*------------------------------------------------------------*/
396
397/* Carries around state during memcheck instrumentation. */
398typedef
399 struct _MCEnv {
400 /* MODIFIED: the bb being constructed. IRStmts are added. */
401 IRBB* bb;
402
403 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
404 original temps to their current their current shadow temp.
405 Initially all entries are IRTemp_INVALID. Entries are added
406 lazily since many original temps are not used due to
407 optimisation prior to instrumentation. Note that floating
408 point original tmps are shadowed by integer tmps of the same
409 size, and Bit-typed original tmps are shadowed by the type
410 Ity_I8. See comment below. */
411 IRTemp* tmpMap;
412 Int n_originalTmps; /* for range checking */
413
414 /* READONLY: the guest layout. This indicates which parts of
415 the guest state should be regarded as 'always defined'. */
416 VexGuestLayout* layout;
417 /* READONLY: the host word type. Needed for constructing
418 arguments of type 'HWord' to be passed to helper functions.
419 Ity_I32 or Ity_I64 only. */
420 IRType hWordTy;
421 }
422 MCEnv;
423
424/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
425 demand), as they are encountered. This is for two reasons.
426
427 (1) (less important reason): Many original tmps are unused due to
428 initial IR optimisation, and we do not want to spaces in tables
429 tracking them.
430
431 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
432 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj92d168d2004-11-15 14:22:12 +0000433 each original tmp, or IRTemp_INVALID if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000434 It is necessary to support making multiple assignments to a shadow
435 -- specifically, after testing a shadow for definedness, it needs
436 to be made defined. But IR's SSA property disallows this.
437
438 (2) (more important reason): Therefore, when a shadow needs to get
439 a new value, a new temporary is created, the value is assigned to
440 that, and the tmpMap is updated to reflect the new binding.
441
442 A corollary is that if the tmpMap maps a given tmp to
sewardj92d168d2004-11-15 14:22:12 +0000443 IRTemp_INVALID and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000444 there's a read-before-write error in the original tmps. The IR
445 sanity checker should catch all such anomalies, however.
446*/
447
448/* Find the tmp currently shadowing the given original tmp. If none
449 so far exists, allocate one. */
450static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
451{
452 sk_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000453 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000454 mce->tmpMap[orig]
455 = newIRTemp(mce->bb->tyenv,
456 shadowType(mce->bb->tyenv->types[orig]));
457 }
458 return mce->tmpMap[orig];
459}
460
461/* Allocate a new shadow for the given original tmp. This means any
462 previous shadow is abandoned. This is needed because it is
463 necessary to give a new value to a shadow once it has been tested
464 for undefinedness, but unfortunately IR's SSA property disallows
465 this. Instead we must abandon the old shadow, allocate a new one
466 and use that instead. */
467static void newShadowTmp ( MCEnv* mce, IRTemp orig )
468{
469 sk_assert(orig < mce->n_originalTmps);
470 mce->tmpMap[orig]
471 = newIRTemp(mce->bb->tyenv,
472 shadowType(mce->bb->tyenv->types[orig]));
473}
474
475
476/*------------------------------------------------------------*/
477/*--- IRAtoms -- a subset of IRExprs ---*/
478/*------------------------------------------------------------*/
479
480/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
481 isAtom() in libvex_ir.h. Because this instrumenter expects flat
482 input, most of this code deals in atoms. Usefully, a value atom
483 always has a V-value which is also an atom: constants are shadowed
484 by constants, and temps are shadowed by the corresponding shadow
485 temporary. */
486
487typedef IRExpr IRAtom;
488
489/* (used for sanity checks only): is this an atom which looks
490 like it's from original code? */
491static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
492{
493 if (a1->tag == Iex_Const)
494 return True;
495 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
496 return True;
497 return False;
498}
499
500/* (used for sanity checks only): is this an atom which looks
501 like it's from shadow code? */
502static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
503{
504 if (a1->tag == Iex_Const)
505 return True;
506 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
507 return True;
508 return False;
509}
510
511/* (used for sanity checks only): check that both args are atoms and
512 are identically-kinded. */
513static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
514{
515 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
516 return True;
517 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
518 return True;
519 return False;
520}
521
522
523/*------------------------------------------------------------*/
524/*--- Type management ---*/
525/*------------------------------------------------------------*/
526
527/* Shadow state is always accessed using integer types. This returns
528 an integer type with the same size (as per sizeofIRType) as the
529 given type. The only valid shadow types are Bit, I8, I16, I32,
530 I64. */
531
532static IRType shadowType ( IRType ty )
533{
534 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000535 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000536 case Ity_I8:
537 case Ity_I16:
538 case Ity_I32:
539 case Ity_I64: return ty;
540 case Ity_F32: return Ity_I32;
541 case Ity_F64: return Ity_I64;
542 default: ppIRType(ty);
543 VG_(skin_panic)("memcheck:shadowType");
544 }
545}
546
547/* Produce a 'defined' value of the given shadow type. Should only be
548 supplied shadow types (Bit/I8/I16/I32/UI64). */
549static IRExpr* definedOfType ( IRType ty ) {
550 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000551 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
sewardjde8a5ae2004-11-06 14:20:54 +0000552 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
553 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
554 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
555 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
556 default: VG_(skin_panic)("memcheck:definedOfType");
557 }
558}
559
560
561/*------------------------------------------------------------*/
562/*--- Constructing IR fragments ---*/
563/*------------------------------------------------------------*/
564
565/* assign value to tmp */
566#define assign(_bb,_tmp,_expr) \
567 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
568
569/* add stmt to a bb */
570#define stmt(_bb,_stmt) \
571 addStmtToIRBB((_bb), (_stmt))
572
573/* build various kinds of expressions */
574#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
575#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
576#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
577#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
578#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
579#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
580#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
581
582/* bind the given expression to a new temporary, and return the
583 temporary. This effectively converts an arbitrary expression into
584 an atom. */
585static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
586 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
587 assign(mce->bb, t, e);
588 return mkexpr(t);
589}
590
591
592/*------------------------------------------------------------*/
593/*--- Constructing definedness primitive ops ---*/
594/*------------------------------------------------------------*/
595
596/* --------- Defined-if-either-defined --------- */
597
598static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
599 sk_assert(isShadowAtom(mce,a1));
600 sk_assert(isShadowAtom(mce,a2));
601 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
602}
603
604static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
605 sk_assert(isShadowAtom(mce,a1));
606 sk_assert(isShadowAtom(mce,a2));
607 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
608}
609
610static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
611 sk_assert(isShadowAtom(mce,a1));
612 sk_assert(isShadowAtom(mce,a2));
613 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
614}
615
616/* --------- Undefined-if-either-undefined --------- */
617
618static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
619 sk_assert(isShadowAtom(mce,a1));
620 sk_assert(isShadowAtom(mce,a2));
621 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
622}
623
624static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
625 sk_assert(isShadowAtom(mce,a1));
626 sk_assert(isShadowAtom(mce,a2));
627 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
628}
629
630static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
631 sk_assert(isShadowAtom(mce,a1));
632 sk_assert(isShadowAtom(mce,a2));
633 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
634}
635
636static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
637 sk_assert(isShadowAtom(mce,a1));
638 sk_assert(isShadowAtom(mce,a2));
639 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
640}
641
642static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
643 switch (vty) {
sewardj3598ef92004-11-11 02:13:30 +0000644 case Ity_I16: return mkUifU16(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000645 case Ity_I32: return mkUifU32(mce, a1, a2);
646 case Ity_I64: return mkUifU64(mce, a1, a2);
647 default:
648 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
649 VG_(skin_panic)("memcheck:mkUifU");
650 }
651}
652
653/* --------- The Left-family of operations. --------- */
654
655static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
656 sk_assert(isShadowAtom(mce,a1));
657 /* It's safe to duplicate a1 since it's only an atom */
658 return assignNew(mce, Ity_I8,
659 binop(Iop_Or8, a1,
660 assignNew(mce, Ity_I8,
661 /* unop(Iop_Neg8, a1)))); */
662 binop(Iop_Sub8, mkU8(0), a1) )));
663}
664
665static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
666 sk_assert(isShadowAtom(mce,a1));
667 /* It's safe to duplicate a1 since it's only an atom */
668 return assignNew(mce, Ity_I16,
669 binop(Iop_Or16, a1,
670 assignNew(mce, Ity_I16,
671 /* unop(Iop_Neg16, a1)))); */
672 binop(Iop_Sub16, mkU16(0), a1) )));
673}
674
675static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
676 sk_assert(isShadowAtom(mce,a1));
677 /* It's safe to duplicate a1 since it's only an atom */
678 return assignNew(mce, Ity_I32,
679 binop(Iop_Or32, a1,
680 assignNew(mce, Ity_I32,
681 /* unop(Iop_Neg32, a1)))); */
682 binop(Iop_Sub32, mkU32(0), a1) )));
683}
684
685/* --------- 'Improvement' functions for AND/OR. --------- */
686
687/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
688 defined (0); all other -> undefined (1).
689*/
690static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
691{
692 sk_assert(isOriginalAtom(mce, data));
693 sk_assert(isShadowAtom(mce, vbits));
694 sk_assert(sameKindedAtoms(data, vbits));
695 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
696}
697
sewardj3598ef92004-11-11 02:13:30 +0000698static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
699{
700 sk_assert(isOriginalAtom(mce, data));
701 sk_assert(isShadowAtom(mce, vbits));
702 sk_assert(sameKindedAtoms(data, vbits));
703 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
704}
705
sewardjde8a5ae2004-11-06 14:20:54 +0000706static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
707{
708 sk_assert(isOriginalAtom(mce, data));
709 sk_assert(isShadowAtom(mce, vbits));
710 sk_assert(sameKindedAtoms(data, vbits));
711 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
712}
713
714/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
715 defined (0); all other -> undefined (1).
716*/
717static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
718{
719 sk_assert(isOriginalAtom(mce, data));
720 sk_assert(isShadowAtom(mce, vbits));
721 sk_assert(sameKindedAtoms(data, vbits));
722 return assignNew(
723 mce, Ity_I8,
724 binop(Iop_Or8,
725 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
726 vbits) );
727}
728
729static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
730{
731 sk_assert(isOriginalAtom(mce, data));
732 sk_assert(isShadowAtom(mce, vbits));
733 sk_assert(sameKindedAtoms(data, vbits));
734 return assignNew(
735 mce, Ity_I16,
736 binop(Iop_Or16,
737 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
738 vbits) );
739}
740
741static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
742{
743 sk_assert(isOriginalAtom(mce, data));
744 sk_assert(isShadowAtom(mce, vbits));
745 sk_assert(sameKindedAtoms(data, vbits));
746 return assignNew(
747 mce, Ity_I32,
748 binop(Iop_Or32,
749 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
750 vbits) );
751}
752
753/* --------- Pessimising casts. --------- */
754
755static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
756{
sewardj8fc93742004-11-22 11:29:33 +0000757 IRType ty;
758 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000759 /* Note, dst_ty is a shadow type, not an original type. */
760 /* First of all, collapse vbits down to a single bit. */
761 sk_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000762 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
763 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000764 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000765 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000766 tmp1 = vbits;
767 break;
768 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000769 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000770 break;
771 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000772 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000773 break;
774 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000775 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000776 break;
777 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000778 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000779 break;
780 default:
781 VG_(skin_panic)("mkPCastTo(1)");
782 }
783 sk_assert(tmp1);
784 /* Now widen up to the dst type. */
785 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000786 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000787 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000788 case Ity_I8:
789 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000790 case Ity_I16:
791 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
792 case Ity_I32:
793 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
794 case Ity_I64:
795 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
796 default:
797 ppIRType(dst_ty);
798 VG_(skin_panic)("mkPCastTo(2)");
799 }
800}
801
802
803/*------------------------------------------------------------*/
804/*--- Emit a test and complaint if something is undefined. ---*/
805/*------------------------------------------------------------*/
806
807/* Set the annotations on a dirty helper to indicate that the stack
808 pointer and instruction pointers might be read. This is the
809 behaviour of all 'emit-a-complaint' style functions we might
810 call. */
811
812static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
813 di->nFxState = 2;
814 di->fxState[0].fx = Ifx_Read;
815 di->fxState[0].offset = mce->layout->offset_SP;
816 di->fxState[0].size = mce->layout->sizeof_SP;
817 di->fxState[1].fx = Ifx_Read;
818 di->fxState[1].offset = mce->layout->offset_IP;
819 di->fxState[1].size = mce->layout->sizeof_IP;
820}
821
822
823/* Check the supplied **original** atom for undefinedness, and emit a
824 complaint if so. Once that happens, mark it as defined. This is
825 possible because the atom is either a tmp or literal. If it's a
826 tmp, it will be shadowed by a tmp, and so we can set the shadow to
827 be defined. In fact as mentioned above, we will have to allocate a
828 new tmp to carry the new 'defined' shadow value, and update the
829 original->tmp mapping accordingly; we cannot simply assign a new
830 value to an existing shadow tmp as this breaks SSAness -- resulting
831 in the post-instrumentation sanity checker spluttering in disapproval.
832*/
833static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
834{
sewardj8fc93742004-11-22 11:29:33 +0000835 Int sz;
836 IRType ty;
837 IRAtom* vatom;
838 IRAtom* cond;
839 IRDirty* di;
840
sewardjde8a5ae2004-11-06 14:20:54 +0000841 /* Since the original expression is atomic, there's no duplicated
842 work generated by making multiple V-expressions for it. So we
843 don't really care about the possibility that someone else may
844 also create a V-interpretion for it. */
845 sk_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +0000846 vatom = expr2vbits( mce, atom );
sewardjde8a5ae2004-11-06 14:20:54 +0000847 sk_assert(isShadowAtom(mce, vatom));
848 sk_assert(sameKindedAtoms(atom, vatom));
849
sewardj8fc93742004-11-22 11:29:33 +0000850 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +0000851
852 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +0000853 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +0000854
sewardj8fc93742004-11-22 11:29:33 +0000855 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +0000856 /* cond will be 0 if all defined, and 1 if any not defined. */
857
sewardj3598ef92004-11-11 02:13:30 +0000858 switch (sz) {
859 case 0:
860 di = unsafeIRDirty_0_N( 0/*regparms*/,
861 "MC_(helperc_value_check0_fail)",
862 &MC_(helperc_value_check0_fail),
863 mkIRExprVec_0()
864 );
865 break;
866 case 1:
867 di = unsafeIRDirty_0_N( 0/*regparms*/,
868 "MC_(helperc_value_check1_fail)",
869 &MC_(helperc_value_check1_fail),
870 mkIRExprVec_0()
871 );
872 break;
873 case 4:
874 di = unsafeIRDirty_0_N( 0/*regparms*/,
875 "MC_(helperc_value_check4_fail)",
876 &MC_(helperc_value_check4_fail),
877 mkIRExprVec_0()
878 );
879 break;
880 default:
881 di = unsafeIRDirty_0_N( 1/*regparms*/,
882 "MC_(helperc_complain_undef)",
883 &MC_(helperc_complain_undef),
884 mkIRExprVec_1( mkIRExpr_HWord( sz ))
885 );
886 break;
887 }
sewardjde8a5ae2004-11-06 14:20:54 +0000888 di->guard = cond;
889 setHelperAnns( mce, di );
890 stmt( mce->bb, IRStmt_Dirty(di));
891
892 /* Set the shadow tmp to be defined. First, update the
893 orig->shadow tmp mapping to reflect the fact that this shadow is
894 getting a new value. */
895 sk_assert(isAtom(vatom));
896 /* sameKindedAtoms ... */
897 if (vatom->tag == Iex_Tmp) {
898 sk_assert(atom->tag == Iex_Tmp);
899 newShadowTmp(mce, atom->Iex.Tmp.tmp);
900 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
901 definedOfType(ty));
902 }
903}
904
905
906/*------------------------------------------------------------*/
907/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
908/*------------------------------------------------------------*/
909
910/* Examine the always-defined sections declared in layout to see if
911 the (offset,size) section is within one. Note, is is an error to
912 partially fall into such a region: (offset,size) should either be
913 completely in such a region or completely not-in such a region.
914*/
915static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
916{
917 Int minoffD, maxoffD, i;
918 Int minoff = offset;
919 Int maxoff = minoff + size - 1;
920 sk_assert((minoff & ~0xFFFF) == 0);
921 sk_assert((maxoff & ~0xFFFF) == 0);
922
923 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
924 minoffD = mce->layout->alwaysDefd[i].offset;
925 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
926 sk_assert((minoffD & ~0xFFFF) == 0);
927 sk_assert((maxoffD & ~0xFFFF) == 0);
928
929 if (maxoff < minoffD || maxoffD < minoff)
930 continue; /* no overlap */
931 if (minoff >= minoffD && maxoff <= maxoffD)
932 return True; /* completely contained in an always-defd section */
933
934 VG_(skin_panic)("memcheck:isAlwaysDefd:partial overlap");
935 }
936 return False; /* could not find any containing section */
937}
938
939
940/* Generate into bb suitable actions to shadow this Put. If the state
941 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +0000942 supplied V bits to the shadow state. We can pass in either an
943 original atom or a V-atom, but not both. In the former case the
944 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +0000945*/
946static
sewardj3598ef92004-11-11 02:13:30 +0000947void do_shadow_PUT ( MCEnv* mce, Int offset,
948 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +0000949{
sewardj8fc93742004-11-22 11:29:33 +0000950 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +0000951 if (atom) {
952 sk_assert(!vatom);
953 sk_assert(isOriginalAtom(mce, atom));
954 vatom = expr2vbits( mce, atom );
955 } else {
956 sk_assert(vatom);
957 sk_assert(isShadowAtom(mce, vatom));
958 }
959
sewardj8fc93742004-11-22 11:29:33 +0000960 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjba999312004-11-15 15:21:17 +0000961 sk_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +0000962 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
963 /* later: no ... */
964 /* emit code to emit a complaint if any of the vbits are 1. */
965 /* complainIfUndefined(mce, atom); */
966 } else {
967 /* Do a plain shadow Put. */
968 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
969 }
970}
971
972
973/* Return an expression which contains the V bits corresponding to the
974 given GETI (passed in in pieces).
975*/
976static
977void do_shadow_PUTI ( MCEnv* mce,
978 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
979{
sewardj8fc93742004-11-22 11:29:33 +0000980 IRAtom* vatom;
981 IRType ty, tyS;
982 Int arrSize;
983
sewardjde8a5ae2004-11-06 14:20:54 +0000984 sk_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +0000985 vatom = expr2vbits( mce, atom );
sewardjde8a5ae2004-11-06 14:20:54 +0000986 sk_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +0000987 ty = descr->elemTy;
988 tyS = shadowType(ty);
989 arrSize = descr->nElems * sizeofIRType(ty);
sewardjba999312004-11-15 15:21:17 +0000990 sk_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +0000991 sk_assert(isOriginalAtom(mce,ix));
992 complainIfUndefined(mce,ix);
993 if (isAlwaysDefd(mce, descr->base, arrSize)) {
994 /* later: no ... */
995 /* emit code to emit a complaint if any of the vbits are 1. */
996 /* complainIfUndefined(mce, atom); */
997 } else {
998 /* Do a cloned version of the Put that refers to the shadow
999 area. */
1000 IRArray* new_descr
1001 = mkIRArray( descr->base + mce->layout->total_sizeB,
1002 tyS, descr->nElems);
1003 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1004 }
1005}
1006
1007
1008/* Return an expression which contains the V bits corresponding to the
1009 given GET (passed in in pieces).
1010*/
1011static
1012IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1013{
1014 IRType tyS = shadowType(ty);
sewardjba999312004-11-15 15:21:17 +00001015 sk_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001016 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1017 /* Always defined, return all zeroes of the relevant type */
1018 return definedOfType(tyS);
1019 } else {
1020 /* return a cloned version of the Get that refers to the shadow
1021 area. */
1022 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1023 }
1024}
1025
1026
1027/* Return an expression which contains the V bits corresponding to the
1028 given GETI (passed in in pieces).
1029*/
1030static
1031IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
1032{
1033 IRType ty = descr->elemTy;
1034 IRType tyS = shadowType(ty);
1035 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardjba999312004-11-15 15:21:17 +00001036 sk_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001037 sk_assert(isOriginalAtom(mce,ix));
1038 complainIfUndefined(mce,ix);
1039 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1040 /* Always defined, return all zeroes of the relevant type */
1041 return definedOfType(tyS);
1042 } else {
1043 /* return a cloned version of the Get that refers to the shadow
1044 area. */
1045 IRArray* new_descr
1046 = mkIRArray( descr->base + mce->layout->total_sizeB,
1047 tyS, descr->nElems);
1048 return IRExpr_GetI( new_descr, ix, bias );
1049 }
1050}
1051
1052
1053/*------------------------------------------------------------*/
1054/*--- Generating approximations for unknown operations, ---*/
1055/*--- using lazy-propagate semantics ---*/
1056/*------------------------------------------------------------*/
1057
1058/* Lazy propagation of undefinedness from two values, resulting in the
1059 specified shadow type.
1060*/
1061static
1062IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1063{
1064 /* force everything via 32-bit intermediaries. */
1065 IRAtom* at;
1066 sk_assert(isShadowAtom(mce,va1));
1067 sk_assert(isShadowAtom(mce,va2));
1068 at = mkPCastTo(mce, Ity_I32, va1);
1069 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1070 at = mkPCastTo(mce, finalVty, at);
1071 return at;
1072}
1073
1074
1075/* Do the lazy propagation game from a null-terminated vector of
1076 atoms. This is presumably the arguments to a helper call, so the
1077 IRCallee info is also supplied in order that we can know which
1078 arguments should be ignored (via the .mcx_mask field).
1079*/
1080static
1081IRAtom* mkLazyN ( MCEnv* mce,
1082 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1083{
1084 Int i;
1085 IRAtom* here;
1086 IRAtom* curr = definedOfType(Ity_I32);
1087 for (i = 0; exprvec[i]; i++) {
1088 sk_assert(i < 32);
1089 sk_assert(isOriginalAtom(mce, exprvec[i]));
1090 /* Only take notice of this arg if the callee's mc-exclusion
1091 mask does not say it is to be excluded. */
1092 if (cee->mcx_mask & (1<<i)) {
1093 /* the arg is to be excluded from definedness checking. Do
1094 nothing. */
1095 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1096 } else {
1097 /* calculate the arg's definedness, and pessimistically merge
1098 it in. */
1099 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1100 curr = mkUifU32(mce, here, curr);
1101 }
1102 }
1103 return mkPCastTo(mce, finalVtype, curr );
1104}
1105
1106
1107/*------------------------------------------------------------*/
1108/*--- Generating expensive sequences for exact carry-chain ---*/
1109/*--- propagation in add/sub and related operations. ---*/
1110/*------------------------------------------------------------*/
1111
1112static
1113IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1114 IRAtom* aa, IRAtom* bb )
1115{
sewardj8fc93742004-11-22 11:29:33 +00001116 IRType ty;
1117 IROp opAND, opOR, opXOR, opNOT, opADD;
1118 IRAtom *a_min, *b_min, *a_max, *b_max;
1119
sewardjde8a5ae2004-11-06 14:20:54 +00001120 sk_assert(isShadowAtom(mce,qaa));
1121 sk_assert(isShadowAtom(mce,qbb));
1122 sk_assert(isOriginalAtom(mce,aa));
1123 sk_assert(isOriginalAtom(mce,bb));
1124 sk_assert(sameKindedAtoms(qaa,aa));
1125 sk_assert(sameKindedAtoms(qbb,bb));
1126
sewardj8fc93742004-11-22 11:29:33 +00001127 ty = Ity_I32;
1128 opAND = Iop_And32;
1129 opOR = Iop_Or32;
1130 opXOR = Iop_Xor32;
1131 opNOT = Iop_Not32;
1132 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001133
1134 // a_min = aa & ~qaa
1135 a_min = assignNew(mce,ty,
1136 binop(opAND, aa,
1137 assignNew(mce,ty, unop(opNOT, qaa))));
1138
1139 // b_min = bb & ~qbb
1140 b_min = assignNew(mce,ty,
1141 binop(opAND, bb,
1142 assignNew(mce,ty, unop(opNOT, qbb))));
1143
1144 // a_max = aa | qaa
1145 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1146
1147 // b_max = bb | qbb
1148 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1149
1150 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1151 return
1152 assignNew(mce,ty,
1153 binop( opOR,
1154 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1155 assignNew(mce,ty,
1156 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1157 assignNew(mce,ty, binop(opADD, a_max, b_max))
1158 )
1159 )
1160 )
1161 );
1162}
1163
1164
1165/*------------------------------------------------------------*/
1166/*--- Generate shadow values from all kinds of IRExprs. ---*/
1167/*------------------------------------------------------------*/
1168
1169static
1170IRAtom* expr2vbits_Binop ( MCEnv* mce,
1171 IROp op,
1172 IRAtom* atom1, IRAtom* atom2 )
1173{
1174 IRType and_or_ty;
1175 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1176 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1177 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1178
1179 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1180 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1181
1182 sk_assert(isOriginalAtom(mce,atom1));
1183 sk_assert(isOriginalAtom(mce,atom2));
1184 sk_assert(isShadowAtom(mce,vatom1));
1185 sk_assert(isShadowAtom(mce,vatom2));
1186 sk_assert(sameKindedAtoms(atom1,vatom1));
1187 sk_assert(sameKindedAtoms(atom2,vatom2));
1188 switch (op) {
1189
sewardj3598ef92004-11-11 02:13:30 +00001190 case Iop_RoundF64:
1191 case Iop_F64toI64:
1192 /* First arg is I32 (rounding mode), second is F64 (data). */
1193 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1194
1195 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1196 /* Takes two F64 args. */
sewardjde8a5ae2004-11-06 14:20:54 +00001197 case Iop_F64toI32:
1198 /* First arg is I32 (rounding mode), second is F64 (data). */
1199 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1200
1201 case Iop_F64toI16:
1202 /* First arg is I32 (rounding mode), second is F64 (data). */
1203 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1204
sewardj3598ef92004-11-11 02:13:30 +00001205 case Iop_ScaleF64:
1206 case Iop_Yl2xF64:
1207 case Iop_Yl2xp1F64:
1208 case Iop_PRemF64:
1209 case Iop_AtanF64:
1210 case Iop_AddF64:
1211 case Iop_DivF64:
1212 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001213 case Iop_MulF64:
1214 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1215
sewardj3598ef92004-11-11 02:13:30 +00001216 case Iop_CmpF64:
1217 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1218
sewardjde8a5ae2004-11-06 14:20:54 +00001219 /* non-FP after here */
1220
1221 case Iop_DivModU64to32:
1222 case Iop_DivModS64to32:
1223 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1224
sewardj3598ef92004-11-11 02:13:30 +00001225 case Iop_16HLto32:
1226 return assignNew(mce, Ity_I32,
1227 binop(Iop_16HLto32, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001228 case Iop_32HLto64:
1229 return assignNew(mce, Ity_I64,
sewardj3598ef92004-11-11 02:13:30 +00001230 binop(Iop_32HLto64, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001231
1232 case Iop_MullS32:
1233 case Iop_MullU32: {
1234 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1235 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1236 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1237 }
1238
sewardj3598ef92004-11-11 02:13:30 +00001239 case Iop_MullS16:
1240 case Iop_MullU16: {
1241 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1242 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1243 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1244 }
1245
1246 case Iop_MullS8:
1247 case Iop_MullU8: {
1248 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1249 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1250 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1251 }
1252
sewardjde8a5ae2004-11-06 14:20:54 +00001253 case Iop_Add32:
1254# if 0
1255 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1256# endif
1257 case Iop_Sub32:
1258 case Iop_Mul32:
1259 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1260
sewardj3598ef92004-11-11 02:13:30 +00001261 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001262 case Iop_Add16:
1263 case Iop_Sub16:
1264 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1265
1266 case Iop_Sub8:
1267 case Iop_Add8:
1268 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1269
1270 case Iop_CmpLE32S: case Iop_CmpLE32U:
1271 case Iop_CmpLT32U: case Iop_CmpLT32S:
1272 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001273 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001274
sewardj3598ef92004-11-11 02:13:30 +00001275 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001276 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001277
1278 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001279 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001280
1281 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1282 /* Complain if the shift amount is undefined. Then simply
1283 shift the first arg's V bits by the real shift amount. */
1284 complainIfUndefined(mce, atom2);
1285 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1286
1287 case Iop_Shl16: case Iop_Shr16:
1288 /* Same scheme as with 32-bit shifts. */
1289 complainIfUndefined(mce, atom2);
1290 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1291
sewardj3598ef92004-11-11 02:13:30 +00001292 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001293 /* Same scheme as with 32-bit shifts. */
1294 complainIfUndefined(mce, atom2);
1295 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1296
1297 case Iop_Shl64: case Iop_Shr64:
1298 /* Same scheme as with 32-bit shifts. */
1299 complainIfUndefined(mce, atom2);
1300 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1301
1302 case Iop_And32:
1303 uifu = mkUifU32; difd = mkDifD32;
1304 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001305 case Iop_And16:
1306 uifu = mkUifU16; difd = mkDifD16;
1307 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001308 case Iop_And8:
1309 uifu = mkUifU8; difd = mkDifD8;
1310 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1311
1312 case Iop_Or32:
1313 uifu = mkUifU32; difd = mkDifD32;
1314 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1315 case Iop_Or16:
1316 uifu = mkUifU16; difd = mkDifD16;
1317 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1318 case Iop_Or8:
1319 uifu = mkUifU8; difd = mkDifD8;
1320 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1321
1322 do_And_Or:
1323 return
1324 assignNew(
1325 mce,
1326 and_or_ty,
1327 difd(mce, uifu(mce, vatom1, vatom2),
1328 difd(mce, improve(mce, atom1, vatom1),
1329 improve(mce, atom2, vatom2) ) ) );
1330
1331 case Iop_Xor8:
1332 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001333 case Iop_Xor16:
1334 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001335 case Iop_Xor32:
1336 return mkUifU32(mce, vatom1, vatom2);
1337
1338 default:
1339 ppIROp(op);
1340 VG_(skin_panic)("memcheck:expr2vbits_Binop");
1341 }
1342}
1343
1344
1345static
1346IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1347{
1348 IRAtom* vatom = expr2vbits( mce, atom );
1349 sk_assert(isOriginalAtom(mce,atom));
1350 switch (op) {
1351
1352 case Iop_F32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001353 case Iop_I32toF64:
1354 case Iop_I64toF64:
1355 case Iop_NegF64:
1356 case Iop_SinF64:
1357 case Iop_CosF64:
1358 case Iop_TanF64:
1359 case Iop_SqrtF64:
1360 case Iop_AbsF64:
1361 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001362 return mkPCastTo(mce, Ity_I64, vatom);
1363
sewardj3598ef92004-11-11 02:13:30 +00001364 case Iop_F64toF32:
1365 case Iop_Clz32:
1366 case Iop_Ctz32:
1367 return mkPCastTo(mce, Ity_I32, vatom);
1368
1369 case Iop_32Sto64:
1370 case Iop_32Uto64:
1371 return assignNew(mce, Ity_I64, unop(op, vatom));
1372
sewardjde8a5ae2004-11-06 14:20:54 +00001373 case Iop_64to32:
1374 case Iop_64HIto32:
1375 case Iop_1Uto32:
1376 case Iop_8Uto32:
1377 case Iop_16Uto32:
1378 case Iop_16Sto32:
1379 case Iop_8Sto32:
1380 return assignNew(mce, Ity_I32, unop(op, vatom));
1381
1382 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001383 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001384 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001385 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001386 return assignNew(mce, Ity_I16, unop(op, vatom));
1387
1388 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001389 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001390 case Iop_32to8:
1391 return assignNew(mce, Ity_I8, unop(op, vatom));
1392
1393 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001394 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001395
sewardj3598ef92004-11-11 02:13:30 +00001396 case Iop_ReinterpF64asI64:
1397 case Iop_ReinterpI64asF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001398 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001399 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001400 case Iop_Not8:
1401 case Iop_Not1:
1402 return vatom;
1403 default:
1404 ppIROp(op);
1405 VG_(skin_panic)("memcheck:expr2vbits_Unop");
1406 }
1407}
1408
1409
1410static
sewardj3598ef92004-11-11 02:13:30 +00001411IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001412{
1413 void* helper;
1414 Char* hname;
1415 IRDirty* di;
1416 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00001417 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001418
1419 sk_assert(isOriginalAtom(mce,addr));
1420
1421 /* First, emit a definedness test for the address. This also sets
1422 the address (shadow) to 'defined' following the test. */
1423 complainIfUndefined( mce, addr );
1424
1425 /* Now cook up a call to the relevant helper function, to read the
1426 data V bits from shadow memory. */
1427 ty = shadowType(ty);
1428 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001429 case Ity_I64: helper = &MC_(helperc_LOADV8);
1430 hname = "MC_(helperc_LOADV8)";
1431 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001432 case Ity_I32: helper = &MC_(helperc_LOADV4);
1433 hname = "MC_(helperc_LOADV4)";
1434 break;
1435 case Ity_I16: helper = &MC_(helperc_LOADV2);
1436 hname = "MC_(helperc_LOADV2)";
1437 break;
1438 case Ity_I8: helper = &MC_(helperc_LOADV1);
1439 hname = "MC_(helperc_LOADV1)";
1440 break;
1441 default: ppIRType(ty);
1442 VG_(skin_panic)("memcheck:do_shadow_LDle");
1443 }
1444
sewardj3598ef92004-11-11 02:13:30 +00001445 /* Generate the actual address into addrAct. */
1446 if (bias == 0) {
1447 addrAct = addr;
1448 } else {
1449 IRType tyAddr = mce->hWordTy;
sewardj3598ef92004-11-11 02:13:30 +00001450 IROp mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1451 IRAtom* eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj8fc93742004-11-22 11:29:33 +00001452 sk_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj3598ef92004-11-11 02:13:30 +00001453 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1454 }
1455
sewardjde8a5ae2004-11-06 14:20:54 +00001456 /* We need to have a place to park the V bits we're just about to
1457 read. */
1458 datavbits = newIRTemp(mce->bb->tyenv, ty);
1459 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00001460 1/*regparms*/, hname, helper,
1461 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00001462 setHelperAnns( mce, di );
1463 stmt( mce->bb, IRStmt_Dirty(di) );
1464
1465 return mkexpr(datavbits);
1466}
1467
1468
1469static
1470IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00001471 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00001472{
1473 IRAtom *vbitsC, *vbits0, *vbitsX;
1474 IRType ty;
1475 /* Given Mux0X(cond,expr0,exprX), generate
1476 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
1477 That is, steer the V bits like the originals, but trash the
1478 result if the steering value is undefined. This gives
1479 lazy propagation. */
1480 sk_assert(isOriginalAtom(mce, cond));
1481 sk_assert(isOriginalAtom(mce, expr0));
1482 sk_assert(isOriginalAtom(mce, exprX));
1483
1484 vbitsC = expr2vbits(mce, cond);
1485 vbits0 = expr2vbits(mce, expr0);
1486 vbitsX = expr2vbits(mce, exprX);
1487 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
1488
1489 return
1490 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
1491 mkPCastTo(mce, ty, vbitsC) );
1492}
1493
1494/* --------- This is the main expression-handling function. --------- */
1495
1496static
1497IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
1498{
1499 switch (e->tag) {
1500
1501 case Iex_Get:
1502 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
1503
1504 case Iex_GetI:
1505 return shadow_GETI( mce, e->Iex.GetI.descr,
1506 e->Iex.GetI.ix, e->Iex.GetI.bias );
1507
1508 case Iex_Tmp:
1509 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
1510
1511 case Iex_Const:
1512 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
1513
1514 case Iex_Binop:
1515 return expr2vbits_Binop(
1516 mce,
1517 e->Iex.Binop.op,
1518 e->Iex.Binop.arg1, e->Iex.Binop.arg2
1519 );
1520
1521 case Iex_Unop:
1522 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
1523
1524 case Iex_LDle:
sewardj3598ef92004-11-11 02:13:30 +00001525 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
1526 e->Iex.LDle.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00001527
1528 case Iex_CCall:
1529 return mkLazyN( mce, e->Iex.CCall.args,
1530 e->Iex.CCall.retty,
1531 e->Iex.CCall.cee );
1532
1533 case Iex_Mux0X:
1534 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
1535 e->Iex.Mux0X.exprX);
1536
1537 default:
1538 VG_(printf)("\n");
1539 ppIRExpr(e);
1540 VG_(printf)("\n");
1541 VG_(skin_panic)("memcheck: expr2vbits");
1542 }
1543}
1544
1545/*------------------------------------------------------------*/
1546/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
1547/*------------------------------------------------------------*/
1548
1549/* Widen a value to the host word size. */
1550
1551static
1552IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
1553{
sewardjde8a5ae2004-11-06 14:20:54 +00001554 IRType ty = typeOfIRExpr(mce->bb->tyenv, vatom);
1555 IRType tyH = mce->hWordTy;
1556
sewardj8fc93742004-11-22 11:29:33 +00001557 /* vatom is vbits-value and as such can only have a shadow type. */
1558 sk_assert(isShadowAtom(mce,vatom));
1559
sewardjde8a5ae2004-11-06 14:20:54 +00001560 if (tyH == Ity_I32) {
1561 switch (ty) {
1562 case Ity_I32: return vatom;
1563 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
1564 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
1565 default: goto unhandled;
1566 }
1567 } else {
1568 goto unhandled;
1569 }
1570 unhandled:
1571 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
1572 VG_(skin_panic)("zwidenToHostWord");
1573}
1574
1575
sewardj3598ef92004-11-11 02:13:30 +00001576/* Generate a shadow store. addr is always the original address atom.
1577 You can pass in either originals or V-bits for the data atom, but
1578 obviously not both. */
1579
sewardjde8a5ae2004-11-06 14:20:54 +00001580static
sewardj3598ef92004-11-11 02:13:30 +00001581void do_shadow_STle ( MCEnv* mce,
1582 IRAtom* addr, UInt bias,
1583 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00001584{
1585 IRType ty;
1586 IRDirty* di;
sewardjde8a5ae2004-11-06 14:20:54 +00001587 void* helper = NULL;
1588 Char* hname = NULL;
sewardj3598ef92004-11-11 02:13:30 +00001589 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001590
sewardj3598ef92004-11-11 02:13:30 +00001591 if (data) {
1592 sk_assert(!vdata);
1593 sk_assert(isOriginalAtom(mce, data));
1594 sk_assert(bias == 0);
1595 vdata = expr2vbits( mce, data );
1596 } else {
1597 sk_assert(vdata);
1598 }
sewardjde8a5ae2004-11-06 14:20:54 +00001599
1600 sk_assert(isOriginalAtom(mce,addr));
sewardj3598ef92004-11-11 02:13:30 +00001601 sk_assert(isShadowAtom(mce,vdata));
1602
1603 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00001604
1605 /* First, emit a definedness test for the address. This also sets
1606 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00001607 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00001608
1609 /* Now cook up a call to the relevant helper function, to write the
1610 data V bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00001611 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001612 case Ity_I64: helper = &MC_(helperc_STOREV8);
1613 hname = "MC_(helperc_STOREV8)";
1614 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001615 case Ity_I32: helper = &MC_(helperc_STOREV4);
1616 hname = "MC_(helperc_STOREV4)";
1617 break;
1618 case Ity_I16: helper = &MC_(helperc_STOREV2);
1619 hname = "MC_(helperc_STOREV2)";
1620 break;
1621 case Ity_I8: helper = &MC_(helperc_STOREV1);
1622 hname = "MC_(helperc_STOREV1)";
1623 break;
1624 default: VG_(skin_panic)("memcheck:do_shadow_STle");
1625 }
1626
sewardj3598ef92004-11-11 02:13:30 +00001627 /* Generate the actual address into addrAct. */
1628 if (bias == 0) {
1629 addrAct = addr;
1630 } else {
1631 IRType tyAddr = mce->hWordTy;
sewardj3598ef92004-11-11 02:13:30 +00001632 IROp mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1633 IRAtom* eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj8fc93742004-11-22 11:29:33 +00001634 sk_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj3598ef92004-11-11 02:13:30 +00001635 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1636 }
1637
1638 if (ty == Ity_I64) {
1639 /* We can't do this with regparm 2 on 32-bit platforms, since
1640 the back ends aren't clever enough to handle 64-bit regparm
1641 args. Therefore be different. */
1642 di = unsafeIRDirty_0_N(
1643 1/*regparms*/, hname, helper,
1644 mkIRExprVec_2( addrAct, vdata ));
1645 } else {
1646 di = unsafeIRDirty_0_N(
1647 2/*regparms*/, hname, helper,
1648 mkIRExprVec_2( addrAct,
1649 zwidenToHostWord( mce, vdata )));
1650 }
sewardjde8a5ae2004-11-06 14:20:54 +00001651 setHelperAnns( mce, di );
1652 stmt( mce->bb, IRStmt_Dirty(di) );
1653}
1654
1655
sewardj3598ef92004-11-11 02:13:30 +00001656/* Do lazy pessimistic propagation through a dirty helper call, by
1657 looking at the annotations on it. This is the most complex part of
1658 Memcheck. */
1659
1660static IRType szToITy ( Int n )
1661{
1662 switch (n) {
1663 case 1: return Ity_I8;
1664 case 2: return Ity_I16;
1665 case 4: return Ity_I32;
1666 case 8: return Ity_I64;
1667 default: VG_(skin_panic)("szToITy(memcheck)");
1668 }
1669}
1670
1671static
1672void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
1673{
1674 Int i, offset, toDo;
1675 IRAtom* src;
1676 IRType tyAddr, tySrc, tyDst;
1677 IRTemp dst;
sewardj8fc93742004-11-22 11:29:33 +00001678 IRAtom *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00001679
1680 /* First check the guard. */
1681 complainIfUndefined(mce, d->guard);
1682
1683 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00001684 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00001685
1686 /* Inputs: unmasked args */
1687 for (i = 0; d->args[i]; i++) {
1688 if (d->cee->mcx_mask & (1<<i)) {
1689 /* ignore this arg */
1690 } else {
1691 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
1692 curr = mkUifU32(mce, here, curr);
1693 }
1694 }
1695
1696 /* Inputs: guest state that we read. */
1697 for (i = 0; i < d->nFxState; i++) {
1698 sk_assert(d->fxState[i].fx != Ifx_None);
1699 if (d->fxState[i].fx == Ifx_Write)
1700 continue;
1701 /* This state element is read or modified. So we need to
1702 consider it. */
1703 tySrc = szToITy( d->fxState[i].size );
1704 src = assignNew( mce, tySrc,
1705 shadow_GET(mce, d->fxState[i].offset, tySrc ) );
1706 here = mkPCastTo( mce, Ity_I32, src );
1707 curr = mkUifU32(mce, here, curr);
1708 }
1709
1710 /* Inputs: memory. First set up some info needed regardless of
1711 whether we're doing reads or writes. */
1712 tyAddr = Ity_INVALID;
1713
1714 if (d->mFx != Ifx_None) {
1715 /* Because we may do multiple shadow loads/stores from the same
1716 base address, it's best to do a single test of its
1717 definedness right now. Post-instrumentation optimisation
1718 should remove all but this test. */
1719 sk_assert(d->mAddr);
1720 complainIfUndefined(mce, d->mAddr);
1721
1722 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
1723 sk_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
1724 sk_assert(tyAddr == mce->hWordTy); /* not really right */
1725 }
1726
1727 /* Deal with memory inputs (reads or modifies) */
1728 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
1729 offset = 0;
1730 toDo = d->mSize;
1731 /* chew off 32-bit chunks */
1732 while (toDo >= 4) {
1733 here = mkPCastTo(
1734 mce, Ity_I32,
1735 expr2vbits_LDle ( mce, Ity_I32,
1736 d->mAddr, d->mSize - toDo )
1737 );
1738 curr = mkUifU32(mce, here, curr);
1739 toDo -= 4;
1740 }
1741 /* chew off 16-bit chunks */
1742 while (toDo >= 2) {
1743 here = mkPCastTo(
1744 mce, Ity_I32,
1745 expr2vbits_LDle ( mce, Ity_I16,
1746 d->mAddr, d->mSize - toDo )
1747 );
1748 curr = mkUifU32(mce, here, curr);
1749 toDo -= 2;
1750 }
1751 sk_assert(toDo == 0); /* also need to handle 1-byte excess */
1752 }
1753
1754 /* Whew! So curr is a 32-bit V-value summarising pessimistically
1755 all the inputs to the helper. Now we need to re-distribute the
1756 results to all destinations. */
1757
1758 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00001759 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00001760 dst = findShadowTmp(mce, d->tmp);
1761 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
1762 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
1763 }
1764
1765 /* Outputs: guest state that we write or modify. */
1766 for (i = 0; i < d->nFxState; i++) {
1767 sk_assert(d->fxState[i].fx != Ifx_None);
1768 if (d->fxState[i].fx == Ifx_Read)
1769 continue;
1770 /* this state element is written or modified. So we need to
1771 consider it. */
1772 tyDst = szToITy( d->fxState[i].size );
1773 do_shadow_PUT( mce, d->fxState[i].offset,
1774 NULL, /* original atom */
1775 mkPCastTo( mce, tyDst, curr ) );
1776 }
1777
1778 /* Outputs: memory that we write or modify. */
1779 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
1780 offset = 0;
1781 toDo = d->mSize;
1782 /* chew off 32-bit chunks */
1783 while (toDo >= 4) {
1784 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
1785 NULL, /* original data */
1786 mkPCastTo( mce, Ity_I32, curr ) );
1787 toDo -= 4;
1788 }
1789 /* chew off 16-bit chunks */
1790 while (toDo >= 2) {
1791 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
1792 NULL, /* original data */
1793 mkPCastTo( mce, Ity_I16, curr ) );
1794 toDo -= 2;
1795 }
1796 sk_assert(toDo == 0); /* also need to handle 1-byte excess */
1797 }
1798
1799}
1800
1801
sewardjde8a5ae2004-11-06 14:20:54 +00001802/*------------------------------------------------------------*/
1803/*--- Memcheck main ---*/
1804/*------------------------------------------------------------*/
1805
sewardj3598ef92004-11-11 02:13:30 +00001806#if 0 /* UNUSED */
1807static Bool isBogusAtom ( IRAtom* at )
1808{
1809 ULong n = 0;
1810 IRConst* con;
1811 sk_assert(isAtom(at));
1812 if (at->tag == Iex_Tmp)
1813 return False;
1814 sk_assert(at->tag == Iex_Const);
1815 con = at->Iex.Const.con;
1816 switch (con->tag) {
1817 case Ico_U8: n = (ULong)con->Ico.U8; break;
1818 case Ico_U16: n = (ULong)con->Ico.U16; break;
1819 case Ico_U32: n = (ULong)con->Ico.U32; break;
1820 case Ico_U64: n = (ULong)con->Ico.U64; break;
1821 default: ppIRExpr(at); sk_assert(0);
1822 }
1823 /* VG_(printf)("%llx\n", n); */
1824 return (n == 0xFEFEFEFF
1825 || n == 0x80808080
1826 || n == 0x1010101
1827 || n == 1010100);
1828}
1829
1830static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
1831{
1832 Int i;
1833 IRExpr* e;
1834 switch (st->tag) {
1835 case Ist_Tmp:
1836 e = st->Ist.Tmp.data;
1837 switch (e->tag) {
1838 case Iex_Get:
1839 case Iex_Tmp:
1840 return False;
1841 case Iex_Unop:
1842 return isBogusAtom(e->Iex.Unop.arg);
1843 case Iex_Binop:
1844 return isBogusAtom(e->Iex.Binop.arg1)
1845 || isBogusAtom(e->Iex.Binop.arg2);
1846 case Iex_Mux0X:
1847 return isBogusAtom(e->Iex.Mux0X.cond)
1848 || isBogusAtom(e->Iex.Mux0X.expr0)
1849 || isBogusAtom(e->Iex.Mux0X.exprX);
1850 case Iex_LDle:
1851 return isBogusAtom(e->Iex.LDle.addr);
1852 case Iex_CCall:
1853 for (i = 0; e->Iex.CCall.args[i]; i++)
1854 if (isBogusAtom(e->Iex.CCall.args[i]))
1855 return True;
1856 return False;
1857 default:
1858 goto unhandled;
1859 }
1860 case Ist_Put:
1861 return isBogusAtom(st->Ist.Put.data);
1862 case Ist_STle:
1863 return isBogusAtom(st->Ist.STle.addr)
1864 || isBogusAtom(st->Ist.STle.data);
1865 case Ist_Exit:
sewardj0276d4b2004-11-15 15:30:21 +00001866 return isBogusAtom(st->Ist.Exit.guard);
sewardj3598ef92004-11-11 02:13:30 +00001867 default:
1868 unhandled:
1869 ppIRStmt(st);
1870 VG_(skin_panic)("hasBogusLiterals");
1871 }
1872}
1873#endif /* UNUSED */
1874
1875
sewardjde8a5ae2004-11-06 14:20:54 +00001876IRBB* mc_instrument ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
1877{
sewardj3598ef92004-11-11 02:13:30 +00001878 Bool verboze = False; //True;
1879
1880 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00001881
1882 Int i, j, first_stmt;
1883 IRStmt* st;
1884 MCEnv mce;
1885
1886 /* Set up BB */
1887 IRBB* bb = emptyIRBB();
1888 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
1889 bb->next = dopyIRExpr(bb_in->next);
1890 bb->jumpkind = bb_in->jumpkind;
1891
1892 /* Set up the running environment. Only .bb is modified as we go
1893 along. */
1894 mce.bb = bb;
1895 mce.layout = layout;
1896 mce.n_originalTmps = bb->tyenv->types_used;
1897 mce.hWordTy = hWordTy;
1898 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
1899 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00001900 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00001901
1902 /* Iterate over the stmts. */
1903
1904 for (i = 0; i < bb_in->stmts_used; i++) {
1905 st = bb_in->stmts[i];
1906 if (!st) continue;
1907
1908 sk_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00001909
1910 /*
1911 if (!hasBogusLiterals) {
1912 hasBogusLiterals = checkForBogusLiterals(st);
1913 if (hasBogusLiterals) {
1914 VG_(printf)("bogus: ");
1915 ppIRStmt(st);
1916 VG_(printf)("\n");
1917 }
1918 }
1919 */
sewardjde8a5ae2004-11-06 14:20:54 +00001920 first_stmt = bb->stmts_used;
1921
1922 if (verboze) {
1923 ppIRStmt(st);
1924 VG_(printf)("\n\n");
1925 }
1926
1927 switch (st->tag) {
1928
1929 case Ist_Tmp:
1930 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
1931 expr2vbits( &mce, st->Ist.Tmp.data) );
1932 break;
1933
1934 case Ist_Put:
1935 do_shadow_PUT( &mce,
1936 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00001937 st->Ist.Put.data,
1938 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00001939 break;
1940
1941 case Ist_PutI:
1942 do_shadow_PUTI( &mce,
1943 st->Ist.PutI.descr,
1944 st->Ist.PutI.ix,
1945 st->Ist.PutI.bias,
1946 st->Ist.PutI.data );
1947 break;
1948
1949 case Ist_STle:
sewardj3598ef92004-11-11 02:13:30 +00001950 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
1951 st->Ist.STle.data,
1952 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00001953 break;
1954
1955 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00001956 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00001957 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00001958 break;
1959
1960 case Ist_Dirty:
1961 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00001962 break;
1963
1964 default:
1965 VG_(printf)("\n");
1966 ppIRStmt(st);
1967 VG_(printf)("\n");
1968 VG_(skin_panic)("memcheck: unhandled IRStmt");
1969
1970 } /* switch (st->tag) */
1971
1972 if (verboze) {
1973 for (j = first_stmt; j < bb->stmts_used; j++) {
1974 VG_(printf)(" ");
1975 ppIRStmt(bb->stmts[j]);
1976 VG_(printf)("\n");
1977 }
1978 VG_(printf)("\n");
1979 }
1980
1981 addStmtToIRBB(bb, st);
1982
1983 }
1984
1985 /* Now we need to complain if the jump target is undefined. */
1986 first_stmt = bb->stmts_used;
1987
1988 if (verboze) {
1989 VG_(printf)("bb->next = ");
1990 ppIRExpr(bb->next);
1991 VG_(printf)("\n\n");
1992 }
1993
1994 complainIfUndefined( &mce, bb->next );
1995
1996 if (verboze) {
1997 for (j = first_stmt; j < bb->stmts_used; j++) {
1998 VG_(printf)(" ");
1999 ppIRStmt(bb->stmts[j]);
2000 VG_(printf)("\n");
2001 }
2002 VG_(printf)("\n");
2003 }
2004
2005 return bb;
2006}
2007
2008/*--------------------------------------------------------------------*/
2009/*--- end mc_translate.c ---*/
2010/*--------------------------------------------------------------------*/