blob: c588551432dad282010ef96da323d8e62fd188e9 [file] [log] [blame]
sewardjc97096c2004-06-30 09:28:04 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
4/*--- This file (test_main.c) is ---*/
5/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
6/*--- ---*/
7/*---------------------------------------------------------------*/
8
9#include <stdio.h>
10#include <stdlib.h>
sewardjced9fe52004-07-07 11:55:36 +000011#include <assert.h>
sewardj9b1004e2004-10-30 22:25:40 +000012#include <string.h>
sewardjc97096c2004-06-30 09:28:04 +000013
sewardjced9fe52004-07-07 11:55:36 +000014#include "libvex_basictypes.h"
15#include "libvex.h"
sewardjc97096c2004-06-30 09:28:04 +000016
sewardjabe017e2004-10-29 23:42:36 +000017#include "test_main.h"
18
19
sewardjc97096c2004-06-30 09:28:04 +000020/*---------------------------------------------------------------*/
21/*--- Test ---*/
22/*---------------------------------------------------------------*/
23
sewardjce605f92004-07-05 14:39:15 +000024
sewardj2b515872004-07-05 20:50:45 +000025__attribute__ ((noreturn))
sewardj41f43bc2004-07-08 14:23:22 +000026static
sewardjce605f92004-07-05 14:39:15 +000027void failure_exit ( void )
28{
29 fprintf(stdout, "VEX did failure_exit. Bye.\n");
30 exit(1);
31}
32
sewardj41f43bc2004-07-08 14:23:22 +000033static
sewardjce605f92004-07-05 14:39:15 +000034void log_bytes ( Char* bytes, Int nbytes )
35{
36 fwrite ( bytes, 1, nbytes, stdout );
37}
38
sewardjced9fe52004-07-07 11:55:36 +000039#define N_LINEBUF 10000
sewardj41f43bc2004-07-08 14:23:22 +000040static Char linebuf[N_LINEBUF];
sewardjced9fe52004-07-07 11:55:36 +000041
sewardjf05537e2004-10-14 01:08:12 +000042#define N_ORIGBUF 1000
sewardj4459baa2004-09-10 20:00:46 +000043#define N_TRANSBUF 5000
sewardjced9fe52004-07-07 11:55:36 +000044
sewardj4459baa2004-09-10 20:00:46 +000045static UChar origbuf[N_ORIGBUF];
46static UChar transbuf[N_TRANSBUF];
sewardjced9fe52004-07-07 11:55:36 +000047
sewardj1f40a0a2004-07-21 12:28:07 +000048static Bool verbose = True;
sewardjced9fe52004-07-07 11:55:36 +000049
sewardj9b1004e2004-10-30 22:25:40 +000050/* Forwards */
sewardj9578a8b2004-11-04 19:44:48 +000051static IRBB* ac_instrument ( IRBB*, VexGuestLayout*, IRType );
sewardjde8a5ae2004-11-06 14:20:54 +000052static IRBB* mc_instrument ( IRBB*, VexGuestLayout*, IRType );
sewardj9b1004e2004-10-30 22:25:40 +000053
sewardj5bd4d162004-11-10 13:02:48 +000054static Bool chase_into_not_ok ( Addr64 dst ) { return False; }
sewardj9b1004e2004-10-30 22:25:40 +000055
sewardjced9fe52004-07-07 11:55:36 +000056int main ( int argc, char** argv )
sewardjce605f92004-07-05 14:39:15 +000057{
sewardjced9fe52004-07-07 11:55:36 +000058 FILE* f;
59 Int i;
sewardj4459baa2004-09-10 20:00:46 +000060 UInt u, sum;
sewardjced9fe52004-07-07 11:55:36 +000061 Addr32 orig_addr;
sewardjabe017e2004-10-29 23:42:36 +000062 Int bb_number, n_bbs_done = 0;
sewardjced9fe52004-07-07 11:55:36 +000063 Int orig_nbytes, trans_used, orig_used;
sewardjd887b862005-01-17 18:34:34 +000064 VexTranslateResult tres;
sewardjb5bf2e02004-10-25 13:06:17 +000065 VexControl vcon;
sewardjced9fe52004-07-07 11:55:36 +000066
67 if (argc != 2) {
68 fprintf(stderr, "usage: vex file.org\n");
69 exit(1);
70 }
71 f = fopen(argv[1], "r");
72 if (!f) {
73 fprintf(stderr, "can't open `%s'\n", argv[1]);
74 exit(1);
75 }
76
sewardjb5bf2e02004-10-25 13:06:17 +000077 /* Run with default params. However, we can't allow bb chasing
78 since that causes the front end to get segfaults when it tries
sewardj5bd4d162004-11-10 13:02:48 +000079 to read code outside the initial BB we hand it. So when calling
80 LibVEX_Translate, send in a chase-into predicate that always
81 returns False. */
sewardjb5bf2e02004-10-25 13:06:17 +000082 LibVEX_default_VexControl ( &vcon );
sewardjb4952402004-10-26 13:24:50 +000083 vcon.iropt_level = 2;
sewardjb5bf2e02004-10-25 13:06:17 +000084
sewardjced9fe52004-07-07 11:55:36 +000085 LibVEX_Init ( &failure_exit, &log_bytes,
sewardj1f40a0a2004-07-21 12:28:07 +000086 1, /* debug_paranoia */
sewardjabe017e2004-10-29 23:42:36 +000087 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +000088 &vcon );
sewardjced9fe52004-07-07 11:55:36 +000089
sewardjea64e142004-07-22 16:47:21 +000090
sewardjced9fe52004-07-07 11:55:36 +000091 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +000092
sewardjced9fe52004-07-07 11:55:36 +000093 fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +000094 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +000095 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +000096
97 if (n_bbs_done == TEST_N_BBS) break;
98 n_bbs_done++;
99
sewardjced9fe52004-07-07 11:55:36 +0000100 /* first line is: . bb-number bb-addr n-bytes */
101 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
102 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000103 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000104 assert(orig_nbytes >= 1);
105 assert(!feof(f));
106 fgets(linebuf, N_LINEBUF,f);
107 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000108
sewardjced9fe52004-07-07 11:55:36 +0000109 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000110 if (verbose)
sewardj4459baa2004-09-10 20:00:46 +0000111 printf("============ Basic Block %d, "
112 "Start %x, nbytes %2d ============",
sewardjabe017e2004-10-29 23:42:36 +0000113 n_bbs_done-1, orig_addr, orig_nbytes);
114
sewardjced9fe52004-07-07 11:55:36 +0000115 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
116 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000117 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
118 origbuf[i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000119 }
120
sewardjabe017e2004-10-29 23:42:36 +0000121 for (i = 0; i < TEST_N_ITERS; i++)
122 tres
123 = LibVEX_Translate (
sewardjc3263ee2004-12-29 17:48:22 +0000124 VexArchX86, VexSubArchX86_sse2,
125 VexArchX86, VexSubArchX86_sse2,
sewardj5bd4d162004-11-10 13:02:48 +0000126 origbuf, (Addr64)orig_addr, chase_into_not_ok,
127 &orig_used,
sewardjabe017e2004-10-29 23:42:36 +0000128 transbuf, N_TRANSBUF, &trans_used,
sewardj9e7448b2004-11-18 13:44:15 +0000129#if 1 /* no instrumentation */
130 NULL, /* instrument1 */
131 NULL, /* instrument2 */
132 False, /* cleanup after instrument */
133#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000134#if 0 /* addrcheck */
135 ac_instrument, /* instrument1 */
136 NULL, /* instrument2 */
137 False, /* cleanup after instrument */
138#endif
sewardj9e7448b2004-11-18 13:44:15 +0000139#if 0 /* memcheck */
sewardjde8a5ae2004-11-06 14:20:54 +0000140 mc_instrument, /* instrument1 */
141 NULL, /* instrument2 */
sewardj69f9e3e2004-12-30 02:05:34 +0000142 True, /* cleanup after instrument */
sewardjde8a5ae2004-11-06 14:20:54 +0000143#endif
sewardjabe017e2004-10-29 23:42:36 +0000144 NULL, /* access checker */
145 TEST_FLAGS
146 );
147
sewardjd887b862005-01-17 18:34:34 +0000148 if (tres != VexTransOK)
sewardj4459baa2004-09-10 20:00:46 +0000149 printf("\ntres = %d\n", (Int)tres);
sewardjd887b862005-01-17 18:34:34 +0000150 assert(tres == VexTransOK);
sewardjced9fe52004-07-07 11:55:36 +0000151 assert(orig_used == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000152
sewardj4459baa2004-09-10 20:00:46 +0000153 sum = 0;
154 for (i = 0; i < trans_used; i++)
155 sum += (UInt)transbuf[i];
156 printf ( " %6.2f ... %d\n", (double)trans_used / (double)orig_used, sum );
sewardjced9fe52004-07-07 11:55:36 +0000157 }
158
159 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000160 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000161 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000162
sewardjce605f92004-07-05 14:39:15 +0000163 return 0;
164}
sewardj9b1004e2004-10-30 22:25:40 +0000165
166//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000167//////////////////////////////////////////////////////////////////////
168//////////////////////////////////////////////////////////////////////
169//////////////////////////////////////////////////////////////////////
170//////////////////////////////////////////////////////////////////////
171//////////////////////////////////////////////////////////////////////
172//////////////////////////////////////////////////////////////////////
173//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000174
175static
sewardjde8a5ae2004-11-06 14:20:54 +0000176__attribute((noreturn))
sewardj9b1004e2004-10-30 22:25:40 +0000177void panic ( Char* s )
178{
179 printf("\npanic: %s\n", s);
180 failure_exit();
181}
182
183static
sewardj9578a8b2004-11-04 19:44:48 +0000184IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000185{
186/* Use this rather than eg. -1 because it's a UInt. */
187#define INVALID_DATA_SIZE 999999
188
189 Int i;
190 Int sz;
191 IRCallee* helper;
192 IRStmt* st;
193 IRExpr* data;
194 IRExpr* addr;
195 Bool needSz;
196
197 /* Set up BB */
198 IRBB* bb = emptyIRBB();
199 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
200 bb->next = dopyIRExpr(bb_in->next);
201 bb->jumpkind = bb_in->jumpkind;
202
203 /* No loads to consider in ->next. */
204 assert(isAtom(bb_in->next));
205
206 for (i = 0; i < bb_in->stmts_used; i++) {
207 st = bb_in->stmts[i];
208 if (!st) continue;
209
210 switch (st->tag) {
211
212 case Ist_Tmp:
213 data = st->Ist.Tmp.data;
214 if (data->tag == Iex_LDle) {
215 addr = data->Iex.LDle.addr;
216 sz = sizeofIRType(data->Iex.LDle.ty);
217 needSz = False;
218 switch (sz) {
219 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000220 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000221 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000222 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000223 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000224 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000225 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000226 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000227 needSz = True; break;
228 }
229 if (needSz) {
230 addStmtToIRBB(
231 bb,
232 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000233 unsafeIRDirty_0_N( helper->regparms,
234 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000235 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
236 ));
237 } else {
238 addStmtToIRBB(
239 bb,
240 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000241 unsafeIRDirty_0_N( helper->regparms,
242 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000243 mkIRExprVec_1(addr) )
244 ));
245 }
246 }
247 break;
248
249 case Ist_STle:
250 data = st->Ist.STle.data;
251 addr = st->Ist.STle.addr;
252 assert(isAtom(data));
253 assert(isAtom(addr));
254 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
255 needSz = False;
256 switch (sz) {
257 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000258 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000259 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000260 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000261 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000262 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000263 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000264 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000265 needSz = True; break;
266 }
267 if (needSz) {
268 addStmtToIRBB(
269 bb,
270 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000271 unsafeIRDirty_0_N( helper->regparms,
272 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000273 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
274 ));
275 } else {
276 addStmtToIRBB(
277 bb,
278 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000279 unsafeIRDirty_0_N( helper->regparms,
280 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000281 mkIRExprVec_1(addr) )
282 ));
283 }
284 break;
285
286 case Ist_Put:
287 assert(isAtom(st->Ist.Put.data));
288 break;
289
290 case Ist_PutI:
sewardjeeac8412004-11-02 00:26:55 +0000291 assert(isAtom(st->Ist.PutI.ix));
sewardj9b1004e2004-10-30 22:25:40 +0000292 assert(isAtom(st->Ist.PutI.data));
293 break;
294
295 case Ist_Exit:
sewardj0276d4b2004-11-15 15:30:21 +0000296 assert(isAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000297 break;
298
299 case Ist_Dirty:
300 /* If the call doesn't interact with memory, we ain't
301 interested. */
302 if (st->Ist.Dirty.details->mFx == Ifx_None)
303 break;
304 goto unhandled;
305
306 default:
307 unhandled:
308 printf("\n");
309 ppIRStmt(st);
310 printf("\n");
311 panic("addrcheck: unhandled IRStmt");
312 }
313
314 addStmtToIRBB( bb, dopyIRStmt(st));
315 }
316
317 return bb;
318}
sewardjde8a5ae2004-11-06 14:20:54 +0000319
320//////////////////////////////////////////////////////////////////////
321//////////////////////////////////////////////////////////////////////
322//////////////////////////////////////////////////////////////////////
323//////////////////////////////////////////////////////////////////////
324//////////////////////////////////////////////////////////////////////
325//////////////////////////////////////////////////////////////////////
326//////////////////////////////////////////////////////////////////////
327//////////////////////////////////////////////////////////////////////
328
sewardj69f9e3e2004-12-30 02:05:34 +0000329#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000330#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000331#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000332#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000333#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000334
335void MC_helperc_complain_undef ( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000336void MC_helperc_LOADV8 ( void ) { }
sewardjde8a5ae2004-11-06 14:20:54 +0000337void MC_helperc_LOADV4 ( void ) { }
338void MC_helperc_LOADV2 ( void ) { }
339void MC_helperc_LOADV1 ( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000340void MC_helperc_STOREV8( void ) { }
sewardjde8a5ae2004-11-06 14:20:54 +0000341void MC_helperc_STOREV4( void ) { }
342void MC_helperc_STOREV2( void ) { }
343void MC_helperc_STOREV1( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000344void MC_helperc_value_check0_fail( void ) { }
345void MC_helperc_value_check1_fail( void ) { }
346void MC_helperc_value_check4_fail( void ) { }
347
348
sewardj3598ef92004-11-11 02:13:30 +0000349/*--------------------------------------------------------------------*/
350/*--- Instrument IR to perform memory checking operations. ---*/
351/*--- mc_translate.c ---*/
352/*--------------------------------------------------------------------*/
353
354/*
355 This file is part of MemCheck, a heavyweight Valgrind tool for
356 detecting memory errors.
357
358 Copyright (C) 2000-2004 Julian Seward
359 jseward@acm.org
360
361 This program is free software; you can redistribute it and/or
362 modify it under the terms of the GNU General Public License as
363 published by the Free Software Foundation; either version 2 of the
364 License, or (at your option) any later version.
365
366 This program is distributed in the hope that it will be useful, but
367 WITHOUT ANY WARRANTY; without even the implied warranty of
368 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
369 General Public License for more details.
370
371 You should have received a copy of the GNU General Public License
372 along with this program; if not, write to the Free Software
373 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
374 02111-1307, USA.
375
376 The GNU General Public License is contained in the file COPYING.
377*/
378
379//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000380
381
382/*------------------------------------------------------------*/
383/*--- Forward decls ---*/
384/*------------------------------------------------------------*/
385
386struct _MCEnv;
387
388static IRType shadowType ( IRType ty );
389static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
390
391
392/*------------------------------------------------------------*/
393/*--- Memcheck running state, and tmp management. ---*/
394/*------------------------------------------------------------*/
395
396/* Carries around state during memcheck instrumentation. */
397typedef
398 struct _MCEnv {
399 /* MODIFIED: the bb being constructed. IRStmts are added. */
400 IRBB* bb;
401
402 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
403 original temps to their current their current shadow temp.
404 Initially all entries are IRTemp_INVALID. Entries are added
405 lazily since many original temps are not used due to
406 optimisation prior to instrumentation. Note that floating
407 point original tmps are shadowed by integer tmps of the same
408 size, and Bit-typed original tmps are shadowed by the type
409 Ity_I8. See comment below. */
410 IRTemp* tmpMap;
411 Int n_originalTmps; /* for range checking */
412
413 /* READONLY: the guest layout. This indicates which parts of
414 the guest state should be regarded as 'always defined'. */
415 VexGuestLayout* layout;
416 /* READONLY: the host word type. Needed for constructing
417 arguments of type 'HWord' to be passed to helper functions.
418 Ity_I32 or Ity_I64 only. */
419 IRType hWordTy;
420 }
421 MCEnv;
422
423/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
424 demand), as they are encountered. This is for two reasons.
425
426 (1) (less important reason): Many original tmps are unused due to
427 initial IR optimisation, and we do not want to spaces in tables
428 tracking them.
429
430 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
431 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000432 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000433 It is necessary to support making multiple assignments to a shadow
434 -- specifically, after testing a shadow for definedness, it needs
435 to be made defined. But IR's SSA property disallows this.
436
437 (2) (more important reason): Therefore, when a shadow needs to get
438 a new value, a new temporary is created, the value is assigned to
439 that, and the tmpMap is updated to reflect the new binding.
440
441 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000442 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000443 there's a read-before-write error in the original tmps. The IR
444 sanity checker should catch all such anomalies, however.
445*/
446
447/* Find the tmp currently shadowing the given original tmp. If none
448 so far exists, allocate one. */
449static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
450{
sewardj69f9e3e2004-12-30 02:05:34 +0000451 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000452 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000453 mce->tmpMap[orig]
454 = newIRTemp(mce->bb->tyenv,
455 shadowType(mce->bb->tyenv->types[orig]));
456 }
457 return mce->tmpMap[orig];
458}
459
460/* Allocate a new shadow for the given original tmp. This means any
461 previous shadow is abandoned. This is needed because it is
462 necessary to give a new value to a shadow once it has been tested
463 for undefinedness, but unfortunately IR's SSA property disallows
464 this. Instead we must abandon the old shadow, allocate a new one
465 and use that instead. */
466static void newShadowTmp ( MCEnv* mce, IRTemp orig )
467{
sewardj69f9e3e2004-12-30 02:05:34 +0000468 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000469 mce->tmpMap[orig]
470 = newIRTemp(mce->bb->tyenv,
471 shadowType(mce->bb->tyenv->types[orig]));
472}
473
474
475/*------------------------------------------------------------*/
476/*--- IRAtoms -- a subset of IRExprs ---*/
477/*------------------------------------------------------------*/
478
479/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
480 isAtom() in libvex_ir.h. Because this instrumenter expects flat
481 input, most of this code deals in atoms. Usefully, a value atom
482 always has a V-value which is also an atom: constants are shadowed
483 by constants, and temps are shadowed by the corresponding shadow
484 temporary. */
485
486typedef IRExpr IRAtom;
487
488/* (used for sanity checks only): is this an atom which looks
489 like it's from original code? */
490static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
491{
492 if (a1->tag == Iex_Const)
493 return True;
494 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
495 return True;
496 return False;
497}
498
499/* (used for sanity checks only): is this an atom which looks
500 like it's from shadow code? */
501static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
502{
503 if (a1->tag == Iex_Const)
504 return True;
505 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
506 return True;
507 return False;
508}
509
510/* (used for sanity checks only): check that both args are atoms and
511 are identically-kinded. */
512static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
513{
514 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
515 return True;
516 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
517 return True;
518 return False;
519}
520
521
522/*------------------------------------------------------------*/
523/*--- Type management ---*/
524/*------------------------------------------------------------*/
525
526/* Shadow state is always accessed using integer types. This returns
527 an integer type with the same size (as per sizeofIRType) as the
528 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000529 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000530
531static IRType shadowType ( IRType ty )
532{
533 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000534 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000535 case Ity_I8:
536 case Ity_I16:
537 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000538 case Ity_I64: return ty;
539 case Ity_F32: return Ity_I32;
540 case Ity_F64: return Ity_I64;
541 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000542 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000543 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000544 }
545}
546
547/* Produce a 'defined' value of the given shadow type. Should only be
548 supplied shadow types (Bit/I8/I16/I32/UI64). */
549static IRExpr* definedOfType ( IRType ty ) {
550 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000551 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
552 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
553 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
554 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
555 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
556 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
557 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000558 }
559}
560
561
562/*------------------------------------------------------------*/
563/*--- Constructing IR fragments ---*/
564/*------------------------------------------------------------*/
565
566/* assign value to tmp */
567#define assign(_bb,_tmp,_expr) \
568 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
569
570/* add stmt to a bb */
571#define stmt(_bb,_stmt) \
572 addStmtToIRBB((_bb), (_stmt))
573
574/* build various kinds of expressions */
575#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
576#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
577#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
578#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
579#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
580#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000581#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardjde8a5ae2004-11-06 14:20:54 +0000582#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
583
584/* bind the given expression to a new temporary, and return the
585 temporary. This effectively converts an arbitrary expression into
586 an atom. */
587static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
588 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
589 assign(mce->bb, t, e);
590 return mkexpr(t);
591}
592
593
594/*------------------------------------------------------------*/
595/*--- Constructing definedness primitive ops ---*/
596/*------------------------------------------------------------*/
597
598/* --------- Defined-if-either-defined --------- */
599
600static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000601 tl_assert(isShadowAtom(mce,a1));
602 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000603 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
604}
605
606static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000607 tl_assert(isShadowAtom(mce,a1));
608 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000609 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
610}
611
612static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000613 tl_assert(isShadowAtom(mce,a1));
614 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000615 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
616}
617
sewardj69f9e3e2004-12-30 02:05:34 +0000618static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
619 tl_assert(isShadowAtom(mce,a1));
620 tl_assert(isShadowAtom(mce,a2));
621 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
622}
623
624static IRAtom* mkDifD128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
625 tl_assert(isShadowAtom(mce,a1));
626 tl_assert(isShadowAtom(mce,a2));
627 return assignNew(mce, Ity_V128, binop(Iop_And128, a1, a2));
628}
629
sewardjde8a5ae2004-11-06 14:20:54 +0000630/* --------- Undefined-if-either-undefined --------- */
631
632static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000633 tl_assert(isShadowAtom(mce,a1));
634 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000635 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
636}
637
638static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000639 tl_assert(isShadowAtom(mce,a1));
640 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000641 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
642}
643
644static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000645 tl_assert(isShadowAtom(mce,a1));
646 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000647 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
648}
649
650static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000651 tl_assert(isShadowAtom(mce,a1));
652 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000653 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
654}
655
sewardj69f9e3e2004-12-30 02:05:34 +0000656static IRAtom* mkUifU128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
657 tl_assert(isShadowAtom(mce,a1));
658 tl_assert(isShadowAtom(mce,a2));
659 return assignNew(mce, Ity_V128, binop(Iop_Or128, a1, a2));
660}
661
662static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000663 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000664 case Ity_I8: return mkUifU8(mce, a1, a2);
665 case Ity_I16: return mkUifU16(mce, a1, a2);
666 case Ity_I32: return mkUifU32(mce, a1, a2);
667 case Ity_I64: return mkUifU64(mce, a1, a2);
668 case Ity_V128: return mkUifU128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000669 default:
670 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000671 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000672 }
673}
674
675/* --------- The Left-family of operations. --------- */
676
677static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000678 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000679 /* It's safe to duplicate a1 since it's only an atom */
680 return assignNew(mce, Ity_I8,
681 binop(Iop_Or8, a1,
682 assignNew(mce, Ity_I8,
683 /* unop(Iop_Neg8, a1)))); */
684 binop(Iop_Sub8, mkU8(0), a1) )));
685}
686
687static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000688 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000689 /* It's safe to duplicate a1 since it's only an atom */
690 return assignNew(mce, Ity_I16,
691 binop(Iop_Or16, a1,
692 assignNew(mce, Ity_I16,
693 /* unop(Iop_Neg16, a1)))); */
694 binop(Iop_Sub16, mkU16(0), a1) )));
695}
696
697static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000698 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000699 /* It's safe to duplicate a1 since it's only an atom */
700 return assignNew(mce, Ity_I32,
701 binop(Iop_Or32, a1,
702 assignNew(mce, Ity_I32,
703 /* unop(Iop_Neg32, a1)))); */
704 binop(Iop_Sub32, mkU32(0), a1) )));
705}
706
707/* --------- 'Improvement' functions for AND/OR. --------- */
708
709/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
710 defined (0); all other -> undefined (1).
711*/
712static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
713{
sewardj69f9e3e2004-12-30 02:05:34 +0000714 tl_assert(isOriginalAtom(mce, data));
715 tl_assert(isShadowAtom(mce, vbits));
716 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000717 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
718}
719
sewardj3598ef92004-11-11 02:13:30 +0000720static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
721{
sewardj69f9e3e2004-12-30 02:05:34 +0000722 tl_assert(isOriginalAtom(mce, data));
723 tl_assert(isShadowAtom(mce, vbits));
724 tl_assert(sameKindedAtoms(data, vbits));
sewardj3598ef92004-11-11 02:13:30 +0000725 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
726}
727
sewardjde8a5ae2004-11-06 14:20:54 +0000728static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
729{
sewardj69f9e3e2004-12-30 02:05:34 +0000730 tl_assert(isOriginalAtom(mce, data));
731 tl_assert(isShadowAtom(mce, vbits));
732 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000733 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
734}
735
sewardj69f9e3e2004-12-30 02:05:34 +0000736static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
737{
738 tl_assert(isOriginalAtom(mce, data));
739 tl_assert(isShadowAtom(mce, vbits));
740 tl_assert(sameKindedAtoms(data, vbits));
741 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
742}
743
744static IRAtom* mkImproveAND128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
745{
746 tl_assert(isOriginalAtom(mce, data));
747 tl_assert(isShadowAtom(mce, vbits));
748 tl_assert(sameKindedAtoms(data, vbits));
749 return assignNew(mce, Ity_V128, binop(Iop_Or128, data, vbits));
750}
751
sewardjde8a5ae2004-11-06 14:20:54 +0000752/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
753 defined (0); all other -> undefined (1).
754*/
755static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
756{
sewardj69f9e3e2004-12-30 02:05:34 +0000757 tl_assert(isOriginalAtom(mce, data));
758 tl_assert(isShadowAtom(mce, vbits));
759 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000760 return assignNew(
761 mce, Ity_I8,
762 binop(Iop_Or8,
763 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
764 vbits) );
765}
766
767static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
768{
sewardj69f9e3e2004-12-30 02:05:34 +0000769 tl_assert(isOriginalAtom(mce, data));
770 tl_assert(isShadowAtom(mce, vbits));
771 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000772 return assignNew(
773 mce, Ity_I16,
774 binop(Iop_Or16,
775 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
776 vbits) );
777}
778
779static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
780{
sewardj69f9e3e2004-12-30 02:05:34 +0000781 tl_assert(isOriginalAtom(mce, data));
782 tl_assert(isShadowAtom(mce, vbits));
783 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000784 return assignNew(
785 mce, Ity_I32,
786 binop(Iop_Or32,
787 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
788 vbits) );
789}
790
sewardj69f9e3e2004-12-30 02:05:34 +0000791static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
792{
793 tl_assert(isOriginalAtom(mce, data));
794 tl_assert(isShadowAtom(mce, vbits));
795 tl_assert(sameKindedAtoms(data, vbits));
796 return assignNew(
797 mce, Ity_I64,
798 binop(Iop_Or64,
799 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
800 vbits) );
801}
802
803static IRAtom* mkImproveOR128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
804{
805 tl_assert(isOriginalAtom(mce, data));
806 tl_assert(isShadowAtom(mce, vbits));
807 tl_assert(sameKindedAtoms(data, vbits));
808 return assignNew(
809 mce, Ity_V128,
810 binop(Iop_Or128,
811 assignNew(mce, Ity_V128, unop(Iop_Not128, data)),
812 vbits) );
813}
814
sewardjde8a5ae2004-11-06 14:20:54 +0000815/* --------- Pessimising casts. --------- */
816
817static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
818{
sewardj8fc93742004-11-22 11:29:33 +0000819 IRType ty;
820 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000821 /* Note, dst_ty is a shadow type, not an original type. */
822 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000823 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000824 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
825 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000826 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000827 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000828 tmp1 = vbits;
829 break;
830 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000831 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000832 break;
833 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000834 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000835 break;
836 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000837 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000838 break;
839 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000840 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000841 break;
842 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000843 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000844 }
sewardj69f9e3e2004-12-30 02:05:34 +0000845 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000846 /* Now widen up to the dst type. */
847 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000848 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000849 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000850 case Ity_I8:
851 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000852 case Ity_I16:
853 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
854 case Ity_I32:
855 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
856 case Ity_I64:
857 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000858 case Ity_V128:
859 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
860 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLto128, tmp1, tmp1));
861 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000862 default:
863 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000864 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +0000865 }
866}
867
868
869/*------------------------------------------------------------*/
870/*--- Emit a test and complaint if something is undefined. ---*/
871/*------------------------------------------------------------*/
872
873/* Set the annotations on a dirty helper to indicate that the stack
874 pointer and instruction pointers might be read. This is the
875 behaviour of all 'emit-a-complaint' style functions we might
876 call. */
877
878static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
879 di->nFxState = 2;
880 di->fxState[0].fx = Ifx_Read;
881 di->fxState[0].offset = mce->layout->offset_SP;
882 di->fxState[0].size = mce->layout->sizeof_SP;
883 di->fxState[1].fx = Ifx_Read;
884 di->fxState[1].offset = mce->layout->offset_IP;
885 di->fxState[1].size = mce->layout->sizeof_IP;
886}
887
888
889/* Check the supplied **original** atom for undefinedness, and emit a
890 complaint if so. Once that happens, mark it as defined. This is
891 possible because the atom is either a tmp or literal. If it's a
892 tmp, it will be shadowed by a tmp, and so we can set the shadow to
893 be defined. In fact as mentioned above, we will have to allocate a
894 new tmp to carry the new 'defined' shadow value, and update the
895 original->tmp mapping accordingly; we cannot simply assign a new
896 value to an existing shadow tmp as this breaks SSAness -- resulting
897 in the post-instrumentation sanity checker spluttering in disapproval.
898*/
899static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
900{
sewardj8fc93742004-11-22 11:29:33 +0000901 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +0000902 IRType ty;
903 Int sz;
sewardj8fc93742004-11-22 11:29:33 +0000904 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +0000905 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +0000906
sewardjde8a5ae2004-11-06 14:20:54 +0000907 /* Since the original expression is atomic, there's no duplicated
908 work generated by making multiple V-expressions for it. So we
909 don't really care about the possibility that someone else may
910 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +0000911 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +0000912 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +0000913 tl_assert(isShadowAtom(mce, vatom));
914 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +0000915
sewardj8fc93742004-11-22 11:29:33 +0000916 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +0000917
918 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +0000919 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +0000920
sewardj8fc93742004-11-22 11:29:33 +0000921 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +0000922 /* cond will be 0 if all defined, and 1 if any not defined. */
923
sewardj3598ef92004-11-11 02:13:30 +0000924 switch (sz) {
925 case 0:
926 di = unsafeIRDirty_0_N( 0/*regparms*/,
927 "MC_(helperc_value_check0_fail)",
928 &MC_(helperc_value_check0_fail),
929 mkIRExprVec_0()
930 );
931 break;
932 case 1:
933 di = unsafeIRDirty_0_N( 0/*regparms*/,
934 "MC_(helperc_value_check1_fail)",
935 &MC_(helperc_value_check1_fail),
936 mkIRExprVec_0()
937 );
938 break;
939 case 4:
940 di = unsafeIRDirty_0_N( 0/*regparms*/,
941 "MC_(helperc_value_check4_fail)",
942 &MC_(helperc_value_check4_fail),
943 mkIRExprVec_0()
944 );
945 break;
946 default:
947 di = unsafeIRDirty_0_N( 1/*regparms*/,
948 "MC_(helperc_complain_undef)",
949 &MC_(helperc_complain_undef),
950 mkIRExprVec_1( mkIRExpr_HWord( sz ))
951 );
952 break;
953 }
sewardjde8a5ae2004-11-06 14:20:54 +0000954 di->guard = cond;
955 setHelperAnns( mce, di );
956 stmt( mce->bb, IRStmt_Dirty(di));
957
958 /* Set the shadow tmp to be defined. First, update the
959 orig->shadow tmp mapping to reflect the fact that this shadow is
960 getting a new value. */
sewardj69f9e3e2004-12-30 02:05:34 +0000961 tl_assert(isAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +0000962 /* sameKindedAtoms ... */
963 if (vatom->tag == Iex_Tmp) {
sewardj69f9e3e2004-12-30 02:05:34 +0000964 tl_assert(atom->tag == Iex_Tmp);
sewardjde8a5ae2004-11-06 14:20:54 +0000965 newShadowTmp(mce, atom->Iex.Tmp.tmp);
966 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
967 definedOfType(ty));
968 }
969}
970
971
972/*------------------------------------------------------------*/
973/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
974/*------------------------------------------------------------*/
975
976/* Examine the always-defined sections declared in layout to see if
977 the (offset,size) section is within one. Note, is is an error to
978 partially fall into such a region: (offset,size) should either be
979 completely in such a region or completely not-in such a region.
980*/
981static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
982{
983 Int minoffD, maxoffD, i;
984 Int minoff = offset;
985 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +0000986 tl_assert((minoff & ~0xFFFF) == 0);
987 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +0000988
989 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
990 minoffD = mce->layout->alwaysDefd[i].offset;
991 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +0000992 tl_assert((minoffD & ~0xFFFF) == 0);
993 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +0000994
995 if (maxoff < minoffD || maxoffD < minoff)
996 continue; /* no overlap */
997 if (minoff >= minoffD && maxoff <= maxoffD)
998 return True; /* completely contained in an always-defd section */
999
sewardj69f9e3e2004-12-30 02:05:34 +00001000 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001001 }
1002 return False; /* could not find any containing section */
1003}
1004
1005
1006/* Generate into bb suitable actions to shadow this Put. If the state
1007 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001008 supplied V bits to the shadow state. We can pass in either an
1009 original atom or a V-atom, but not both. In the former case the
1010 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001011*/
1012static
sewardj3598ef92004-11-11 02:13:30 +00001013void do_shadow_PUT ( MCEnv* mce, Int offset,
1014 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001015{
sewardj8fc93742004-11-22 11:29:33 +00001016 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001017 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001018 tl_assert(!vatom);
1019 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001020 vatom = expr2vbits( mce, atom );
1021 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001022 tl_assert(vatom);
1023 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001024 }
1025
sewardj8fc93742004-11-22 11:29:33 +00001026 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001027 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001028 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1029 /* later: no ... */
1030 /* emit code to emit a complaint if any of the vbits are 1. */
1031 /* complainIfUndefined(mce, atom); */
1032 } else {
1033 /* Do a plain shadow Put. */
1034 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1035 }
1036}
1037
1038
1039/* Return an expression which contains the V bits corresponding to the
1040 given GETI (passed in in pieces).
1041*/
1042static
1043void do_shadow_PUTI ( MCEnv* mce,
1044 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
1045{
sewardj8fc93742004-11-22 11:29:33 +00001046 IRAtom* vatom;
1047 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001048 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001049
sewardj69f9e3e2004-12-30 02:05:34 +00001050 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001051 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001052 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001053 ty = descr->elemTy;
1054 tyS = shadowType(ty);
1055 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001056 tl_assert(ty != Ity_I1);
1057 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001058 complainIfUndefined(mce,ix);
1059 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1060 /* later: no ... */
1061 /* emit code to emit a complaint if any of the vbits are 1. */
1062 /* complainIfUndefined(mce, atom); */
1063 } else {
1064 /* Do a cloned version of the Put that refers to the shadow
1065 area. */
1066 IRArray* new_descr
1067 = mkIRArray( descr->base + mce->layout->total_sizeB,
1068 tyS, descr->nElems);
1069 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1070 }
1071}
1072
1073
1074/* Return an expression which contains the V bits corresponding to the
1075 given GET (passed in in pieces).
1076*/
1077static
1078IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1079{
1080 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001081 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001082 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1083 /* Always defined, return all zeroes of the relevant type */
1084 return definedOfType(tyS);
1085 } else {
1086 /* return a cloned version of the Get that refers to the shadow
1087 area. */
1088 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1089 }
1090}
1091
1092
1093/* Return an expression which contains the V bits corresponding to the
1094 given GETI (passed in in pieces).
1095*/
1096static
1097IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
1098{
1099 IRType ty = descr->elemTy;
1100 IRType tyS = shadowType(ty);
1101 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001102 tl_assert(ty != Ity_I1);
1103 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001104 complainIfUndefined(mce,ix);
1105 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1106 /* Always defined, return all zeroes of the relevant type */
1107 return definedOfType(tyS);
1108 } else {
1109 /* return a cloned version of the Get that refers to the shadow
1110 area. */
1111 IRArray* new_descr
1112 = mkIRArray( descr->base + mce->layout->total_sizeB,
1113 tyS, descr->nElems);
1114 return IRExpr_GetI( new_descr, ix, bias );
1115 }
1116}
1117
1118
1119/*------------------------------------------------------------*/
1120/*--- Generating approximations for unknown operations, ---*/
1121/*--- using lazy-propagate semantics ---*/
1122/*------------------------------------------------------------*/
1123
1124/* Lazy propagation of undefinedness from two values, resulting in the
1125 specified shadow type.
1126*/
1127static
1128IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1129{
1130 /* force everything via 32-bit intermediaries. */
1131 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001132 tl_assert(isShadowAtom(mce,va1));
1133 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001134 at = mkPCastTo(mce, Ity_I32, va1);
1135 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1136 at = mkPCastTo(mce, finalVty, at);
1137 return at;
1138}
1139
1140
1141/* Do the lazy propagation game from a null-terminated vector of
1142 atoms. This is presumably the arguments to a helper call, so the
1143 IRCallee info is also supplied in order that we can know which
1144 arguments should be ignored (via the .mcx_mask field).
1145*/
1146static
1147IRAtom* mkLazyN ( MCEnv* mce,
1148 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1149{
1150 Int i;
1151 IRAtom* here;
1152 IRAtom* curr = definedOfType(Ity_I32);
1153 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001154 tl_assert(i < 32);
1155 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001156 /* Only take notice of this arg if the callee's mc-exclusion
1157 mask does not say it is to be excluded. */
1158 if (cee->mcx_mask & (1<<i)) {
1159 /* the arg is to be excluded from definedness checking. Do
1160 nothing. */
1161 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1162 } else {
1163 /* calculate the arg's definedness, and pessimistically merge
1164 it in. */
1165 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1166 curr = mkUifU32(mce, here, curr);
1167 }
1168 }
1169 return mkPCastTo(mce, finalVtype, curr );
1170}
1171
1172
1173/*------------------------------------------------------------*/
1174/*--- Generating expensive sequences for exact carry-chain ---*/
1175/*--- propagation in add/sub and related operations. ---*/
1176/*------------------------------------------------------------*/
1177
1178static
1179IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1180 IRAtom* aa, IRAtom* bb )
1181{
sewardj69f9e3e2004-12-30 02:05:34 +00001182 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001183 IRType ty;
1184 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001185
sewardj69f9e3e2004-12-30 02:05:34 +00001186 tl_assert(isShadowAtom(mce,qaa));
1187 tl_assert(isShadowAtom(mce,qbb));
1188 tl_assert(isOriginalAtom(mce,aa));
1189 tl_assert(isOriginalAtom(mce,bb));
1190 tl_assert(sameKindedAtoms(qaa,aa));
1191 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001192
sewardj8fc93742004-11-22 11:29:33 +00001193 ty = Ity_I32;
1194 opAND = Iop_And32;
1195 opOR = Iop_Or32;
1196 opXOR = Iop_Xor32;
1197 opNOT = Iop_Not32;
1198 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001199
1200 // a_min = aa & ~qaa
1201 a_min = assignNew(mce,ty,
1202 binop(opAND, aa,
1203 assignNew(mce,ty, unop(opNOT, qaa))));
1204
1205 // b_min = bb & ~qbb
1206 b_min = assignNew(mce,ty,
1207 binop(opAND, bb,
1208 assignNew(mce,ty, unop(opNOT, qbb))));
1209
1210 // a_max = aa | qaa
1211 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1212
1213 // b_max = bb | qbb
1214 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1215
1216 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1217 return
1218 assignNew(mce,ty,
1219 binop( opOR,
1220 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1221 assignNew(mce,ty,
1222 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1223 assignNew(mce,ty, binop(opADD, a_max, b_max))
1224 )
1225 )
1226 )
1227 );
1228}
1229
1230
1231/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001232/*--- Helpers for dealing with vector primops. ---*/
1233/*------------------------------------------------------------*/
1234
1235/* Vector pessimisation -- pessimise within each lane individually. */
1236
1237static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1238{
1239 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1240}
1241
1242static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1243{
1244 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1245}
1246
1247static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1248{
1249 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1250}
1251
1252static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1253{
1254 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1255}
1256
1257
1258/* Here's a simple scheme capable of handling ops derived from SSE1
1259 code and while only generating ops that can be efficiently
1260 implemented in SSE1. */
1261
1262/* All-lanes versions are straightforward:
1263
1264 binary32Fx4(x,y) ==> PCast32x4(UifU128(x#,y#))
1265
1266 unary32Fx4(x,y) ==> PCast32x4(x#)
1267
1268 Lowest-lane-only versions are more complex:
1269
1270 binary32F0x4(x,y) ==> Set128lo32(
1271 x#,
1272 PCast32(128to32(UifU128(x#,y#)))
1273 )
1274
1275 This is perhaps not so obvious. In particular, it's faster to
1276 do a 128-bit UifU and then take the bottom 32 bits than the more
1277 obvious scheme of taking the bottom 32 bits of each operand
1278 and doing a 32-bit UifU. Basically since UifU is fast and
1279 chopping lanes off vector values is slow.
1280
1281 Finally:
1282
1283 unary32F0x4(x) ==> Set128lo32(
1284 x#,
1285 PCast32(128to32(x#))
1286 )
1287
1288 Where:
1289
1290 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1291 PCast32x4(v#) = CmpNEZ32x4(v#)
1292*/
1293
1294static
1295IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1296{
1297 IRAtom* at;
1298 tl_assert(isShadowAtom(mce, vatomX));
1299 tl_assert(isShadowAtom(mce, vatomY));
1300 at = mkUifU128(mce, vatomX, vatomY);
1301 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1302 return at;
1303}
1304
1305static
1306IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1307{
1308 IRAtom* at;
1309 tl_assert(isShadowAtom(mce, vatomX));
1310 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1311 return at;
1312}
1313
1314static
1315IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1316{
1317 IRAtom* at;
1318 tl_assert(isShadowAtom(mce, vatomX));
1319 tl_assert(isShadowAtom(mce, vatomY));
1320 at = mkUifU128(mce, vatomX, vatomY);
1321 at = assignNew(mce, Ity_I32, unop(Iop_128to32, at));
1322 at = mkPCastTo(mce, Ity_I32, at);
1323 at = assignNew(mce, Ity_V128, binop(Iop_Set128lo32, vatomX, at));
1324 return at;
1325}
1326
1327static
1328IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1329{
1330 IRAtom* at;
1331 tl_assert(isShadowAtom(mce, vatomX));
1332 at = assignNew(mce, Ity_I32, unop(Iop_128to32, vatomX));
1333 at = mkPCastTo(mce, Ity_I32, at);
1334 at = assignNew(mce, Ity_V128, binop(Iop_Set128lo32, vatomX, at));
1335 return at;
1336}
1337
1338/* --- ... and ... 64Fx2 versions of the same ... --- */
1339
1340static
1341IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1342{
1343 IRAtom* at;
1344 tl_assert(isShadowAtom(mce, vatomX));
1345 tl_assert(isShadowAtom(mce, vatomY));
1346 at = mkUifU128(mce, vatomX, vatomY);
1347 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1348 return at;
1349}
1350
1351static
1352IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1353{
1354 IRAtom* at;
1355 tl_assert(isShadowAtom(mce, vatomX));
1356 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1357 return at;
1358}
1359
1360static
1361IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1362{
1363 IRAtom* at;
1364 tl_assert(isShadowAtom(mce, vatomX));
1365 tl_assert(isShadowAtom(mce, vatomY));
1366 at = mkUifU128(mce, vatomX, vatomY);
1367 at = assignNew(mce, Ity_I64, unop(Iop_128to64, at));
1368 at = mkPCastTo(mce, Ity_I64, at);
1369 at = assignNew(mce, Ity_V128, binop(Iop_Set128lo64, vatomX, at));
1370 return at;
1371}
1372
1373static
1374IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1375{
1376 IRAtom* at;
1377 tl_assert(isShadowAtom(mce, vatomX));
1378 at = assignNew(mce, Ity_I64, unop(Iop_128to64, vatomX));
1379 at = mkPCastTo(mce, Ity_I64, at);
1380 at = assignNew(mce, Ity_V128, binop(Iop_Set128lo64, vatomX, at));
1381 return at;
1382}
1383
1384/* --- --- Vector saturated narrowing --- --- */
1385
1386/* This is quite subtle. What to do is simple:
1387
1388 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1389
1390 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1391
1392 Why this is right is not so simple. Consider a lane in the args,
1393 vatom1 or 2, doesn't matter.
1394
1395 After the PCast, that lane is all 0s (defined) or all
1396 1s(undefined).
1397
1398 Both signed and unsigned saturating narrowing of all 0s produces
1399 all 0s, which is what we want.
1400
1401 The all-1s case is more complex. Unsigned narrowing interprets an
1402 all-1s input as the largest unsigned integer, and so produces all
1403 1s as a result since that is the largest unsigned value at the
1404 smaller width.
1405
1406 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1407 to -1, so we still wind up with all 1s at the smaller width.
1408
1409 So: In short, pessimise the args, then apply the original narrowing
1410 op.
1411*/
1412static
1413IRAtom* vectorNarrow128 ( MCEnv* mce, IROp narrow_op,
1414 IRAtom* vatom1, IRAtom* vatom2)
1415{
1416 IRAtom *at1, *at2, *at3;
1417 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1418 switch (narrow_op) {
1419 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1420 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1421 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
1422 default: VG_(tool_panic)("vectorNarrow128");
1423 }
1424 tl_assert(isShadowAtom(mce,vatom1));
1425 tl_assert(isShadowAtom(mce,vatom2));
1426 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1427 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1428 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1429 return at3;
1430}
1431
1432
1433/* --- --- Vector integer arithmetic --- --- */
1434
1435/* Simple ... UifU the args and per-lane pessimise the results. */
1436static
1437IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1438{
1439 IRAtom* at;
1440 at = mkUifU128(mce, vatom1, vatom2);
1441 at = mkPCast8x16(mce, at);
1442 return at;
1443}
1444
1445static
1446IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1447{
1448 IRAtom* at;
1449 at = mkUifU128(mce, vatom1, vatom2);
1450 at = mkPCast16x8(mce, at);
1451 return at;
1452}
1453
1454static
1455IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1456{
1457 IRAtom* at;
1458 at = mkUifU128(mce, vatom1, vatom2);
1459 at = mkPCast32x4(mce, at);
1460 return at;
1461}
1462
1463static
1464IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1465{
1466 IRAtom* at;
1467 at = mkUifU128(mce, vatom1, vatom2);
1468 at = mkPCast64x2(mce, at);
1469 return at;
1470}
1471
1472
1473/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001474/*--- Generate shadow values from all kinds of IRExprs. ---*/
1475/*------------------------------------------------------------*/
1476
1477static
1478IRAtom* expr2vbits_Binop ( MCEnv* mce,
1479 IROp op,
1480 IRAtom* atom1, IRAtom* atom2 )
1481{
1482 IRType and_or_ty;
1483 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1484 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1485 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1486
1487 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1488 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1489
sewardj69f9e3e2004-12-30 02:05:34 +00001490 tl_assert(isOriginalAtom(mce,atom1));
1491 tl_assert(isOriginalAtom(mce,atom2));
1492 tl_assert(isShadowAtom(mce,vatom1));
1493 tl_assert(isShadowAtom(mce,vatom2));
1494 tl_assert(sameKindedAtoms(atom1,vatom1));
1495 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001496 switch (op) {
1497
sewardj69f9e3e2004-12-30 02:05:34 +00001498 /* 128-bit SIMD (SSE2-esque) */
1499
1500 case Iop_ShrN16x8:
1501 case Iop_ShrN32x4:
1502 case Iop_ShrN64x2:
1503 case Iop_SarN16x8:
1504 case Iop_SarN32x4:
1505 case Iop_ShlN16x8:
1506 case Iop_ShlN32x4:
1507 case Iop_ShlN64x2:
1508 /* Same scheme as with all other shifts. */
1509 complainIfUndefined(mce, atom2);
1510 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1511
1512 case Iop_QSub8Ux16:
1513 case Iop_QSub8Sx16:
1514 case Iop_Sub8x16:
1515 case Iop_Min8Ux16:
1516 case Iop_Max8Ux16:
1517 case Iop_CmpGT8Sx16:
1518 case Iop_CmpEQ8x16:
1519 case Iop_Avg8Ux16:
1520 case Iop_QAdd8Ux16:
1521 case Iop_QAdd8Sx16:
1522 case Iop_Add8x16:
1523 return binary8Ix16(mce, vatom1, vatom2);
1524
1525 case Iop_QSub16Ux8:
1526 case Iop_QSub16Sx8:
1527 case Iop_Sub16x8:
1528 case Iop_Mul16x8:
1529 case Iop_MulHi16Sx8:
1530 case Iop_MulHi16Ux8:
1531 case Iop_Min16Sx8:
1532 case Iop_Max16Sx8:
1533 case Iop_CmpGT16Sx8:
1534 case Iop_CmpEQ16x8:
1535 case Iop_Avg16Ux8:
1536 case Iop_QAdd16Ux8:
1537 case Iop_QAdd16Sx8:
1538 case Iop_Add16x8:
1539 return binary16Ix8(mce, vatom1, vatom2);
1540
1541 case Iop_Sub32x4:
1542 case Iop_CmpGT32Sx4:
1543 case Iop_CmpEQ32x4:
1544 case Iop_Add32x4:
1545 return binary32Ix4(mce, vatom1, vatom2);
1546
1547 case Iop_Sub64x2:
1548 case Iop_Add64x2:
1549 return binary64Ix2(mce, vatom1, vatom2);
1550
1551 case Iop_QNarrow32Sx4:
1552 case Iop_QNarrow16Sx8:
1553 case Iop_QNarrow16Ux8:
1554 return vectorNarrow128(mce, op, vatom1, vatom2);
1555
1556 case Iop_Sub64Fx2:
1557 case Iop_Mul64Fx2:
1558 case Iop_Min64Fx2:
1559 case Iop_Max64Fx2:
1560 case Iop_Div64Fx2:
1561 case Iop_CmpLT64Fx2:
1562 case Iop_CmpLE64Fx2:
1563 case Iop_CmpEQ64Fx2:
1564 case Iop_Add64Fx2:
1565 return binary64Fx2(mce, vatom1, vatom2);
1566
1567 case Iop_Sub64F0x2:
1568 case Iop_Mul64F0x2:
1569 case Iop_Min64F0x2:
1570 case Iop_Max64F0x2:
1571 case Iop_Div64F0x2:
1572 case Iop_CmpLT64F0x2:
1573 case Iop_CmpLE64F0x2:
1574 case Iop_CmpEQ64F0x2:
1575 case Iop_Add64F0x2:
1576 return binary64F0x2(mce, vatom1, vatom2);
1577
1578 /* 128-bit SIMD (SSE1-esque) */
1579
1580 case Iop_Sub32Fx4:
1581 case Iop_Mul32Fx4:
1582 case Iop_Min32Fx4:
1583 case Iop_Max32Fx4:
1584 case Iop_Div32Fx4:
1585 case Iop_CmpLT32Fx4:
1586 case Iop_CmpLE32Fx4:
1587 case Iop_CmpEQ32Fx4:
1588 case Iop_Add32Fx4:
1589 return binary32Fx4(mce, vatom1, vatom2);
1590
1591 case Iop_Sub32F0x4:
1592 case Iop_Mul32F0x4:
1593 case Iop_Min32F0x4:
1594 case Iop_Max32F0x4:
1595 case Iop_Div32F0x4:
1596 case Iop_CmpLT32F0x4:
1597 case Iop_CmpLE32F0x4:
1598 case Iop_CmpEQ32F0x4:
1599 case Iop_Add32F0x4:
1600 return binary32F0x4(mce, vatom1, vatom2);
1601
1602 /* 128-bit data-steering */
1603 case Iop_Set128lo32:
1604 case Iop_Set128lo64:
1605 case Iop_64HLto128:
1606 case Iop_InterleaveLO64x2:
1607 case Iop_InterleaveLO32x4:
1608 case Iop_InterleaveLO16x8:
1609 case Iop_InterleaveLO8x16:
1610 case Iop_InterleaveHI64x2:
1611 case Iop_InterleaveHI32x4:
1612 case Iop_InterleaveHI16x8:
1613 case Iop_InterleaveHI8x16:
1614 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1615
1616 /* Scalar floating point */
1617
sewardj3598ef92004-11-11 02:13:30 +00001618 case Iop_RoundF64:
1619 case Iop_F64toI64:
sewardj69f9e3e2004-12-30 02:05:34 +00001620 case Iop_I64toF64:
1621 /* First arg is I32 (rounding mode), second is F64 or I64
1622 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001623 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1624
1625 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1626 /* Takes two F64 args. */
sewardjde8a5ae2004-11-06 14:20:54 +00001627 case Iop_F64toI32:
sewardj69f9e3e2004-12-30 02:05:34 +00001628 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001629 /* First arg is I32 (rounding mode), second is F64 (data). */
1630 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1631
1632 case Iop_F64toI16:
1633 /* First arg is I32 (rounding mode), second is F64 (data). */
1634 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1635
sewardj3598ef92004-11-11 02:13:30 +00001636 case Iop_ScaleF64:
1637 case Iop_Yl2xF64:
1638 case Iop_Yl2xp1F64:
1639 case Iop_PRemF64:
1640 case Iop_AtanF64:
1641 case Iop_AddF64:
1642 case Iop_DivF64:
1643 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001644 case Iop_MulF64:
1645 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1646
sewardj3598ef92004-11-11 02:13:30 +00001647 case Iop_CmpF64:
1648 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1649
sewardjde8a5ae2004-11-06 14:20:54 +00001650 /* non-FP after here */
1651
1652 case Iop_DivModU64to32:
1653 case Iop_DivModS64to32:
1654 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1655
sewardj3598ef92004-11-11 02:13:30 +00001656 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001657 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001658 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001659 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001660
1661 case Iop_MullS32:
1662 case Iop_MullU32: {
1663 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1664 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1665 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1666 }
1667
sewardj3598ef92004-11-11 02:13:30 +00001668 case Iop_MullS16:
1669 case Iop_MullU16: {
1670 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1671 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1672 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1673 }
1674
1675 case Iop_MullS8:
1676 case Iop_MullU8: {
1677 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1678 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1679 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1680 }
1681
sewardjde8a5ae2004-11-06 14:20:54 +00001682 case Iop_Add32:
1683# if 0
1684 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1685# endif
1686 case Iop_Sub32:
1687 case Iop_Mul32:
1688 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1689
sewardj3598ef92004-11-11 02:13:30 +00001690 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001691 case Iop_Add16:
1692 case Iop_Sub16:
1693 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1694
1695 case Iop_Sub8:
1696 case Iop_Add8:
1697 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1698
1699 case Iop_CmpLE32S: case Iop_CmpLE32U:
1700 case Iop_CmpLT32U: case Iop_CmpLT32S:
1701 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001702 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001703
sewardj3598ef92004-11-11 02:13:30 +00001704 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001705 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001706
1707 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001708 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001709
1710 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1711 /* Complain if the shift amount is undefined. Then simply
1712 shift the first arg's V bits by the real shift amount. */
1713 complainIfUndefined(mce, atom2);
1714 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1715
sewardj69f9e3e2004-12-30 02:05:34 +00001716 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001717 /* Same scheme as with 32-bit shifts. */
1718 complainIfUndefined(mce, atom2);
1719 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1720
sewardj3598ef92004-11-11 02:13:30 +00001721 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001722 /* Same scheme as with 32-bit shifts. */
1723 complainIfUndefined(mce, atom2);
1724 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1725
1726 case Iop_Shl64: case Iop_Shr64:
1727 /* Same scheme as with 32-bit shifts. */
1728 complainIfUndefined(mce, atom2);
1729 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1730
sewardj69f9e3e2004-12-30 02:05:34 +00001731 case Iop_And128:
1732 uifu = mkUifU128; difd = mkDifD128;
1733 and_or_ty = Ity_V128; improve = mkImproveAND128; goto do_And_Or;
1734 case Iop_And64:
1735 uifu = mkUifU64; difd = mkDifD64;
1736 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001737 case Iop_And32:
1738 uifu = mkUifU32; difd = mkDifD32;
1739 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001740 case Iop_And16:
1741 uifu = mkUifU16; difd = mkDifD16;
1742 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001743 case Iop_And8:
1744 uifu = mkUifU8; difd = mkDifD8;
1745 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1746
sewardj69f9e3e2004-12-30 02:05:34 +00001747 case Iop_Or128:
1748 uifu = mkUifU128; difd = mkDifD128;
1749 and_or_ty = Ity_V128; improve = mkImproveOR128; goto do_And_Or;
1750 case Iop_Or64:
1751 uifu = mkUifU64; difd = mkDifD64;
1752 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001753 case Iop_Or32:
1754 uifu = mkUifU32; difd = mkDifD32;
1755 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1756 case Iop_Or16:
1757 uifu = mkUifU16; difd = mkDifD16;
1758 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1759 case Iop_Or8:
1760 uifu = mkUifU8; difd = mkDifD8;
1761 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1762
1763 do_And_Or:
1764 return
1765 assignNew(
1766 mce,
1767 and_or_ty,
1768 difd(mce, uifu(mce, vatom1, vatom2),
1769 difd(mce, improve(mce, atom1, vatom1),
1770 improve(mce, atom2, vatom2) ) ) );
1771
1772 case Iop_Xor8:
1773 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001774 case Iop_Xor16:
1775 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001776 case Iop_Xor32:
1777 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001778 case Iop_Xor64:
1779 return mkUifU64(mce, vatom1, vatom2);
1780 case Iop_Xor128:
1781 return mkUifU128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001782
1783 default:
1784 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001785 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001786 }
1787}
1788
1789
1790static
1791IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1792{
1793 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001794 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001795 switch (op) {
1796
sewardj69f9e3e2004-12-30 02:05:34 +00001797 case Iop_Sqrt64Fx2:
1798 return unary64Fx2(mce, vatom);
1799
1800 case Iop_Sqrt64F0x2:
1801 return unary64F0x2(mce, vatom);
1802
1803 case Iop_Sqrt32Fx4:
1804 case Iop_RSqrt32Fx4:
1805 case Iop_Recip32Fx4:
1806 return unary32Fx4(mce, vatom);
1807
1808 case Iop_Sqrt32F0x4:
1809 case Iop_RSqrt32F0x4:
1810 case Iop_Recip32F0x4:
1811 return unary32F0x4(mce, vatom);
1812
1813 case Iop_32Uto128:
1814 case Iop_64Uto128:
1815 return assignNew(mce, Ity_V128, unop(op, vatom));
1816
sewardjde8a5ae2004-11-06 14:20:54 +00001817 case Iop_F32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001818 case Iop_I32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001819 case Iop_NegF64:
1820 case Iop_SinF64:
1821 case Iop_CosF64:
1822 case Iop_TanF64:
1823 case Iop_SqrtF64:
1824 case Iop_AbsF64:
1825 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001826 return mkPCastTo(mce, Ity_I64, vatom);
1827
sewardj3598ef92004-11-11 02:13:30 +00001828 case Iop_Clz32:
1829 case Iop_Ctz32:
1830 return mkPCastTo(mce, Ity_I32, vatom);
1831
1832 case Iop_32Sto64:
1833 case Iop_32Uto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001834 case Iop_128to64:
1835 case Iop_128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001836 return assignNew(mce, Ity_I64, unop(op, vatom));
1837
sewardjde8a5ae2004-11-06 14:20:54 +00001838 case Iop_64to32:
1839 case Iop_64HIto32:
1840 case Iop_1Uto32:
1841 case Iop_8Uto32:
1842 case Iop_16Uto32:
1843 case Iop_16Sto32:
1844 case Iop_8Sto32:
1845 return assignNew(mce, Ity_I32, unop(op, vatom));
1846
1847 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001848 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001849 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001850 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001851 return assignNew(mce, Ity_I16, unop(op, vatom));
1852
1853 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001854 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001855 case Iop_32to8:
1856 return assignNew(mce, Ity_I8, unop(op, vatom));
1857
1858 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001859 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001860
sewardj3598ef92004-11-11 02:13:30 +00001861 case Iop_ReinterpF64asI64:
1862 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001863 case Iop_ReinterpI32asF32:
1864 case Iop_Not128:
1865 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00001866 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001867 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001868 case Iop_Not8:
1869 case Iop_Not1:
1870 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001871
sewardjde8a5ae2004-11-06 14:20:54 +00001872 default:
1873 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001874 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00001875 }
1876}
1877
1878
sewardj69f9e3e2004-12-30 02:05:34 +00001879/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00001880static
sewardj69f9e3e2004-12-30 02:05:34 +00001881IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001882{
1883 void* helper;
1884 Char* hname;
1885 IRDirty* di;
1886 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00001887 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001888
sewardj69f9e3e2004-12-30 02:05:34 +00001889 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00001890
1891 /* First, emit a definedness test for the address. This also sets
1892 the address (shadow) to 'defined' following the test. */
1893 complainIfUndefined( mce, addr );
1894
1895 /* Now cook up a call to the relevant helper function, to read the
1896 data V bits from shadow memory. */
1897 ty = shadowType(ty);
1898 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001899 case Ity_I64: helper = &MC_(helperc_LOADV8);
1900 hname = "MC_(helperc_LOADV8)";
1901 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001902 case Ity_I32: helper = &MC_(helperc_LOADV4);
1903 hname = "MC_(helperc_LOADV4)";
1904 break;
1905 case Ity_I16: helper = &MC_(helperc_LOADV2);
1906 hname = "MC_(helperc_LOADV2)";
1907 break;
1908 case Ity_I8: helper = &MC_(helperc_LOADV1);
1909 hname = "MC_(helperc_LOADV1)";
1910 break;
1911 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001912 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00001913 }
1914
sewardj3598ef92004-11-11 02:13:30 +00001915 /* Generate the actual address into addrAct. */
1916 if (bias == 0) {
1917 addrAct = addr;
1918 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001919 IROp mkAdd;
1920 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00001921 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00001922 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
1923 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1924 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00001925 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1926 }
1927
sewardjde8a5ae2004-11-06 14:20:54 +00001928 /* We need to have a place to park the V bits we're just about to
1929 read. */
1930 datavbits = newIRTemp(mce->bb->tyenv, ty);
1931 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00001932 1/*regparms*/, hname, helper,
1933 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00001934 setHelperAnns( mce, di );
1935 stmt( mce->bb, IRStmt_Dirty(di) );
1936
1937 return mkexpr(datavbits);
1938}
1939
1940
1941static
sewardj69f9e3e2004-12-30 02:05:34 +00001942IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
1943{
1944 IRAtom *v64hi, *v64lo;
1945 switch (shadowType(ty)) {
1946 case Ity_I8:
1947 case Ity_I16:
1948 case Ity_I32:
1949 case Ity_I64:
1950 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
1951 case Ity_V128:
1952 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
1953 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
1954 return assignNew( mce,
1955 Ity_V128,
1956 binop(Iop_64HLto128, v64hi, v64lo));
1957 default:
1958 VG_(tool_panic)("expr2vbits_LDle");
1959 }
1960}
1961
1962
1963static
sewardjde8a5ae2004-11-06 14:20:54 +00001964IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00001965 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00001966{
1967 IRAtom *vbitsC, *vbits0, *vbitsX;
1968 IRType ty;
1969 /* Given Mux0X(cond,expr0,exprX), generate
1970 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
1971 That is, steer the V bits like the originals, but trash the
1972 result if the steering value is undefined. This gives
1973 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00001974 tl_assert(isOriginalAtom(mce, cond));
1975 tl_assert(isOriginalAtom(mce, expr0));
1976 tl_assert(isOriginalAtom(mce, exprX));
sewardjde8a5ae2004-11-06 14:20:54 +00001977
1978 vbitsC = expr2vbits(mce, cond);
1979 vbits0 = expr2vbits(mce, expr0);
1980 vbitsX = expr2vbits(mce, exprX);
1981 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
1982
1983 return
1984 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
1985 mkPCastTo(mce, ty, vbitsC) );
1986}
1987
1988/* --------- This is the main expression-handling function. --------- */
1989
1990static
1991IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
1992{
1993 switch (e->tag) {
1994
1995 case Iex_Get:
1996 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
1997
1998 case Iex_GetI:
1999 return shadow_GETI( mce, e->Iex.GetI.descr,
2000 e->Iex.GetI.ix, e->Iex.GetI.bias );
2001
2002 case Iex_Tmp:
2003 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
2004
2005 case Iex_Const:
2006 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2007
2008 case Iex_Binop:
2009 return expr2vbits_Binop(
2010 mce,
2011 e->Iex.Binop.op,
2012 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2013 );
2014
2015 case Iex_Unop:
2016 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2017
2018 case Iex_LDle:
sewardj3598ef92004-11-11 02:13:30 +00002019 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
2020 e->Iex.LDle.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002021
2022 case Iex_CCall:
2023 return mkLazyN( mce, e->Iex.CCall.args,
2024 e->Iex.CCall.retty,
2025 e->Iex.CCall.cee );
2026
2027 case Iex_Mux0X:
2028 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2029 e->Iex.Mux0X.exprX);
2030
2031 default:
2032 VG_(printf)("\n");
2033 ppIRExpr(e);
2034 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002035 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002036 }
2037}
2038
2039/*------------------------------------------------------------*/
2040/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2041/*------------------------------------------------------------*/
2042
2043/* Widen a value to the host word size. */
2044
2045static
2046IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2047{
sewardj69f9e3e2004-12-30 02:05:34 +00002048 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002049
sewardj8fc93742004-11-22 11:29:33 +00002050 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002051 tl_assert(isShadowAtom(mce,vatom));
2052
2053 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2054 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002055
sewardjde8a5ae2004-11-06 14:20:54 +00002056 if (tyH == Ity_I32) {
2057 switch (ty) {
2058 case Ity_I32: return vatom;
2059 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2060 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2061 default: goto unhandled;
2062 }
2063 } else {
2064 goto unhandled;
2065 }
2066 unhandled:
2067 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002068 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002069}
2070
2071
sewardj3598ef92004-11-11 02:13:30 +00002072/* Generate a shadow store. addr is always the original address atom.
2073 You can pass in either originals or V-bits for the data atom, but
2074 obviously not both. */
2075
sewardjde8a5ae2004-11-06 14:20:54 +00002076static
sewardj3598ef92004-11-11 02:13:30 +00002077void do_shadow_STle ( MCEnv* mce,
2078 IRAtom* addr, UInt bias,
2079 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002080{
sewardj69f9e3e2004-12-30 02:05:34 +00002081 IROp mkAdd;
2082 IRType ty, tyAddr;
2083 IRDirty *di, *diLo64, *diHi64;
2084 IRAtom *addrAct, *addrLo64, *addrHi64;
2085 IRAtom *vdataLo64, *vdataHi64;
2086 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002087 void* helper = NULL;
2088 Char* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002089
2090 tyAddr = mce->hWordTy;
2091 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2092 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2093
2094 di = diLo64 = diHi64 = NULL;
2095 eBias = eBias0 = eBias8 = NULL;
2096 addrAct = addrLo64 = addrHi64 = NULL;
2097 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002098
sewardj3598ef92004-11-11 02:13:30 +00002099 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002100 tl_assert(!vdata);
2101 tl_assert(isOriginalAtom(mce, data));
2102 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002103 vdata = expr2vbits( mce, data );
2104 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002105 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002106 }
sewardjde8a5ae2004-11-06 14:20:54 +00002107
sewardj69f9e3e2004-12-30 02:05:34 +00002108 tl_assert(isOriginalAtom(mce,addr));
2109 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002110
2111 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002112
2113 /* First, emit a definedness test for the address. This also sets
2114 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002115 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002116
sewardj69f9e3e2004-12-30 02:05:34 +00002117 /* Now decide which helper function to call to write the data V
2118 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002119 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002120 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002121 case Ity_I64: helper = &MC_(helperc_STOREV8);
2122 hname = "MC_(helperc_STOREV8)";
2123 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002124 case Ity_I32: helper = &MC_(helperc_STOREV4);
2125 hname = "MC_(helperc_STOREV4)";
2126 break;
2127 case Ity_I16: helper = &MC_(helperc_STOREV2);
2128 hname = "MC_(helperc_STOREV2)";
2129 break;
2130 case Ity_I8: helper = &MC_(helperc_STOREV1);
2131 hname = "MC_(helperc_STOREV1)";
2132 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002133 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002134 }
2135
sewardj69f9e3e2004-12-30 02:05:34 +00002136 if (ty == Ity_V128) {
2137
2138 /* 128-bit case */
2139 /* See comment in next clause re 64-bit regparms */
2140 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2141 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
2142 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_128to64, vdata));
2143 diLo64 = unsafeIRDirty_0_N(
2144 1/*regparms*/, hname, helper,
2145 mkIRExprVec_2( addrLo64, vdataLo64 ));
2146
2147 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2148 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
2149 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_128HIto64, vdata));
2150 diHi64 = unsafeIRDirty_0_N(
2151 1/*regparms*/, hname, helper,
2152 mkIRExprVec_2( addrHi64, vdataHi64 ));
2153
2154 setHelperAnns( mce, diLo64 );
2155 setHelperAnns( mce, diHi64 );
2156 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2157 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2158
sewardj3598ef92004-11-11 02:13:30 +00002159 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002160
2161 /* 8/16/32/64-bit cases */
2162 /* Generate the actual address into addrAct. */
2163 if (bias == 0) {
2164 addrAct = addr;
2165 } else {
2166 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2167 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2168 }
2169
2170 if (ty == Ity_I64) {
2171 /* We can't do this with regparm 2 on 32-bit platforms, since
2172 the back ends aren't clever enough to handle 64-bit
2173 regparm args. Therefore be different. */
2174 di = unsafeIRDirty_0_N(
2175 1/*regparms*/, hname, helper,
2176 mkIRExprVec_2( addrAct, vdata ));
2177 } else {
2178 di = unsafeIRDirty_0_N(
2179 2/*regparms*/, hname, helper,
2180 mkIRExprVec_2( addrAct,
2181 zwidenToHostWord( mce, vdata )));
2182 }
2183 setHelperAnns( mce, di );
2184 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002185 }
2186
sewardjde8a5ae2004-11-06 14:20:54 +00002187}
2188
2189
sewardj3598ef92004-11-11 02:13:30 +00002190/* Do lazy pessimistic propagation through a dirty helper call, by
2191 looking at the annotations on it. This is the most complex part of
2192 Memcheck. */
2193
2194static IRType szToITy ( Int n )
2195{
2196 switch (n) {
2197 case 1: return Ity_I8;
2198 case 2: return Ity_I16;
2199 case 4: return Ity_I32;
2200 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002201 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002202 }
2203}
2204
2205static
2206void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2207{
sewardj69f9e3e2004-12-30 02:05:34 +00002208 Int i, n, offset, toDo, gSz, gOff;
2209 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002210 IRType tyAddr, tySrc, tyDst;
2211 IRTemp dst;
2212
2213 /* First check the guard. */
2214 complainIfUndefined(mce, d->guard);
2215
2216 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002217 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002218
2219 /* Inputs: unmasked args */
2220 for (i = 0; d->args[i]; i++) {
2221 if (d->cee->mcx_mask & (1<<i)) {
2222 /* ignore this arg */
2223 } else {
2224 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2225 curr = mkUifU32(mce, here, curr);
2226 }
2227 }
2228
2229 /* Inputs: guest state that we read. */
2230 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002231 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002232 if (d->fxState[i].fx == Ifx_Write)
2233 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002234
2235 /* Ignore any sections marked as 'always defined'. */
2236 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2237 if (0)
2238 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2239 d->fxState[i].offset, d->fxState[i].size );
2240 continue;
2241 }
2242
sewardj3598ef92004-11-11 02:13:30 +00002243 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002244 consider it. If larger than 8 bytes, deal with it in 8-byte
2245 chunks. */
2246 gSz = d->fxState[i].size;
2247 gOff = d->fxState[i].offset;
2248 tl_assert(gSz > 0);
2249 while (True) {
2250 if (gSz == 0) break;
2251 n = gSz <= 8 ? gSz : 8;
2252 /* update 'curr' with UifU of the state slice
2253 gOff .. gOff+n-1 */
2254 tySrc = szToITy( n );
2255 src = assignNew( mce, tySrc,
2256 shadow_GET(mce, gOff, tySrc ) );
2257 here = mkPCastTo( mce, Ity_I32, src );
2258 curr = mkUifU32(mce, here, curr);
2259 gSz -= n;
2260 gOff += n;
2261 }
2262
sewardj3598ef92004-11-11 02:13:30 +00002263 }
2264
2265 /* Inputs: memory. First set up some info needed regardless of
2266 whether we're doing reads or writes. */
2267 tyAddr = Ity_INVALID;
2268
2269 if (d->mFx != Ifx_None) {
2270 /* Because we may do multiple shadow loads/stores from the same
2271 base address, it's best to do a single test of its
2272 definedness right now. Post-instrumentation optimisation
2273 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002274 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002275 complainIfUndefined(mce, d->mAddr);
2276
2277 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002278 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2279 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002280 }
2281
2282 /* Deal with memory inputs (reads or modifies) */
2283 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2284 offset = 0;
2285 toDo = d->mSize;
2286 /* chew off 32-bit chunks */
2287 while (toDo >= 4) {
2288 here = mkPCastTo(
2289 mce, Ity_I32,
2290 expr2vbits_LDle ( mce, Ity_I32,
2291 d->mAddr, d->mSize - toDo )
2292 );
2293 curr = mkUifU32(mce, here, curr);
2294 toDo -= 4;
2295 }
2296 /* chew off 16-bit chunks */
2297 while (toDo >= 2) {
2298 here = mkPCastTo(
2299 mce, Ity_I32,
2300 expr2vbits_LDle ( mce, Ity_I16,
2301 d->mAddr, d->mSize - toDo )
2302 );
2303 curr = mkUifU32(mce, here, curr);
2304 toDo -= 2;
2305 }
sewardj69f9e3e2004-12-30 02:05:34 +00002306 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002307 }
2308
2309 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2310 all the inputs to the helper. Now we need to re-distribute the
2311 results to all destinations. */
2312
2313 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002314 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002315 dst = findShadowTmp(mce, d->tmp);
2316 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2317 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2318 }
2319
2320 /* Outputs: guest state that we write or modify. */
2321 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002322 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002323 if (d->fxState[i].fx == Ifx_Read)
2324 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002325 /* Ignore any sections marked as 'always defined'. */
2326 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2327 continue;
2328 /* This state element is written or modified. So we need to
2329 consider it. If larger than 8 bytes, deal with it in 8-byte
2330 chunks. */
2331 gSz = d->fxState[i].size;
2332 gOff = d->fxState[i].offset;
2333 tl_assert(gSz > 0);
2334 while (True) {
2335 if (gSz == 0) break;
2336 n = gSz <= 8 ? gSz : 8;
2337 /* Write suitably-casted 'curr' to the state slice
2338 gOff .. gOff+n-1 */
2339 tyDst = szToITy( n );
2340 do_shadow_PUT( mce, gOff,
2341 NULL, /* original atom */
2342 mkPCastTo( mce, tyDst, curr ) );
2343 gSz -= n;
2344 gOff += n;
2345 }
sewardj3598ef92004-11-11 02:13:30 +00002346 }
2347
2348 /* Outputs: memory that we write or modify. */
2349 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2350 offset = 0;
2351 toDo = d->mSize;
2352 /* chew off 32-bit chunks */
2353 while (toDo >= 4) {
2354 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2355 NULL, /* original data */
2356 mkPCastTo( mce, Ity_I32, curr ) );
2357 toDo -= 4;
2358 }
2359 /* chew off 16-bit chunks */
2360 while (toDo >= 2) {
2361 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2362 NULL, /* original data */
2363 mkPCastTo( mce, Ity_I16, curr ) );
2364 toDo -= 2;
2365 }
sewardj69f9e3e2004-12-30 02:05:34 +00002366 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002367 }
2368
2369}
2370
2371
sewardjde8a5ae2004-11-06 14:20:54 +00002372/*------------------------------------------------------------*/
2373/*--- Memcheck main ---*/
2374/*------------------------------------------------------------*/
2375
sewardj3598ef92004-11-11 02:13:30 +00002376#if 0 /* UNUSED */
2377static Bool isBogusAtom ( IRAtom* at )
2378{
2379 ULong n = 0;
2380 IRConst* con;
sewardj69f9e3e2004-12-30 02:05:34 +00002381 tl_assert(isAtom(at));
sewardj3598ef92004-11-11 02:13:30 +00002382 if (at->tag == Iex_Tmp)
2383 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002384 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002385 con = at->Iex.Const.con;
2386 switch (con->tag) {
2387 case Ico_U8: n = (ULong)con->Ico.U8; break;
2388 case Ico_U16: n = (ULong)con->Ico.U16; break;
2389 case Ico_U32: n = (ULong)con->Ico.U32; break;
2390 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002391 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002392 }
2393 /* VG_(printf)("%llx\n", n); */
2394 return (n == 0xFEFEFEFF
2395 || n == 0x80808080
2396 || n == 0x1010101
2397 || n == 1010100);
2398}
2399
2400static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2401{
2402 Int i;
2403 IRExpr* e;
2404 switch (st->tag) {
2405 case Ist_Tmp:
2406 e = st->Ist.Tmp.data;
2407 switch (e->tag) {
2408 case Iex_Get:
2409 case Iex_Tmp:
2410 return False;
2411 case Iex_Unop:
2412 return isBogusAtom(e->Iex.Unop.arg);
2413 case Iex_Binop:
2414 return isBogusAtom(e->Iex.Binop.arg1)
2415 || isBogusAtom(e->Iex.Binop.arg2);
2416 case Iex_Mux0X:
2417 return isBogusAtom(e->Iex.Mux0X.cond)
2418 || isBogusAtom(e->Iex.Mux0X.expr0)
2419 || isBogusAtom(e->Iex.Mux0X.exprX);
2420 case Iex_LDle:
2421 return isBogusAtom(e->Iex.LDle.addr);
2422 case Iex_CCall:
2423 for (i = 0; e->Iex.CCall.args[i]; i++)
2424 if (isBogusAtom(e->Iex.CCall.args[i]))
2425 return True;
2426 return False;
2427 default:
2428 goto unhandled;
2429 }
2430 case Ist_Put:
2431 return isBogusAtom(st->Ist.Put.data);
2432 case Ist_STle:
2433 return isBogusAtom(st->Ist.STle.addr)
2434 || isBogusAtom(st->Ist.STle.data);
2435 case Ist_Exit:
sewardj69f9e3e2004-12-30 02:05:34 +00002436 return isBogusAtom(st->Ist.Exit.cond);
sewardj3598ef92004-11-11 02:13:30 +00002437 default:
2438 unhandled:
2439 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002440 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002441 }
2442}
2443#endif /* UNUSED */
2444
2445
sewardjde8a5ae2004-11-06 14:20:54 +00002446IRBB* mc_instrument ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
2447{
sewardj3598ef92004-11-11 02:13:30 +00002448 Bool verboze = False; //True;
2449
2450 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002451
2452 Int i, j, first_stmt;
2453 IRStmt* st;
2454 MCEnv mce;
2455
2456 /* Set up BB */
2457 IRBB* bb = emptyIRBB();
2458 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
2459 bb->next = dopyIRExpr(bb_in->next);
2460 bb->jumpkind = bb_in->jumpkind;
2461
2462 /* Set up the running environment. Only .bb is modified as we go
2463 along. */
2464 mce.bb = bb;
2465 mce.layout = layout;
2466 mce.n_originalTmps = bb->tyenv->types_used;
2467 mce.hWordTy = hWordTy;
2468 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2469 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002470 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002471
2472 /* Iterate over the stmts. */
2473
2474 for (i = 0; i < bb_in->stmts_used; i++) {
2475 st = bb_in->stmts[i];
2476 if (!st) continue;
2477
sewardj69f9e3e2004-12-30 02:05:34 +00002478 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002479
2480 /*
2481 if (!hasBogusLiterals) {
2482 hasBogusLiterals = checkForBogusLiterals(st);
2483 if (hasBogusLiterals) {
2484 VG_(printf)("bogus: ");
2485 ppIRStmt(st);
2486 VG_(printf)("\n");
2487 }
2488 }
2489 */
sewardjde8a5ae2004-11-06 14:20:54 +00002490 first_stmt = bb->stmts_used;
2491
2492 if (verboze) {
2493 ppIRStmt(st);
2494 VG_(printf)("\n\n");
2495 }
2496
2497 switch (st->tag) {
2498
2499 case Ist_Tmp:
2500 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
2501 expr2vbits( &mce, st->Ist.Tmp.data) );
2502 break;
2503
2504 case Ist_Put:
2505 do_shadow_PUT( &mce,
2506 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002507 st->Ist.Put.data,
2508 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002509 break;
2510
2511 case Ist_PutI:
2512 do_shadow_PUTI( &mce,
2513 st->Ist.PutI.descr,
2514 st->Ist.PutI.ix,
2515 st->Ist.PutI.bias,
2516 st->Ist.PutI.data );
2517 break;
2518
2519 case Ist_STle:
sewardj3598ef92004-11-11 02:13:30 +00002520 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
2521 st->Ist.STle.data,
2522 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002523 break;
2524
2525 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002526 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002527 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002528 break;
2529
2530 case Ist_Dirty:
2531 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002532 break;
2533
2534 default:
2535 VG_(printf)("\n");
2536 ppIRStmt(st);
2537 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002538 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002539
2540 } /* switch (st->tag) */
2541
2542 if (verboze) {
2543 for (j = first_stmt; j < bb->stmts_used; j++) {
2544 VG_(printf)(" ");
2545 ppIRStmt(bb->stmts[j]);
2546 VG_(printf)("\n");
2547 }
2548 VG_(printf)("\n");
2549 }
2550
2551 addStmtToIRBB(bb, st);
2552
2553 }
2554
2555 /* Now we need to complain if the jump target is undefined. */
2556 first_stmt = bb->stmts_used;
2557
2558 if (verboze) {
2559 VG_(printf)("bb->next = ");
2560 ppIRExpr(bb->next);
2561 VG_(printf)("\n\n");
2562 }
2563
2564 complainIfUndefined( &mce, bb->next );
2565
2566 if (verboze) {
2567 for (j = first_stmt; j < bb->stmts_used; j++) {
2568 VG_(printf)(" ");
2569 ppIRStmt(bb->stmts[j]);
2570 VG_(printf)("\n");
2571 }
2572 VG_(printf)("\n");
2573 }
2574
2575 return bb;
2576}
2577
2578/*--------------------------------------------------------------------*/
2579/*--- end mc_translate.c ---*/
2580/*--------------------------------------------------------------------*/