blob: 68869a1e09c082d5545eb695fec8eaa6910e2069 [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;
sewardjb5bf2e02004-10-25 13:06:17 +000085
sewardjced9fe52004-07-07 11:55:36 +000086 LibVEX_Init ( &failure_exit, &log_bytes,
sewardj1f40a0a2004-07-21 12:28:07 +000087 1, /* debug_paranoia */
sewardjabe017e2004-10-29 23:42:36 +000088 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +000089 &vcon );
sewardjced9fe52004-07-07 11:55:36 +000090
sewardjea64e142004-07-22 16:47:21 +000091
sewardjced9fe52004-07-07 11:55:36 +000092 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +000093
sewardjced9fe52004-07-07 11:55:36 +000094 fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +000095 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +000096 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +000097
98 if (n_bbs_done == TEST_N_BBS) break;
99 n_bbs_done++;
100
sewardjced9fe52004-07-07 11:55:36 +0000101 /* first line is: . bb-number bb-addr n-bytes */
102 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
103 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000104 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000105 assert(orig_nbytes >= 1);
106 assert(!feof(f));
107 fgets(linebuf, N_LINEBUF,f);
108 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000109
sewardjced9fe52004-07-07 11:55:36 +0000110 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000111 if (verbose)
sewardj4459baa2004-09-10 20:00:46 +0000112 printf("============ Basic Block %d, "
113 "Start %x, nbytes %2d ============",
sewardjabe017e2004-10-29 23:42:36 +0000114 n_bbs_done-1, orig_addr, orig_nbytes);
115
sewardjced9fe52004-07-07 11:55:36 +0000116 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
117 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000118 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
119 origbuf[i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000120 }
121
sewardjabe017e2004-10-29 23:42:36 +0000122 for (i = 0; i < TEST_N_ITERS; i++)
123 tres
124 = LibVEX_Translate (
sewardjc3263ee2004-12-29 17:48:22 +0000125 VexArchX86, VexSubArchX86_sse2,
126 VexArchX86, VexSubArchX86_sse2,
sewardj5bd4d162004-11-10 13:02:48 +0000127 origbuf, (Addr64)orig_addr, chase_into_not_ok,
sewardj72c72812005-01-19 11:49:45 +0000128 &vge,
sewardjabe017e2004-10-29 23:42:36 +0000129 transbuf, N_TRANSBUF, &trans_used,
sewardj9e7448b2004-11-18 13:44:15 +0000130#if 1 /* no instrumentation */
131 NULL, /* instrument1 */
132 NULL, /* instrument2 */
133 False, /* cleanup after instrument */
134#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000135#if 0 /* addrcheck */
136 ac_instrument, /* instrument1 */
137 NULL, /* instrument2 */
138 False, /* cleanup after instrument */
139#endif
sewardj9e7448b2004-11-18 13:44:15 +0000140#if 0 /* memcheck */
sewardjde8a5ae2004-11-06 14:20:54 +0000141 mc_instrument, /* instrument1 */
142 NULL, /* instrument2 */
sewardj69f9e3e2004-12-30 02:05:34 +0000143 True, /* cleanup after instrument */
sewardjde8a5ae2004-11-06 14:20:54 +0000144#endif
sewardjabe017e2004-10-29 23:42:36 +0000145 NULL, /* access checker */
146 TEST_FLAGS
147 );
148
sewardjd887b862005-01-17 18:34:34 +0000149 if (tres != VexTransOK)
sewardj4459baa2004-09-10 20:00:46 +0000150 printf("\ntres = %d\n", (Int)tres);
sewardjd887b862005-01-17 18:34:34 +0000151 assert(tres == VexTransOK);
sewardj72c72812005-01-19 11:49:45 +0000152 assert(vge.n_used == 1);
153 assert((UInt)(vge.len[0]) == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000154
sewardj4459baa2004-09-10 20:00:46 +0000155 sum = 0;
156 for (i = 0; i < trans_used; i++)
157 sum += (UInt)transbuf[i];
sewardj72c72812005-01-19 11:49:45 +0000158 printf ( " %6.2f ... %d\n", (double)trans_used / (double)vge.len[0], sum );
sewardjced9fe52004-07-07 11:55:36 +0000159 }
160
161 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000162 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000163 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000164
sewardjce605f92004-07-05 14:39:15 +0000165 return 0;
166}
sewardj9b1004e2004-10-30 22:25:40 +0000167
168//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000169//////////////////////////////////////////////////////////////////////
170//////////////////////////////////////////////////////////////////////
171//////////////////////////////////////////////////////////////////////
172//////////////////////////////////////////////////////////////////////
173//////////////////////////////////////////////////////////////////////
174//////////////////////////////////////////////////////////////////////
175//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000176
177static
sewardjde8a5ae2004-11-06 14:20:54 +0000178__attribute((noreturn))
sewardj9b1004e2004-10-30 22:25:40 +0000179void panic ( Char* s )
180{
181 printf("\npanic: %s\n", s);
182 failure_exit();
183}
184
185static
sewardj9578a8b2004-11-04 19:44:48 +0000186IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000187{
188/* Use this rather than eg. -1 because it's a UInt. */
189#define INVALID_DATA_SIZE 999999
190
191 Int i;
192 Int sz;
193 IRCallee* helper;
194 IRStmt* st;
195 IRExpr* data;
196 IRExpr* addr;
197 Bool needSz;
198
199 /* Set up BB */
200 IRBB* bb = emptyIRBB();
201 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
202 bb->next = dopyIRExpr(bb_in->next);
203 bb->jumpkind = bb_in->jumpkind;
204
205 /* No loads to consider in ->next. */
206 assert(isAtom(bb_in->next));
207
208 for (i = 0; i < bb_in->stmts_used; i++) {
209 st = bb_in->stmts[i];
210 if (!st) continue;
211
212 switch (st->tag) {
213
214 case Ist_Tmp:
215 data = st->Ist.Tmp.data;
216 if (data->tag == Iex_LDle) {
217 addr = data->Iex.LDle.addr;
218 sz = sizeofIRType(data->Iex.LDle.ty);
219 needSz = False;
220 switch (sz) {
221 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000222 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000223 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000224 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000225 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000226 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000227 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000228 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000229 needSz = True; break;
230 }
231 if (needSz) {
232 addStmtToIRBB(
233 bb,
234 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000235 unsafeIRDirty_0_N( helper->regparms,
236 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000237 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
238 ));
239 } else {
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_1(addr) )
246 ));
247 }
248 }
249 break;
250
251 case Ist_STle:
252 data = st->Ist.STle.data;
253 addr = st->Ist.STle.addr;
254 assert(isAtom(data));
255 assert(isAtom(addr));
256 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
257 needSz = False;
258 switch (sz) {
259 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000260 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000261 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000262 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000263 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000264 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000265 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000266 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000267 needSz = True; break;
268 }
269 if (needSz) {
270 addStmtToIRBB(
271 bb,
272 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000273 unsafeIRDirty_0_N( helper->regparms,
274 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000275 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
276 ));
277 } else {
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_1(addr) )
284 ));
285 }
286 break;
287
288 case Ist_Put:
289 assert(isAtom(st->Ist.Put.data));
290 break;
291
292 case Ist_PutI:
sewardjeeac8412004-11-02 00:26:55 +0000293 assert(isAtom(st->Ist.PutI.ix));
sewardj9b1004e2004-10-30 22:25:40 +0000294 assert(isAtom(st->Ist.PutI.data));
295 break;
296
297 case Ist_Exit:
sewardj0276d4b2004-11-15 15:30:21 +0000298 assert(isAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000299 break;
300
301 case Ist_Dirty:
302 /* If the call doesn't interact with memory, we ain't
303 interested. */
304 if (st->Ist.Dirty.details->mFx == Ifx_None)
305 break;
306 goto unhandled;
307
308 default:
309 unhandled:
310 printf("\n");
311 ppIRStmt(st);
312 printf("\n");
313 panic("addrcheck: unhandled IRStmt");
314 }
315
316 addStmtToIRBB( bb, dopyIRStmt(st));
317 }
318
319 return bb;
320}
sewardjde8a5ae2004-11-06 14:20:54 +0000321
322//////////////////////////////////////////////////////////////////////
323//////////////////////////////////////////////////////////////////////
324//////////////////////////////////////////////////////////////////////
325//////////////////////////////////////////////////////////////////////
326//////////////////////////////////////////////////////////////////////
327//////////////////////////////////////////////////////////////////////
328//////////////////////////////////////////////////////////////////////
329//////////////////////////////////////////////////////////////////////
330
sewardj69f9e3e2004-12-30 02:05:34 +0000331#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000332#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000333#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000334#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000335#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000336
337void MC_helperc_complain_undef ( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000338void MC_helperc_LOADV8 ( void ) { }
sewardjde8a5ae2004-11-06 14:20:54 +0000339void MC_helperc_LOADV4 ( void ) { }
340void MC_helperc_LOADV2 ( void ) { }
341void MC_helperc_LOADV1 ( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000342void MC_helperc_STOREV8( void ) { }
sewardjde8a5ae2004-11-06 14:20:54 +0000343void MC_helperc_STOREV4( void ) { }
344void MC_helperc_STOREV2( void ) { }
345void MC_helperc_STOREV1( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000346void MC_helperc_value_check0_fail( void ) { }
347void MC_helperc_value_check1_fail( void ) { }
348void MC_helperc_value_check4_fail( void ) { }
349
350
sewardj3598ef92004-11-11 02:13:30 +0000351/*--------------------------------------------------------------------*/
352/*--- Instrument IR to perform memory checking operations. ---*/
353/*--- mc_translate.c ---*/
354/*--------------------------------------------------------------------*/
355
356/*
357 This file is part of MemCheck, a heavyweight Valgrind tool for
358 detecting memory errors.
359
360 Copyright (C) 2000-2004 Julian Seward
361 jseward@acm.org
362
363 This program is free software; you can redistribute it and/or
364 modify it under the terms of the GNU General Public License as
365 published by the Free Software Foundation; either version 2 of the
366 License, or (at your option) any later version.
367
368 This program is distributed in the hope that it will be useful, but
369 WITHOUT ANY WARRANTY; without even the implied warranty of
370 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
371 General Public License for more details.
372
373 You should have received a copy of the GNU General Public License
374 along with this program; if not, write to the Free Software
375 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
376 02111-1307, USA.
377
378 The GNU General Public License is contained in the file COPYING.
379*/
380
381//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000382
383
384/*------------------------------------------------------------*/
385/*--- Forward decls ---*/
386/*------------------------------------------------------------*/
387
388struct _MCEnv;
389
390static IRType shadowType ( IRType ty );
391static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
392
393
394/*------------------------------------------------------------*/
395/*--- Memcheck running state, and tmp management. ---*/
396/*------------------------------------------------------------*/
397
398/* Carries around state during memcheck instrumentation. */
399typedef
400 struct _MCEnv {
401 /* MODIFIED: the bb being constructed. IRStmts are added. */
402 IRBB* bb;
403
404 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
405 original temps to their current their current shadow temp.
406 Initially all entries are IRTemp_INVALID. Entries are added
407 lazily since many original temps are not used due to
408 optimisation prior to instrumentation. Note that floating
409 point original tmps are shadowed by integer tmps of the same
410 size, and Bit-typed original tmps are shadowed by the type
411 Ity_I8. See comment below. */
412 IRTemp* tmpMap;
413 Int n_originalTmps; /* for range checking */
414
415 /* READONLY: the guest layout. This indicates which parts of
416 the guest state should be regarded as 'always defined'. */
417 VexGuestLayout* layout;
418 /* READONLY: the host word type. Needed for constructing
419 arguments of type 'HWord' to be passed to helper functions.
420 Ity_I32 or Ity_I64 only. */
421 IRType hWordTy;
422 }
423 MCEnv;
424
425/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
426 demand), as they are encountered. This is for two reasons.
427
428 (1) (less important reason): Many original tmps are unused due to
429 initial IR optimisation, and we do not want to spaces in tables
430 tracking them.
431
432 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
433 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000434 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000435 It is necessary to support making multiple assignments to a shadow
436 -- specifically, after testing a shadow for definedness, it needs
437 to be made defined. But IR's SSA property disallows this.
438
439 (2) (more important reason): Therefore, when a shadow needs to get
440 a new value, a new temporary is created, the value is assigned to
441 that, and the tmpMap is updated to reflect the new binding.
442
443 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000444 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000445 there's a read-before-write error in the original tmps. The IR
446 sanity checker should catch all such anomalies, however.
447*/
448
449/* Find the tmp currently shadowing the given original tmp. If none
450 so far exists, allocate one. */
451static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
452{
sewardj69f9e3e2004-12-30 02:05:34 +0000453 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000454 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000455 mce->tmpMap[orig]
456 = newIRTemp(mce->bb->tyenv,
457 shadowType(mce->bb->tyenv->types[orig]));
458 }
459 return mce->tmpMap[orig];
460}
461
462/* Allocate a new shadow for the given original tmp. This means any
463 previous shadow is abandoned. This is needed because it is
464 necessary to give a new value to a shadow once it has been tested
465 for undefinedness, but unfortunately IR's SSA property disallows
466 this. Instead we must abandon the old shadow, allocate a new one
467 and use that instead. */
468static void newShadowTmp ( MCEnv* mce, IRTemp orig )
469{
sewardj69f9e3e2004-12-30 02:05:34 +0000470 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000471 mce->tmpMap[orig]
472 = newIRTemp(mce->bb->tyenv,
473 shadowType(mce->bb->tyenv->types[orig]));
474}
475
476
477/*------------------------------------------------------------*/
478/*--- IRAtoms -- a subset of IRExprs ---*/
479/*------------------------------------------------------------*/
480
481/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
482 isAtom() in libvex_ir.h. Because this instrumenter expects flat
483 input, most of this code deals in atoms. Usefully, a value atom
484 always has a V-value which is also an atom: constants are shadowed
485 by constants, and temps are shadowed by the corresponding shadow
486 temporary. */
487
488typedef IRExpr IRAtom;
489
490/* (used for sanity checks only): is this an atom which looks
491 like it's from original code? */
492static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
493{
494 if (a1->tag == Iex_Const)
495 return True;
496 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
497 return True;
498 return False;
499}
500
501/* (used for sanity checks only): is this an atom which looks
502 like it's from shadow code? */
503static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
504{
505 if (a1->tag == Iex_Const)
506 return True;
507 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
508 return True;
509 return False;
510}
511
512/* (used for sanity checks only): check that both args are atoms and
513 are identically-kinded. */
514static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
515{
516 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
517 return True;
518 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
519 return True;
520 return False;
521}
522
523
524/*------------------------------------------------------------*/
525/*--- Type management ---*/
526/*------------------------------------------------------------*/
527
528/* Shadow state is always accessed using integer types. This returns
529 an integer type with the same size (as per sizeofIRType) as the
530 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000531 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000532
533static IRType shadowType ( IRType ty )
534{
535 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000536 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000537 case Ity_I8:
538 case Ity_I16:
539 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000540 case Ity_I64: return ty;
541 case Ity_F32: return Ity_I32;
542 case Ity_F64: return Ity_I64;
543 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000544 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000545 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000546 }
547}
548
549/* Produce a 'defined' value of the given shadow type. Should only be
550 supplied shadow types (Bit/I8/I16/I32/UI64). */
551static IRExpr* definedOfType ( IRType ty ) {
552 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000553 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
554 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
555 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
556 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
557 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
558 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
559 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000560 }
561}
562
563
564/*------------------------------------------------------------*/
565/*--- Constructing IR fragments ---*/
566/*------------------------------------------------------------*/
567
568/* assign value to tmp */
569#define assign(_bb,_tmp,_expr) \
570 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
571
572/* add stmt to a bb */
573#define stmt(_bb,_stmt) \
574 addStmtToIRBB((_bb), (_stmt))
575
576/* build various kinds of expressions */
577#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
578#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
579#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
580#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
581#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
582#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000583#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardjde8a5ae2004-11-06 14:20:54 +0000584#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
585
586/* bind the given expression to a new temporary, and return the
587 temporary. This effectively converts an arbitrary expression into
588 an atom. */
589static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
590 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
591 assign(mce->bb, t, e);
592 return mkexpr(t);
593}
594
595
596/*------------------------------------------------------------*/
597/*--- Constructing definedness primitive ops ---*/
598/*------------------------------------------------------------*/
599
600/* --------- Defined-if-either-defined --------- */
601
602static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000603 tl_assert(isShadowAtom(mce,a1));
604 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000605 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
606}
607
608static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000609 tl_assert(isShadowAtom(mce,a1));
610 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000611 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
612}
613
614static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000615 tl_assert(isShadowAtom(mce,a1));
616 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000617 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
618}
619
sewardj69f9e3e2004-12-30 02:05:34 +0000620static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
621 tl_assert(isShadowAtom(mce,a1));
622 tl_assert(isShadowAtom(mce,a2));
623 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
624}
625
626static IRAtom* mkDifD128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
627 tl_assert(isShadowAtom(mce,a1));
628 tl_assert(isShadowAtom(mce,a2));
629 return assignNew(mce, Ity_V128, binop(Iop_And128, a1, a2));
630}
631
sewardjde8a5ae2004-11-06 14:20:54 +0000632/* --------- Undefined-if-either-undefined --------- */
633
634static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000635 tl_assert(isShadowAtom(mce,a1));
636 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000637 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
638}
639
640static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000641 tl_assert(isShadowAtom(mce,a1));
642 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000643 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
644}
645
646static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000647 tl_assert(isShadowAtom(mce,a1));
648 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000649 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
650}
651
652static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000653 tl_assert(isShadowAtom(mce,a1));
654 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000655 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
656}
657
sewardj69f9e3e2004-12-30 02:05:34 +0000658static IRAtom* mkUifU128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
659 tl_assert(isShadowAtom(mce,a1));
660 tl_assert(isShadowAtom(mce,a2));
661 return assignNew(mce, Ity_V128, binop(Iop_Or128, a1, a2));
662}
663
664static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000665 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000666 case Ity_I8: return mkUifU8(mce, a1, a2);
667 case Ity_I16: return mkUifU16(mce, a1, a2);
668 case Ity_I32: return mkUifU32(mce, a1, a2);
669 case Ity_I64: return mkUifU64(mce, a1, a2);
670 case Ity_V128: return mkUifU128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000671 default:
672 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000673 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000674 }
675}
676
677/* --------- The Left-family of operations. --------- */
678
679static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000680 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000681 /* It's safe to duplicate a1 since it's only an atom */
682 return assignNew(mce, Ity_I8,
683 binop(Iop_Or8, a1,
684 assignNew(mce, Ity_I8,
685 /* unop(Iop_Neg8, a1)))); */
686 binop(Iop_Sub8, mkU8(0), a1) )));
687}
688
689static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000690 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000691 /* It's safe to duplicate a1 since it's only an atom */
692 return assignNew(mce, Ity_I16,
693 binop(Iop_Or16, a1,
694 assignNew(mce, Ity_I16,
695 /* unop(Iop_Neg16, a1)))); */
696 binop(Iop_Sub16, mkU16(0), a1) )));
697}
698
699static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000700 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000701 /* It's safe to duplicate a1 since it's only an atom */
702 return assignNew(mce, Ity_I32,
703 binop(Iop_Or32, a1,
704 assignNew(mce, Ity_I32,
705 /* unop(Iop_Neg32, a1)))); */
706 binop(Iop_Sub32, mkU32(0), a1) )));
707}
708
709/* --------- 'Improvement' functions for AND/OR. --------- */
710
711/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
712 defined (0); all other -> undefined (1).
713*/
714static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
715{
sewardj69f9e3e2004-12-30 02:05:34 +0000716 tl_assert(isOriginalAtom(mce, data));
717 tl_assert(isShadowAtom(mce, vbits));
718 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000719 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
720}
721
sewardj3598ef92004-11-11 02:13:30 +0000722static IRAtom* mkImproveAND16 ( 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));
sewardj3598ef92004-11-11 02:13:30 +0000727 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
728}
729
sewardjde8a5ae2004-11-06 14:20:54 +0000730static IRAtom* mkImproveAND32 ( 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));
sewardjde8a5ae2004-11-06 14:20:54 +0000735 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
736}
737
sewardj69f9e3e2004-12-30 02:05:34 +0000738static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
739{
740 tl_assert(isOriginalAtom(mce, data));
741 tl_assert(isShadowAtom(mce, vbits));
742 tl_assert(sameKindedAtoms(data, vbits));
743 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
744}
745
746static IRAtom* mkImproveAND128 ( 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_V128, binop(Iop_Or128, data, vbits));
752}
753
sewardjde8a5ae2004-11-06 14:20:54 +0000754/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
755 defined (0); all other -> undefined (1).
756*/
757static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
758{
sewardj69f9e3e2004-12-30 02:05:34 +0000759 tl_assert(isOriginalAtom(mce, data));
760 tl_assert(isShadowAtom(mce, vbits));
761 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000762 return assignNew(
763 mce, Ity_I8,
764 binop(Iop_Or8,
765 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
766 vbits) );
767}
768
769static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
770{
sewardj69f9e3e2004-12-30 02:05:34 +0000771 tl_assert(isOriginalAtom(mce, data));
772 tl_assert(isShadowAtom(mce, vbits));
773 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000774 return assignNew(
775 mce, Ity_I16,
776 binop(Iop_Or16,
777 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
778 vbits) );
779}
780
781static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
782{
sewardj69f9e3e2004-12-30 02:05:34 +0000783 tl_assert(isOriginalAtom(mce, data));
784 tl_assert(isShadowAtom(mce, vbits));
785 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000786 return assignNew(
787 mce, Ity_I32,
788 binop(Iop_Or32,
789 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
790 vbits) );
791}
792
sewardj69f9e3e2004-12-30 02:05:34 +0000793static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
794{
795 tl_assert(isOriginalAtom(mce, data));
796 tl_assert(isShadowAtom(mce, vbits));
797 tl_assert(sameKindedAtoms(data, vbits));
798 return assignNew(
799 mce, Ity_I64,
800 binop(Iop_Or64,
801 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
802 vbits) );
803}
804
805static IRAtom* mkImproveOR128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
806{
807 tl_assert(isOriginalAtom(mce, data));
808 tl_assert(isShadowAtom(mce, vbits));
809 tl_assert(sameKindedAtoms(data, vbits));
810 return assignNew(
811 mce, Ity_V128,
812 binop(Iop_Or128,
813 assignNew(mce, Ity_V128, unop(Iop_Not128, data)),
814 vbits) );
815}
816
sewardjde8a5ae2004-11-06 14:20:54 +0000817/* --------- Pessimising casts. --------- */
818
819static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
820{
sewardj8fc93742004-11-22 11:29:33 +0000821 IRType ty;
822 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000823 /* Note, dst_ty is a shadow type, not an original type. */
824 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000825 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000826 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
827 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000828 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000829 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000830 tmp1 = vbits;
831 break;
832 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000833 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000834 break;
835 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000836 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000837 break;
838 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000839 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000840 break;
841 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000842 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000843 break;
844 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000845 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000846 }
sewardj69f9e3e2004-12-30 02:05:34 +0000847 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000848 /* Now widen up to the dst type. */
849 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000850 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000851 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000852 case Ity_I8:
853 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000854 case Ity_I16:
855 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
856 case Ity_I32:
857 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
858 case Ity_I64:
859 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000860 case Ity_V128:
861 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
862 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLto128, tmp1, tmp1));
863 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000864 default:
865 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000866 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +0000867 }
868}
869
870
871/*------------------------------------------------------------*/
872/*--- Emit a test and complaint if something is undefined. ---*/
873/*------------------------------------------------------------*/
874
875/* Set the annotations on a dirty helper to indicate that the stack
876 pointer and instruction pointers might be read. This is the
877 behaviour of all 'emit-a-complaint' style functions we might
878 call. */
879
880static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
881 di->nFxState = 2;
882 di->fxState[0].fx = Ifx_Read;
883 di->fxState[0].offset = mce->layout->offset_SP;
884 di->fxState[0].size = mce->layout->sizeof_SP;
885 di->fxState[1].fx = Ifx_Read;
886 di->fxState[1].offset = mce->layout->offset_IP;
887 di->fxState[1].size = mce->layout->sizeof_IP;
888}
889
890
891/* Check the supplied **original** atom for undefinedness, and emit a
892 complaint if so. Once that happens, mark it as defined. This is
893 possible because the atom is either a tmp or literal. If it's a
894 tmp, it will be shadowed by a tmp, and so we can set the shadow to
895 be defined. In fact as mentioned above, we will have to allocate a
896 new tmp to carry the new 'defined' shadow value, and update the
897 original->tmp mapping accordingly; we cannot simply assign a new
898 value to an existing shadow tmp as this breaks SSAness -- resulting
899 in the post-instrumentation sanity checker spluttering in disapproval.
900*/
901static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
902{
sewardj8fc93742004-11-22 11:29:33 +0000903 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +0000904 IRType ty;
905 Int sz;
sewardj8fc93742004-11-22 11:29:33 +0000906 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +0000907 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +0000908
sewardjde8a5ae2004-11-06 14:20:54 +0000909 /* Since the original expression is atomic, there's no duplicated
910 work generated by making multiple V-expressions for it. So we
911 don't really care about the possibility that someone else may
912 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +0000913 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +0000914 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +0000915 tl_assert(isShadowAtom(mce, vatom));
916 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +0000917
sewardj8fc93742004-11-22 11:29:33 +0000918 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +0000919
920 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +0000921 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +0000922
sewardj8fc93742004-11-22 11:29:33 +0000923 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +0000924 /* cond will be 0 if all defined, and 1 if any not defined. */
925
sewardj3598ef92004-11-11 02:13:30 +0000926 switch (sz) {
927 case 0:
928 di = unsafeIRDirty_0_N( 0/*regparms*/,
929 "MC_(helperc_value_check0_fail)",
930 &MC_(helperc_value_check0_fail),
931 mkIRExprVec_0()
932 );
933 break;
934 case 1:
935 di = unsafeIRDirty_0_N( 0/*regparms*/,
936 "MC_(helperc_value_check1_fail)",
937 &MC_(helperc_value_check1_fail),
938 mkIRExprVec_0()
939 );
940 break;
941 case 4:
942 di = unsafeIRDirty_0_N( 0/*regparms*/,
943 "MC_(helperc_value_check4_fail)",
944 &MC_(helperc_value_check4_fail),
945 mkIRExprVec_0()
946 );
947 break;
948 default:
949 di = unsafeIRDirty_0_N( 1/*regparms*/,
950 "MC_(helperc_complain_undef)",
951 &MC_(helperc_complain_undef),
952 mkIRExprVec_1( mkIRExpr_HWord( sz ))
953 );
954 break;
955 }
sewardjde8a5ae2004-11-06 14:20:54 +0000956 di->guard = cond;
957 setHelperAnns( mce, di );
958 stmt( mce->bb, IRStmt_Dirty(di));
959
960 /* Set the shadow tmp to be defined. First, update the
961 orig->shadow tmp mapping to reflect the fact that this shadow is
962 getting a new value. */
sewardj69f9e3e2004-12-30 02:05:34 +0000963 tl_assert(isAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +0000964 /* sameKindedAtoms ... */
965 if (vatom->tag == Iex_Tmp) {
sewardj69f9e3e2004-12-30 02:05:34 +0000966 tl_assert(atom->tag == Iex_Tmp);
sewardjde8a5ae2004-11-06 14:20:54 +0000967 newShadowTmp(mce, atom->Iex.Tmp.tmp);
968 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
969 definedOfType(ty));
970 }
971}
972
973
974/*------------------------------------------------------------*/
975/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
976/*------------------------------------------------------------*/
977
978/* Examine the always-defined sections declared in layout to see if
979 the (offset,size) section is within one. Note, is is an error to
980 partially fall into such a region: (offset,size) should either be
981 completely in such a region or completely not-in such a region.
982*/
983static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
984{
985 Int minoffD, maxoffD, i;
986 Int minoff = offset;
987 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +0000988 tl_assert((minoff & ~0xFFFF) == 0);
989 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +0000990
991 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
992 minoffD = mce->layout->alwaysDefd[i].offset;
993 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +0000994 tl_assert((minoffD & ~0xFFFF) == 0);
995 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +0000996
997 if (maxoff < minoffD || maxoffD < minoff)
998 continue; /* no overlap */
999 if (minoff >= minoffD && maxoff <= maxoffD)
1000 return True; /* completely contained in an always-defd section */
1001
sewardj69f9e3e2004-12-30 02:05:34 +00001002 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001003 }
1004 return False; /* could not find any containing section */
1005}
1006
1007
1008/* Generate into bb suitable actions to shadow this Put. If the state
1009 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001010 supplied V bits to the shadow state. We can pass in either an
1011 original atom or a V-atom, but not both. In the former case the
1012 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001013*/
1014static
sewardj3598ef92004-11-11 02:13:30 +00001015void do_shadow_PUT ( MCEnv* mce, Int offset,
1016 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001017{
sewardj8fc93742004-11-22 11:29:33 +00001018 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001019 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001020 tl_assert(!vatom);
1021 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001022 vatom = expr2vbits( mce, atom );
1023 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001024 tl_assert(vatom);
1025 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001026 }
1027
sewardj8fc93742004-11-22 11:29:33 +00001028 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001029 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001030 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1031 /* later: no ... */
1032 /* emit code to emit a complaint if any of the vbits are 1. */
1033 /* complainIfUndefined(mce, atom); */
1034 } else {
1035 /* Do a plain shadow Put. */
1036 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1037 }
1038}
1039
1040
1041/* Return an expression which contains the V bits corresponding to the
1042 given GETI (passed in in pieces).
1043*/
1044static
1045void do_shadow_PUTI ( MCEnv* mce,
1046 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
1047{
sewardj8fc93742004-11-22 11:29:33 +00001048 IRAtom* vatom;
1049 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001050 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001051
sewardj69f9e3e2004-12-30 02:05:34 +00001052 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001053 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001054 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001055 ty = descr->elemTy;
1056 tyS = shadowType(ty);
1057 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001058 tl_assert(ty != Ity_I1);
1059 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001060 complainIfUndefined(mce,ix);
1061 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1062 /* later: no ... */
1063 /* emit code to emit a complaint if any of the vbits are 1. */
1064 /* complainIfUndefined(mce, atom); */
1065 } else {
1066 /* Do a cloned version of the Put that refers to the shadow
1067 area. */
1068 IRArray* new_descr
1069 = mkIRArray( descr->base + mce->layout->total_sizeB,
1070 tyS, descr->nElems);
1071 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1072 }
1073}
1074
1075
1076/* Return an expression which contains the V bits corresponding to the
1077 given GET (passed in in pieces).
1078*/
1079static
1080IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1081{
1082 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001083 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001084 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1085 /* Always defined, return all zeroes of the relevant type */
1086 return definedOfType(tyS);
1087 } else {
1088 /* return a cloned version of the Get that refers to the shadow
1089 area. */
1090 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1091 }
1092}
1093
1094
1095/* Return an expression which contains the V bits corresponding to the
1096 given GETI (passed in in pieces).
1097*/
1098static
1099IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
1100{
1101 IRType ty = descr->elemTy;
1102 IRType tyS = shadowType(ty);
1103 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001104 tl_assert(ty != Ity_I1);
1105 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001106 complainIfUndefined(mce,ix);
1107 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1108 /* Always defined, return all zeroes of the relevant type */
1109 return definedOfType(tyS);
1110 } else {
1111 /* return a cloned version of the Get that refers to the shadow
1112 area. */
1113 IRArray* new_descr
1114 = mkIRArray( descr->base + mce->layout->total_sizeB,
1115 tyS, descr->nElems);
1116 return IRExpr_GetI( new_descr, ix, bias );
1117 }
1118}
1119
1120
1121/*------------------------------------------------------------*/
1122/*--- Generating approximations for unknown operations, ---*/
1123/*--- using lazy-propagate semantics ---*/
1124/*------------------------------------------------------------*/
1125
1126/* Lazy propagation of undefinedness from two values, resulting in the
1127 specified shadow type.
1128*/
1129static
1130IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1131{
1132 /* force everything via 32-bit intermediaries. */
1133 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001134 tl_assert(isShadowAtom(mce,va1));
1135 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001136 at = mkPCastTo(mce, Ity_I32, va1);
1137 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1138 at = mkPCastTo(mce, finalVty, at);
1139 return at;
1140}
1141
1142
1143/* Do the lazy propagation game from a null-terminated vector of
1144 atoms. This is presumably the arguments to a helper call, so the
1145 IRCallee info is also supplied in order that we can know which
1146 arguments should be ignored (via the .mcx_mask field).
1147*/
1148static
1149IRAtom* mkLazyN ( MCEnv* mce,
1150 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1151{
1152 Int i;
1153 IRAtom* here;
1154 IRAtom* curr = definedOfType(Ity_I32);
1155 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001156 tl_assert(i < 32);
1157 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001158 /* Only take notice of this arg if the callee's mc-exclusion
1159 mask does not say it is to be excluded. */
1160 if (cee->mcx_mask & (1<<i)) {
1161 /* the arg is to be excluded from definedness checking. Do
1162 nothing. */
1163 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1164 } else {
1165 /* calculate the arg's definedness, and pessimistically merge
1166 it in. */
1167 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1168 curr = mkUifU32(mce, here, curr);
1169 }
1170 }
1171 return mkPCastTo(mce, finalVtype, curr );
1172}
1173
1174
1175/*------------------------------------------------------------*/
1176/*--- Generating expensive sequences for exact carry-chain ---*/
1177/*--- propagation in add/sub and related operations. ---*/
1178/*------------------------------------------------------------*/
1179
1180static
1181IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1182 IRAtom* aa, IRAtom* bb )
1183{
sewardj69f9e3e2004-12-30 02:05:34 +00001184 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001185 IRType ty;
1186 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001187
sewardj69f9e3e2004-12-30 02:05:34 +00001188 tl_assert(isShadowAtom(mce,qaa));
1189 tl_assert(isShadowAtom(mce,qbb));
1190 tl_assert(isOriginalAtom(mce,aa));
1191 tl_assert(isOriginalAtom(mce,bb));
1192 tl_assert(sameKindedAtoms(qaa,aa));
1193 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001194
sewardj8fc93742004-11-22 11:29:33 +00001195 ty = Ity_I32;
1196 opAND = Iop_And32;
1197 opOR = Iop_Or32;
1198 opXOR = Iop_Xor32;
1199 opNOT = Iop_Not32;
1200 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001201
1202 // a_min = aa & ~qaa
1203 a_min = assignNew(mce,ty,
1204 binop(opAND, aa,
1205 assignNew(mce,ty, unop(opNOT, qaa))));
1206
1207 // b_min = bb & ~qbb
1208 b_min = assignNew(mce,ty,
1209 binop(opAND, bb,
1210 assignNew(mce,ty, unop(opNOT, qbb))));
1211
1212 // a_max = aa | qaa
1213 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1214
1215 // b_max = bb | qbb
1216 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1217
1218 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1219 return
1220 assignNew(mce,ty,
1221 binop( opOR,
1222 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1223 assignNew(mce,ty,
1224 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1225 assignNew(mce,ty, binop(opADD, a_max, b_max))
1226 )
1227 )
1228 )
1229 );
1230}
1231
1232
1233/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001234/*--- Helpers for dealing with vector primops. ---*/
1235/*------------------------------------------------------------*/
1236
1237/* Vector pessimisation -- pessimise within each lane individually. */
1238
1239static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1240{
1241 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1242}
1243
1244static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1245{
1246 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1247}
1248
1249static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1250{
1251 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1252}
1253
1254static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1255{
1256 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1257}
1258
1259
1260/* Here's a simple scheme capable of handling ops derived from SSE1
1261 code and while only generating ops that can be efficiently
1262 implemented in SSE1. */
1263
1264/* All-lanes versions are straightforward:
1265
1266 binary32Fx4(x,y) ==> PCast32x4(UifU128(x#,y#))
1267
1268 unary32Fx4(x,y) ==> PCast32x4(x#)
1269
1270 Lowest-lane-only versions are more complex:
1271
1272 binary32F0x4(x,y) ==> Set128lo32(
1273 x#,
1274 PCast32(128to32(UifU128(x#,y#)))
1275 )
1276
1277 This is perhaps not so obvious. In particular, it's faster to
1278 do a 128-bit UifU and then take the bottom 32 bits than the more
1279 obvious scheme of taking the bottom 32 bits of each operand
1280 and doing a 32-bit UifU. Basically since UifU is fast and
1281 chopping lanes off vector values is slow.
1282
1283 Finally:
1284
1285 unary32F0x4(x) ==> Set128lo32(
1286 x#,
1287 PCast32(128to32(x#))
1288 )
1289
1290 Where:
1291
1292 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1293 PCast32x4(v#) = CmpNEZ32x4(v#)
1294*/
1295
1296static
1297IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1298{
1299 IRAtom* at;
1300 tl_assert(isShadowAtom(mce, vatomX));
1301 tl_assert(isShadowAtom(mce, vatomY));
1302 at = mkUifU128(mce, vatomX, vatomY);
1303 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1304 return at;
1305}
1306
1307static
1308IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1309{
1310 IRAtom* at;
1311 tl_assert(isShadowAtom(mce, vatomX));
1312 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1313 return at;
1314}
1315
1316static
1317IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1318{
1319 IRAtom* at;
1320 tl_assert(isShadowAtom(mce, vatomX));
1321 tl_assert(isShadowAtom(mce, vatomY));
1322 at = mkUifU128(mce, vatomX, vatomY);
1323 at = assignNew(mce, Ity_I32, unop(Iop_128to32, at));
1324 at = mkPCastTo(mce, Ity_I32, at);
1325 at = assignNew(mce, Ity_V128, binop(Iop_Set128lo32, vatomX, at));
1326 return at;
1327}
1328
1329static
1330IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1331{
1332 IRAtom* at;
1333 tl_assert(isShadowAtom(mce, vatomX));
1334 at = assignNew(mce, Ity_I32, unop(Iop_128to32, vatomX));
1335 at = mkPCastTo(mce, Ity_I32, at);
1336 at = assignNew(mce, Ity_V128, binop(Iop_Set128lo32, vatomX, at));
1337 return at;
1338}
1339
1340/* --- ... and ... 64Fx2 versions of the same ... --- */
1341
1342static
1343IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1344{
1345 IRAtom* at;
1346 tl_assert(isShadowAtom(mce, vatomX));
1347 tl_assert(isShadowAtom(mce, vatomY));
1348 at = mkUifU128(mce, vatomX, vatomY);
1349 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1350 return at;
1351}
1352
1353static
1354IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1355{
1356 IRAtom* at;
1357 tl_assert(isShadowAtom(mce, vatomX));
1358 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1359 return at;
1360}
1361
1362static
1363IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1364{
1365 IRAtom* at;
1366 tl_assert(isShadowAtom(mce, vatomX));
1367 tl_assert(isShadowAtom(mce, vatomY));
1368 at = mkUifU128(mce, vatomX, vatomY);
1369 at = assignNew(mce, Ity_I64, unop(Iop_128to64, at));
1370 at = mkPCastTo(mce, Ity_I64, at);
1371 at = assignNew(mce, Ity_V128, binop(Iop_Set128lo64, vatomX, at));
1372 return at;
1373}
1374
1375static
1376IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1377{
1378 IRAtom* at;
1379 tl_assert(isShadowAtom(mce, vatomX));
1380 at = assignNew(mce, Ity_I64, unop(Iop_128to64, vatomX));
1381 at = mkPCastTo(mce, Ity_I64, at);
1382 at = assignNew(mce, Ity_V128, binop(Iop_Set128lo64, vatomX, at));
1383 return at;
1384}
1385
1386/* --- --- Vector saturated narrowing --- --- */
1387
1388/* This is quite subtle. What to do is simple:
1389
1390 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1391
1392 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1393
1394 Why this is right is not so simple. Consider a lane in the args,
1395 vatom1 or 2, doesn't matter.
1396
1397 After the PCast, that lane is all 0s (defined) or all
1398 1s(undefined).
1399
1400 Both signed and unsigned saturating narrowing of all 0s produces
1401 all 0s, which is what we want.
1402
1403 The all-1s case is more complex. Unsigned narrowing interprets an
1404 all-1s input as the largest unsigned integer, and so produces all
1405 1s as a result since that is the largest unsigned value at the
1406 smaller width.
1407
1408 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1409 to -1, so we still wind up with all 1s at the smaller width.
1410
1411 So: In short, pessimise the args, then apply the original narrowing
1412 op.
1413*/
1414static
1415IRAtom* vectorNarrow128 ( MCEnv* mce, IROp narrow_op,
1416 IRAtom* vatom1, IRAtom* vatom2)
1417{
1418 IRAtom *at1, *at2, *at3;
1419 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1420 switch (narrow_op) {
1421 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1422 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1423 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
1424 default: VG_(tool_panic)("vectorNarrow128");
1425 }
1426 tl_assert(isShadowAtom(mce,vatom1));
1427 tl_assert(isShadowAtom(mce,vatom2));
1428 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1429 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1430 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1431 return at3;
1432}
1433
1434
1435/* --- --- Vector integer arithmetic --- --- */
1436
1437/* Simple ... UifU the args and per-lane pessimise the results. */
1438static
1439IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1440{
1441 IRAtom* at;
1442 at = mkUifU128(mce, vatom1, vatom2);
1443 at = mkPCast8x16(mce, at);
1444 return at;
1445}
1446
1447static
1448IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1449{
1450 IRAtom* at;
1451 at = mkUifU128(mce, vatom1, vatom2);
1452 at = mkPCast16x8(mce, at);
1453 return at;
1454}
1455
1456static
1457IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1458{
1459 IRAtom* at;
1460 at = mkUifU128(mce, vatom1, vatom2);
1461 at = mkPCast32x4(mce, at);
1462 return at;
1463}
1464
1465static
1466IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1467{
1468 IRAtom* at;
1469 at = mkUifU128(mce, vatom1, vatom2);
1470 at = mkPCast64x2(mce, at);
1471 return at;
1472}
1473
1474
1475/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001476/*--- Generate shadow values from all kinds of IRExprs. ---*/
1477/*------------------------------------------------------------*/
1478
1479static
1480IRAtom* expr2vbits_Binop ( MCEnv* mce,
1481 IROp op,
1482 IRAtom* atom1, IRAtom* atom2 )
1483{
1484 IRType and_or_ty;
1485 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1486 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1487 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1488
1489 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1490 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1491
sewardj69f9e3e2004-12-30 02:05:34 +00001492 tl_assert(isOriginalAtom(mce,atom1));
1493 tl_assert(isOriginalAtom(mce,atom2));
1494 tl_assert(isShadowAtom(mce,vatom1));
1495 tl_assert(isShadowAtom(mce,vatom2));
1496 tl_assert(sameKindedAtoms(atom1,vatom1));
1497 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001498 switch (op) {
1499
sewardj69f9e3e2004-12-30 02:05:34 +00001500 /* 128-bit SIMD (SSE2-esque) */
1501
1502 case Iop_ShrN16x8:
1503 case Iop_ShrN32x4:
1504 case Iop_ShrN64x2:
1505 case Iop_SarN16x8:
1506 case Iop_SarN32x4:
1507 case Iop_ShlN16x8:
1508 case Iop_ShlN32x4:
1509 case Iop_ShlN64x2:
1510 /* Same scheme as with all other shifts. */
1511 complainIfUndefined(mce, atom2);
1512 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1513
1514 case Iop_QSub8Ux16:
1515 case Iop_QSub8Sx16:
1516 case Iop_Sub8x16:
1517 case Iop_Min8Ux16:
1518 case Iop_Max8Ux16:
1519 case Iop_CmpGT8Sx16:
1520 case Iop_CmpEQ8x16:
1521 case Iop_Avg8Ux16:
1522 case Iop_QAdd8Ux16:
1523 case Iop_QAdd8Sx16:
1524 case Iop_Add8x16:
1525 return binary8Ix16(mce, vatom1, vatom2);
1526
1527 case Iop_QSub16Ux8:
1528 case Iop_QSub16Sx8:
1529 case Iop_Sub16x8:
1530 case Iop_Mul16x8:
1531 case Iop_MulHi16Sx8:
1532 case Iop_MulHi16Ux8:
1533 case Iop_Min16Sx8:
1534 case Iop_Max16Sx8:
1535 case Iop_CmpGT16Sx8:
1536 case Iop_CmpEQ16x8:
1537 case Iop_Avg16Ux8:
1538 case Iop_QAdd16Ux8:
1539 case Iop_QAdd16Sx8:
1540 case Iop_Add16x8:
1541 return binary16Ix8(mce, vatom1, vatom2);
1542
1543 case Iop_Sub32x4:
1544 case Iop_CmpGT32Sx4:
1545 case Iop_CmpEQ32x4:
1546 case Iop_Add32x4:
1547 return binary32Ix4(mce, vatom1, vatom2);
1548
1549 case Iop_Sub64x2:
1550 case Iop_Add64x2:
1551 return binary64Ix2(mce, vatom1, vatom2);
1552
1553 case Iop_QNarrow32Sx4:
1554 case Iop_QNarrow16Sx8:
1555 case Iop_QNarrow16Ux8:
1556 return vectorNarrow128(mce, op, vatom1, vatom2);
1557
1558 case Iop_Sub64Fx2:
1559 case Iop_Mul64Fx2:
1560 case Iop_Min64Fx2:
1561 case Iop_Max64Fx2:
1562 case Iop_Div64Fx2:
1563 case Iop_CmpLT64Fx2:
1564 case Iop_CmpLE64Fx2:
1565 case Iop_CmpEQ64Fx2:
1566 case Iop_Add64Fx2:
1567 return binary64Fx2(mce, vatom1, vatom2);
1568
1569 case Iop_Sub64F0x2:
1570 case Iop_Mul64F0x2:
1571 case Iop_Min64F0x2:
1572 case Iop_Max64F0x2:
1573 case Iop_Div64F0x2:
1574 case Iop_CmpLT64F0x2:
1575 case Iop_CmpLE64F0x2:
1576 case Iop_CmpEQ64F0x2:
1577 case Iop_Add64F0x2:
1578 return binary64F0x2(mce, vatom1, vatom2);
1579
1580 /* 128-bit SIMD (SSE1-esque) */
1581
1582 case Iop_Sub32Fx4:
1583 case Iop_Mul32Fx4:
1584 case Iop_Min32Fx4:
1585 case Iop_Max32Fx4:
1586 case Iop_Div32Fx4:
1587 case Iop_CmpLT32Fx4:
1588 case Iop_CmpLE32Fx4:
1589 case Iop_CmpEQ32Fx4:
1590 case Iop_Add32Fx4:
1591 return binary32Fx4(mce, vatom1, vatom2);
1592
1593 case Iop_Sub32F0x4:
1594 case Iop_Mul32F0x4:
1595 case Iop_Min32F0x4:
1596 case Iop_Max32F0x4:
1597 case Iop_Div32F0x4:
1598 case Iop_CmpLT32F0x4:
1599 case Iop_CmpLE32F0x4:
1600 case Iop_CmpEQ32F0x4:
1601 case Iop_Add32F0x4:
1602 return binary32F0x4(mce, vatom1, vatom2);
1603
1604 /* 128-bit data-steering */
1605 case Iop_Set128lo32:
1606 case Iop_Set128lo64:
1607 case Iop_64HLto128:
1608 case Iop_InterleaveLO64x2:
1609 case Iop_InterleaveLO32x4:
1610 case Iop_InterleaveLO16x8:
1611 case Iop_InterleaveLO8x16:
1612 case Iop_InterleaveHI64x2:
1613 case Iop_InterleaveHI32x4:
1614 case Iop_InterleaveHI16x8:
1615 case Iop_InterleaveHI8x16:
1616 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1617
1618 /* Scalar floating point */
1619
sewardj3598ef92004-11-11 02:13:30 +00001620 case Iop_RoundF64:
1621 case Iop_F64toI64:
sewardj69f9e3e2004-12-30 02:05:34 +00001622 case Iop_I64toF64:
1623 /* First arg is I32 (rounding mode), second is F64 or I64
1624 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001625 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1626
1627 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1628 /* Takes two F64 args. */
sewardjde8a5ae2004-11-06 14:20:54 +00001629 case Iop_F64toI32:
sewardj69f9e3e2004-12-30 02:05:34 +00001630 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001631 /* First arg is I32 (rounding mode), second is F64 (data). */
1632 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1633
1634 case Iop_F64toI16:
1635 /* First arg is I32 (rounding mode), second is F64 (data). */
1636 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1637
sewardj3598ef92004-11-11 02:13:30 +00001638 case Iop_ScaleF64:
1639 case Iop_Yl2xF64:
1640 case Iop_Yl2xp1F64:
1641 case Iop_PRemF64:
1642 case Iop_AtanF64:
1643 case Iop_AddF64:
1644 case Iop_DivF64:
1645 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001646 case Iop_MulF64:
1647 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1648
sewardj3598ef92004-11-11 02:13:30 +00001649 case Iop_CmpF64:
1650 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1651
sewardjde8a5ae2004-11-06 14:20:54 +00001652 /* non-FP after here */
1653
1654 case Iop_DivModU64to32:
1655 case Iop_DivModS64to32:
1656 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1657
sewardj3598ef92004-11-11 02:13:30 +00001658 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001659 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001660 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001661 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001662
1663 case Iop_MullS32:
1664 case Iop_MullU32: {
1665 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1666 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1667 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1668 }
1669
sewardj3598ef92004-11-11 02:13:30 +00001670 case Iop_MullS16:
1671 case Iop_MullU16: {
1672 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1673 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1674 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1675 }
1676
1677 case Iop_MullS8:
1678 case Iop_MullU8: {
1679 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1680 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1681 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1682 }
1683
sewardjde8a5ae2004-11-06 14:20:54 +00001684 case Iop_Add32:
1685# if 0
1686 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1687# endif
1688 case Iop_Sub32:
1689 case Iop_Mul32:
1690 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1691
sewardj3598ef92004-11-11 02:13:30 +00001692 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001693 case Iop_Add16:
1694 case Iop_Sub16:
1695 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1696
1697 case Iop_Sub8:
1698 case Iop_Add8:
1699 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1700
1701 case Iop_CmpLE32S: case Iop_CmpLE32U:
1702 case Iop_CmpLT32U: case Iop_CmpLT32S:
1703 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001704 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001705
sewardj3598ef92004-11-11 02:13:30 +00001706 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001707 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001708
1709 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001710 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001711
1712 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1713 /* Complain if the shift amount is undefined. Then simply
1714 shift the first arg's V bits by the real shift amount. */
1715 complainIfUndefined(mce, atom2);
1716 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1717
sewardj69f9e3e2004-12-30 02:05:34 +00001718 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001719 /* Same scheme as with 32-bit shifts. */
1720 complainIfUndefined(mce, atom2);
1721 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1722
sewardj3598ef92004-11-11 02:13:30 +00001723 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001724 /* Same scheme as with 32-bit shifts. */
1725 complainIfUndefined(mce, atom2);
1726 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1727
1728 case Iop_Shl64: case Iop_Shr64:
1729 /* Same scheme as with 32-bit shifts. */
1730 complainIfUndefined(mce, atom2);
1731 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1732
sewardj69f9e3e2004-12-30 02:05:34 +00001733 case Iop_And128:
1734 uifu = mkUifU128; difd = mkDifD128;
1735 and_or_ty = Ity_V128; improve = mkImproveAND128; goto do_And_Or;
1736 case Iop_And64:
1737 uifu = mkUifU64; difd = mkDifD64;
1738 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001739 case Iop_And32:
1740 uifu = mkUifU32; difd = mkDifD32;
1741 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001742 case Iop_And16:
1743 uifu = mkUifU16; difd = mkDifD16;
1744 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001745 case Iop_And8:
1746 uifu = mkUifU8; difd = mkDifD8;
1747 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1748
sewardj69f9e3e2004-12-30 02:05:34 +00001749 case Iop_Or128:
1750 uifu = mkUifU128; difd = mkDifD128;
1751 and_or_ty = Ity_V128; improve = mkImproveOR128; goto do_And_Or;
1752 case Iop_Or64:
1753 uifu = mkUifU64; difd = mkDifD64;
1754 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001755 case Iop_Or32:
1756 uifu = mkUifU32; difd = mkDifD32;
1757 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1758 case Iop_Or16:
1759 uifu = mkUifU16; difd = mkDifD16;
1760 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1761 case Iop_Or8:
1762 uifu = mkUifU8; difd = mkDifD8;
1763 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1764
1765 do_And_Or:
1766 return
1767 assignNew(
1768 mce,
1769 and_or_ty,
1770 difd(mce, uifu(mce, vatom1, vatom2),
1771 difd(mce, improve(mce, atom1, vatom1),
1772 improve(mce, atom2, vatom2) ) ) );
1773
1774 case Iop_Xor8:
1775 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001776 case Iop_Xor16:
1777 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001778 case Iop_Xor32:
1779 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001780 case Iop_Xor64:
1781 return mkUifU64(mce, vatom1, vatom2);
1782 case Iop_Xor128:
1783 return mkUifU128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001784
1785 default:
1786 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001787 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001788 }
1789}
1790
1791
1792static
1793IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1794{
1795 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001796 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001797 switch (op) {
1798
sewardj69f9e3e2004-12-30 02:05:34 +00001799 case Iop_Sqrt64Fx2:
1800 return unary64Fx2(mce, vatom);
1801
1802 case Iop_Sqrt64F0x2:
1803 return unary64F0x2(mce, vatom);
1804
1805 case Iop_Sqrt32Fx4:
1806 case Iop_RSqrt32Fx4:
1807 case Iop_Recip32Fx4:
1808 return unary32Fx4(mce, vatom);
1809
1810 case Iop_Sqrt32F0x4:
1811 case Iop_RSqrt32F0x4:
1812 case Iop_Recip32F0x4:
1813 return unary32F0x4(mce, vatom);
1814
1815 case Iop_32Uto128:
1816 case Iop_64Uto128:
1817 return assignNew(mce, Ity_V128, unop(op, vatom));
1818
sewardjde8a5ae2004-11-06 14:20:54 +00001819 case Iop_F32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001820 case Iop_I32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001821 case Iop_NegF64:
1822 case Iop_SinF64:
1823 case Iop_CosF64:
1824 case Iop_TanF64:
1825 case Iop_SqrtF64:
1826 case Iop_AbsF64:
1827 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001828 return mkPCastTo(mce, Ity_I64, vatom);
1829
sewardj3598ef92004-11-11 02:13:30 +00001830 case Iop_Clz32:
1831 case Iop_Ctz32:
1832 return mkPCastTo(mce, Ity_I32, vatom);
1833
1834 case Iop_32Sto64:
1835 case Iop_32Uto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001836 case Iop_128to64:
1837 case Iop_128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001838 return assignNew(mce, Ity_I64, unop(op, vatom));
1839
sewardjde8a5ae2004-11-06 14:20:54 +00001840 case Iop_64to32:
1841 case Iop_64HIto32:
1842 case Iop_1Uto32:
1843 case Iop_8Uto32:
1844 case Iop_16Uto32:
1845 case Iop_16Sto32:
1846 case Iop_8Sto32:
1847 return assignNew(mce, Ity_I32, unop(op, vatom));
1848
1849 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001850 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001851 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001852 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001853 return assignNew(mce, Ity_I16, unop(op, vatom));
1854
1855 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001856 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001857 case Iop_32to8:
1858 return assignNew(mce, Ity_I8, unop(op, vatom));
1859
1860 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001861 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001862
sewardj3598ef92004-11-11 02:13:30 +00001863 case Iop_ReinterpF64asI64:
1864 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001865 case Iop_ReinterpI32asF32:
1866 case Iop_Not128:
1867 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00001868 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001869 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001870 case Iop_Not8:
1871 case Iop_Not1:
1872 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001873
sewardjde8a5ae2004-11-06 14:20:54 +00001874 default:
1875 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001876 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00001877 }
1878}
1879
1880
sewardj69f9e3e2004-12-30 02:05:34 +00001881/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00001882static
sewardj69f9e3e2004-12-30 02:05:34 +00001883IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001884{
1885 void* helper;
1886 Char* hname;
1887 IRDirty* di;
1888 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00001889 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001890
sewardj69f9e3e2004-12-30 02:05:34 +00001891 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00001892
1893 /* First, emit a definedness test for the address. This also sets
1894 the address (shadow) to 'defined' following the test. */
1895 complainIfUndefined( mce, addr );
1896
1897 /* Now cook up a call to the relevant helper function, to read the
1898 data V bits from shadow memory. */
1899 ty = shadowType(ty);
1900 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001901 case Ity_I64: helper = &MC_(helperc_LOADV8);
1902 hname = "MC_(helperc_LOADV8)";
1903 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001904 case Ity_I32: helper = &MC_(helperc_LOADV4);
1905 hname = "MC_(helperc_LOADV4)";
1906 break;
1907 case Ity_I16: helper = &MC_(helperc_LOADV2);
1908 hname = "MC_(helperc_LOADV2)";
1909 break;
1910 case Ity_I8: helper = &MC_(helperc_LOADV1);
1911 hname = "MC_(helperc_LOADV1)";
1912 break;
1913 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001914 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00001915 }
1916
sewardj3598ef92004-11-11 02:13:30 +00001917 /* Generate the actual address into addrAct. */
1918 if (bias == 0) {
1919 addrAct = addr;
1920 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001921 IROp mkAdd;
1922 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00001923 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00001924 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
1925 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1926 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00001927 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1928 }
1929
sewardjde8a5ae2004-11-06 14:20:54 +00001930 /* We need to have a place to park the V bits we're just about to
1931 read. */
1932 datavbits = newIRTemp(mce->bb->tyenv, ty);
1933 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00001934 1/*regparms*/, hname, helper,
1935 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00001936 setHelperAnns( mce, di );
1937 stmt( mce->bb, IRStmt_Dirty(di) );
1938
1939 return mkexpr(datavbits);
1940}
1941
1942
1943static
sewardj69f9e3e2004-12-30 02:05:34 +00001944IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
1945{
1946 IRAtom *v64hi, *v64lo;
1947 switch (shadowType(ty)) {
1948 case Ity_I8:
1949 case Ity_I16:
1950 case Ity_I32:
1951 case Ity_I64:
1952 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
1953 case Ity_V128:
1954 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
1955 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
1956 return assignNew( mce,
1957 Ity_V128,
1958 binop(Iop_64HLto128, v64hi, v64lo));
1959 default:
1960 VG_(tool_panic)("expr2vbits_LDle");
1961 }
1962}
1963
1964
1965static
sewardjde8a5ae2004-11-06 14:20:54 +00001966IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00001967 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00001968{
1969 IRAtom *vbitsC, *vbits0, *vbitsX;
1970 IRType ty;
1971 /* Given Mux0X(cond,expr0,exprX), generate
1972 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
1973 That is, steer the V bits like the originals, but trash the
1974 result if the steering value is undefined. This gives
1975 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00001976 tl_assert(isOriginalAtom(mce, cond));
1977 tl_assert(isOriginalAtom(mce, expr0));
1978 tl_assert(isOriginalAtom(mce, exprX));
sewardjde8a5ae2004-11-06 14:20:54 +00001979
1980 vbitsC = expr2vbits(mce, cond);
1981 vbits0 = expr2vbits(mce, expr0);
1982 vbitsX = expr2vbits(mce, exprX);
1983 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
1984
1985 return
1986 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
1987 mkPCastTo(mce, ty, vbitsC) );
1988}
1989
1990/* --------- This is the main expression-handling function. --------- */
1991
1992static
1993IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
1994{
1995 switch (e->tag) {
1996
1997 case Iex_Get:
1998 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
1999
2000 case Iex_GetI:
2001 return shadow_GETI( mce, e->Iex.GetI.descr,
2002 e->Iex.GetI.ix, e->Iex.GetI.bias );
2003
2004 case Iex_Tmp:
2005 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
2006
2007 case Iex_Const:
2008 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2009
2010 case Iex_Binop:
2011 return expr2vbits_Binop(
2012 mce,
2013 e->Iex.Binop.op,
2014 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2015 );
2016
2017 case Iex_Unop:
2018 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2019
2020 case Iex_LDle:
sewardj3598ef92004-11-11 02:13:30 +00002021 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
2022 e->Iex.LDle.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002023
2024 case Iex_CCall:
2025 return mkLazyN( mce, e->Iex.CCall.args,
2026 e->Iex.CCall.retty,
2027 e->Iex.CCall.cee );
2028
2029 case Iex_Mux0X:
2030 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2031 e->Iex.Mux0X.exprX);
2032
2033 default:
2034 VG_(printf)("\n");
2035 ppIRExpr(e);
2036 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002037 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002038 }
2039}
2040
2041/*------------------------------------------------------------*/
2042/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2043/*------------------------------------------------------------*/
2044
2045/* Widen a value to the host word size. */
2046
2047static
2048IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2049{
sewardj69f9e3e2004-12-30 02:05:34 +00002050 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002051
sewardj8fc93742004-11-22 11:29:33 +00002052 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002053 tl_assert(isShadowAtom(mce,vatom));
2054
2055 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2056 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002057
sewardjde8a5ae2004-11-06 14:20:54 +00002058 if (tyH == Ity_I32) {
2059 switch (ty) {
2060 case Ity_I32: return vatom;
2061 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2062 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2063 default: goto unhandled;
2064 }
2065 } else {
2066 goto unhandled;
2067 }
2068 unhandled:
2069 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002070 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002071}
2072
2073
sewardj3598ef92004-11-11 02:13:30 +00002074/* Generate a shadow store. addr is always the original address atom.
2075 You can pass in either originals or V-bits for the data atom, but
2076 obviously not both. */
2077
sewardjde8a5ae2004-11-06 14:20:54 +00002078static
sewardj3598ef92004-11-11 02:13:30 +00002079void do_shadow_STle ( MCEnv* mce,
2080 IRAtom* addr, UInt bias,
2081 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002082{
sewardj69f9e3e2004-12-30 02:05:34 +00002083 IROp mkAdd;
2084 IRType ty, tyAddr;
2085 IRDirty *di, *diLo64, *diHi64;
2086 IRAtom *addrAct, *addrLo64, *addrHi64;
2087 IRAtom *vdataLo64, *vdataHi64;
2088 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002089 void* helper = NULL;
2090 Char* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002091
2092 tyAddr = mce->hWordTy;
2093 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2094 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2095
2096 di = diLo64 = diHi64 = NULL;
2097 eBias = eBias0 = eBias8 = NULL;
2098 addrAct = addrLo64 = addrHi64 = NULL;
2099 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002100
sewardj3598ef92004-11-11 02:13:30 +00002101 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002102 tl_assert(!vdata);
2103 tl_assert(isOriginalAtom(mce, data));
2104 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002105 vdata = expr2vbits( mce, data );
2106 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002107 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002108 }
sewardjde8a5ae2004-11-06 14:20:54 +00002109
sewardj69f9e3e2004-12-30 02:05:34 +00002110 tl_assert(isOriginalAtom(mce,addr));
2111 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002112
2113 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002114
2115 /* First, emit a definedness test for the address. This also sets
2116 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002117 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002118
sewardj69f9e3e2004-12-30 02:05:34 +00002119 /* Now decide which helper function to call to write the data V
2120 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002121 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002122 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002123 case Ity_I64: helper = &MC_(helperc_STOREV8);
2124 hname = "MC_(helperc_STOREV8)";
2125 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002126 case Ity_I32: helper = &MC_(helperc_STOREV4);
2127 hname = "MC_(helperc_STOREV4)";
2128 break;
2129 case Ity_I16: helper = &MC_(helperc_STOREV2);
2130 hname = "MC_(helperc_STOREV2)";
2131 break;
2132 case Ity_I8: helper = &MC_(helperc_STOREV1);
2133 hname = "MC_(helperc_STOREV1)";
2134 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002135 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002136 }
2137
sewardj69f9e3e2004-12-30 02:05:34 +00002138 if (ty == Ity_V128) {
2139
2140 /* 128-bit case */
2141 /* See comment in next clause re 64-bit regparms */
2142 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2143 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
2144 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_128to64, vdata));
2145 diLo64 = unsafeIRDirty_0_N(
2146 1/*regparms*/, hname, helper,
2147 mkIRExprVec_2( addrLo64, vdataLo64 ));
2148
2149 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2150 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
2151 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_128HIto64, vdata));
2152 diHi64 = unsafeIRDirty_0_N(
2153 1/*regparms*/, hname, helper,
2154 mkIRExprVec_2( addrHi64, vdataHi64 ));
2155
2156 setHelperAnns( mce, diLo64 );
2157 setHelperAnns( mce, diHi64 );
2158 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2159 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2160
sewardj3598ef92004-11-11 02:13:30 +00002161 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002162
2163 /* 8/16/32/64-bit cases */
2164 /* Generate the actual address into addrAct. */
2165 if (bias == 0) {
2166 addrAct = addr;
2167 } else {
2168 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2169 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2170 }
2171
2172 if (ty == Ity_I64) {
2173 /* We can't do this with regparm 2 on 32-bit platforms, since
2174 the back ends aren't clever enough to handle 64-bit
2175 regparm args. Therefore be different. */
2176 di = unsafeIRDirty_0_N(
2177 1/*regparms*/, hname, helper,
2178 mkIRExprVec_2( addrAct, vdata ));
2179 } else {
2180 di = unsafeIRDirty_0_N(
2181 2/*regparms*/, hname, helper,
2182 mkIRExprVec_2( addrAct,
2183 zwidenToHostWord( mce, vdata )));
2184 }
2185 setHelperAnns( mce, di );
2186 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002187 }
2188
sewardjde8a5ae2004-11-06 14:20:54 +00002189}
2190
2191
sewardj3598ef92004-11-11 02:13:30 +00002192/* Do lazy pessimistic propagation through a dirty helper call, by
2193 looking at the annotations on it. This is the most complex part of
2194 Memcheck. */
2195
2196static IRType szToITy ( Int n )
2197{
2198 switch (n) {
2199 case 1: return Ity_I8;
2200 case 2: return Ity_I16;
2201 case 4: return Ity_I32;
2202 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002203 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002204 }
2205}
2206
2207static
2208void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2209{
sewardj69f9e3e2004-12-30 02:05:34 +00002210 Int i, n, offset, toDo, gSz, gOff;
2211 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002212 IRType tyAddr, tySrc, tyDst;
2213 IRTemp dst;
2214
2215 /* First check the guard. */
2216 complainIfUndefined(mce, d->guard);
2217
2218 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002219 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002220
2221 /* Inputs: unmasked args */
2222 for (i = 0; d->args[i]; i++) {
2223 if (d->cee->mcx_mask & (1<<i)) {
2224 /* ignore this arg */
2225 } else {
2226 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2227 curr = mkUifU32(mce, here, curr);
2228 }
2229 }
2230
2231 /* Inputs: guest state that we read. */
2232 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002233 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002234 if (d->fxState[i].fx == Ifx_Write)
2235 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002236
2237 /* Ignore any sections marked as 'always defined'. */
2238 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2239 if (0)
2240 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2241 d->fxState[i].offset, d->fxState[i].size );
2242 continue;
2243 }
2244
sewardj3598ef92004-11-11 02:13:30 +00002245 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002246 consider it. If larger than 8 bytes, deal with it in 8-byte
2247 chunks. */
2248 gSz = d->fxState[i].size;
2249 gOff = d->fxState[i].offset;
2250 tl_assert(gSz > 0);
2251 while (True) {
2252 if (gSz == 0) break;
2253 n = gSz <= 8 ? gSz : 8;
2254 /* update 'curr' with UifU of the state slice
2255 gOff .. gOff+n-1 */
2256 tySrc = szToITy( n );
2257 src = assignNew( mce, tySrc,
2258 shadow_GET(mce, gOff, tySrc ) );
2259 here = mkPCastTo( mce, Ity_I32, src );
2260 curr = mkUifU32(mce, here, curr);
2261 gSz -= n;
2262 gOff += n;
2263 }
2264
sewardj3598ef92004-11-11 02:13:30 +00002265 }
2266
2267 /* Inputs: memory. First set up some info needed regardless of
2268 whether we're doing reads or writes. */
2269 tyAddr = Ity_INVALID;
2270
2271 if (d->mFx != Ifx_None) {
2272 /* Because we may do multiple shadow loads/stores from the same
2273 base address, it's best to do a single test of its
2274 definedness right now. Post-instrumentation optimisation
2275 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002276 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002277 complainIfUndefined(mce, d->mAddr);
2278
2279 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002280 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2281 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002282 }
2283
2284 /* Deal with memory inputs (reads or modifies) */
2285 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2286 offset = 0;
2287 toDo = d->mSize;
2288 /* chew off 32-bit chunks */
2289 while (toDo >= 4) {
2290 here = mkPCastTo(
2291 mce, Ity_I32,
2292 expr2vbits_LDle ( mce, Ity_I32,
2293 d->mAddr, d->mSize - toDo )
2294 );
2295 curr = mkUifU32(mce, here, curr);
2296 toDo -= 4;
2297 }
2298 /* chew off 16-bit chunks */
2299 while (toDo >= 2) {
2300 here = mkPCastTo(
2301 mce, Ity_I32,
2302 expr2vbits_LDle ( mce, Ity_I16,
2303 d->mAddr, d->mSize - toDo )
2304 );
2305 curr = mkUifU32(mce, here, curr);
2306 toDo -= 2;
2307 }
sewardj69f9e3e2004-12-30 02:05:34 +00002308 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002309 }
2310
2311 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2312 all the inputs to the helper. Now we need to re-distribute the
2313 results to all destinations. */
2314
2315 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002316 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002317 dst = findShadowTmp(mce, d->tmp);
2318 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2319 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2320 }
2321
2322 /* Outputs: guest state that we write or modify. */
2323 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002324 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002325 if (d->fxState[i].fx == Ifx_Read)
2326 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002327 /* Ignore any sections marked as 'always defined'. */
2328 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2329 continue;
2330 /* This state element is written or modified. So we need to
2331 consider it. If larger than 8 bytes, deal with it in 8-byte
2332 chunks. */
2333 gSz = d->fxState[i].size;
2334 gOff = d->fxState[i].offset;
2335 tl_assert(gSz > 0);
2336 while (True) {
2337 if (gSz == 0) break;
2338 n = gSz <= 8 ? gSz : 8;
2339 /* Write suitably-casted 'curr' to the state slice
2340 gOff .. gOff+n-1 */
2341 tyDst = szToITy( n );
2342 do_shadow_PUT( mce, gOff,
2343 NULL, /* original atom */
2344 mkPCastTo( mce, tyDst, curr ) );
2345 gSz -= n;
2346 gOff += n;
2347 }
sewardj3598ef92004-11-11 02:13:30 +00002348 }
2349
2350 /* Outputs: memory that we write or modify. */
2351 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2352 offset = 0;
2353 toDo = d->mSize;
2354 /* chew off 32-bit chunks */
2355 while (toDo >= 4) {
2356 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2357 NULL, /* original data */
2358 mkPCastTo( mce, Ity_I32, curr ) );
2359 toDo -= 4;
2360 }
2361 /* chew off 16-bit chunks */
2362 while (toDo >= 2) {
2363 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2364 NULL, /* original data */
2365 mkPCastTo( mce, Ity_I16, curr ) );
2366 toDo -= 2;
2367 }
sewardj69f9e3e2004-12-30 02:05:34 +00002368 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002369 }
2370
2371}
2372
2373
sewardjde8a5ae2004-11-06 14:20:54 +00002374/*------------------------------------------------------------*/
2375/*--- Memcheck main ---*/
2376/*------------------------------------------------------------*/
2377
sewardj3598ef92004-11-11 02:13:30 +00002378#if 0 /* UNUSED */
2379static Bool isBogusAtom ( IRAtom* at )
2380{
2381 ULong n = 0;
2382 IRConst* con;
sewardj69f9e3e2004-12-30 02:05:34 +00002383 tl_assert(isAtom(at));
sewardj3598ef92004-11-11 02:13:30 +00002384 if (at->tag == Iex_Tmp)
2385 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002386 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002387 con = at->Iex.Const.con;
2388 switch (con->tag) {
2389 case Ico_U8: n = (ULong)con->Ico.U8; break;
2390 case Ico_U16: n = (ULong)con->Ico.U16; break;
2391 case Ico_U32: n = (ULong)con->Ico.U32; break;
2392 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002393 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002394 }
2395 /* VG_(printf)("%llx\n", n); */
2396 return (n == 0xFEFEFEFF
2397 || n == 0x80808080
2398 || n == 0x1010101
2399 || n == 1010100);
2400}
2401
2402static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2403{
2404 Int i;
2405 IRExpr* e;
2406 switch (st->tag) {
2407 case Ist_Tmp:
2408 e = st->Ist.Tmp.data;
2409 switch (e->tag) {
2410 case Iex_Get:
2411 case Iex_Tmp:
2412 return False;
2413 case Iex_Unop:
2414 return isBogusAtom(e->Iex.Unop.arg);
2415 case Iex_Binop:
2416 return isBogusAtom(e->Iex.Binop.arg1)
2417 || isBogusAtom(e->Iex.Binop.arg2);
2418 case Iex_Mux0X:
2419 return isBogusAtom(e->Iex.Mux0X.cond)
2420 || isBogusAtom(e->Iex.Mux0X.expr0)
2421 || isBogusAtom(e->Iex.Mux0X.exprX);
2422 case Iex_LDle:
2423 return isBogusAtom(e->Iex.LDle.addr);
2424 case Iex_CCall:
2425 for (i = 0; e->Iex.CCall.args[i]; i++)
2426 if (isBogusAtom(e->Iex.CCall.args[i]))
2427 return True;
2428 return False;
2429 default:
2430 goto unhandled;
2431 }
2432 case Ist_Put:
2433 return isBogusAtom(st->Ist.Put.data);
2434 case Ist_STle:
2435 return isBogusAtom(st->Ist.STle.addr)
2436 || isBogusAtom(st->Ist.STle.data);
2437 case Ist_Exit:
sewardj69f9e3e2004-12-30 02:05:34 +00002438 return isBogusAtom(st->Ist.Exit.cond);
sewardj3598ef92004-11-11 02:13:30 +00002439 default:
2440 unhandled:
2441 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002442 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002443 }
2444}
2445#endif /* UNUSED */
2446
2447
sewardjde8a5ae2004-11-06 14:20:54 +00002448IRBB* mc_instrument ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
2449{
sewardj3598ef92004-11-11 02:13:30 +00002450 Bool verboze = False; //True;
2451
2452 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002453
2454 Int i, j, first_stmt;
2455 IRStmt* st;
2456 MCEnv mce;
2457
2458 /* Set up BB */
2459 IRBB* bb = emptyIRBB();
2460 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
2461 bb->next = dopyIRExpr(bb_in->next);
2462 bb->jumpkind = bb_in->jumpkind;
2463
2464 /* Set up the running environment. Only .bb is modified as we go
2465 along. */
2466 mce.bb = bb;
2467 mce.layout = layout;
2468 mce.n_originalTmps = bb->tyenv->types_used;
2469 mce.hWordTy = hWordTy;
2470 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2471 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002472 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002473
2474 /* Iterate over the stmts. */
2475
2476 for (i = 0; i < bb_in->stmts_used; i++) {
2477 st = bb_in->stmts[i];
2478 if (!st) continue;
2479
sewardj69f9e3e2004-12-30 02:05:34 +00002480 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002481
2482 /*
2483 if (!hasBogusLiterals) {
2484 hasBogusLiterals = checkForBogusLiterals(st);
2485 if (hasBogusLiterals) {
2486 VG_(printf)("bogus: ");
2487 ppIRStmt(st);
2488 VG_(printf)("\n");
2489 }
2490 }
2491 */
sewardjde8a5ae2004-11-06 14:20:54 +00002492 first_stmt = bb->stmts_used;
2493
2494 if (verboze) {
2495 ppIRStmt(st);
2496 VG_(printf)("\n\n");
2497 }
2498
2499 switch (st->tag) {
2500
2501 case Ist_Tmp:
2502 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
2503 expr2vbits( &mce, st->Ist.Tmp.data) );
2504 break;
2505
2506 case Ist_Put:
2507 do_shadow_PUT( &mce,
2508 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002509 st->Ist.Put.data,
2510 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002511 break;
2512
2513 case Ist_PutI:
2514 do_shadow_PUTI( &mce,
2515 st->Ist.PutI.descr,
2516 st->Ist.PutI.ix,
2517 st->Ist.PutI.bias,
2518 st->Ist.PutI.data );
2519 break;
2520
2521 case Ist_STle:
sewardj3598ef92004-11-11 02:13:30 +00002522 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
2523 st->Ist.STle.data,
2524 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002525 break;
2526
2527 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002528 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002529 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002530 break;
2531
2532 case Ist_Dirty:
2533 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002534 break;
2535
2536 default:
2537 VG_(printf)("\n");
2538 ppIRStmt(st);
2539 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002540 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002541
2542 } /* switch (st->tag) */
2543
2544 if (verboze) {
2545 for (j = first_stmt; j < bb->stmts_used; j++) {
2546 VG_(printf)(" ");
2547 ppIRStmt(bb->stmts[j]);
2548 VG_(printf)("\n");
2549 }
2550 VG_(printf)("\n");
2551 }
2552
2553 addStmtToIRBB(bb, st);
2554
2555 }
2556
2557 /* Now we need to complain if the jump target is undefined. */
2558 first_stmt = bb->stmts_used;
2559
2560 if (verboze) {
2561 VG_(printf)("bb->next = ");
2562 ppIRExpr(bb->next);
2563 VG_(printf)("\n\n");
2564 }
2565
2566 complainIfUndefined( &mce, bb->next );
2567
2568 if (verboze) {
2569 for (j = first_stmt; j < bb->stmts_used; j++) {
2570 VG_(printf)(" ");
2571 ppIRStmt(bb->stmts[j]);
2572 VG_(printf)("\n");
2573 }
2574 VG_(printf)("\n");
2575 }
2576
2577 return bb;
2578}
2579
2580/*--------------------------------------------------------------------*/
2581/*--- end mc_translate.c ---*/
2582/*--------------------------------------------------------------------*/