blob: e77202135ba3f0941c7d04958d4039f85e145a72 [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
sewardj58277842005-02-07 03:11:17 +000034void log_bytes ( HChar* bytes, Int nbytes )
sewardjce605f92004-07-05 14:39:15 +000035{
36 fwrite ( bytes, 1, nbytes, stdout );
37}
38
sewardjced9fe52004-07-07 11:55:36 +000039#define N_LINEBUF 10000
sewardjde8c9872005-03-25 13:48:55 +000040static HChar linebuf[N_LINEBUF];
sewardjced9fe52004-07-07 11:55:36 +000041
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 */
cerionaee45242005-03-17 14:03:36 +000051#if 0 /* UNUSED */
sewardj9578a8b2004-11-04 19:44:48 +000052static IRBB* ac_instrument ( IRBB*, VexGuestLayout*, IRType );
sewardjde8a5ae2004-11-06 14:20:54 +000053static IRBB* mc_instrument ( IRBB*, VexGuestLayout*, IRType );
cerionaee45242005-03-17 14:03:36 +000054#endif
sewardj9b1004e2004-10-30 22:25:40 +000055
sewardj5bd4d162004-11-10 13:02:48 +000056static Bool chase_into_not_ok ( Addr64 dst ) { return False; }
sewardj9b1004e2004-10-30 22:25:40 +000057
sewardjced9fe52004-07-07 11:55:36 +000058int main ( int argc, char** argv )
sewardjce605f92004-07-05 14:39:15 +000059{
sewardjced9fe52004-07-07 11:55:36 +000060 FILE* f;
61 Int i;
sewardj4459baa2004-09-10 20:00:46 +000062 UInt u, sum;
sewardjced9fe52004-07-07 11:55:36 +000063 Addr32 orig_addr;
sewardjabe017e2004-10-29 23:42:36 +000064 Int bb_number, n_bbs_done = 0;
sewardj72c72812005-01-19 11:49:45 +000065 Int orig_nbytes, trans_used;
sewardjd887b862005-01-17 18:34:34 +000066 VexTranslateResult tres;
sewardjb5bf2e02004-10-25 13:06:17 +000067 VexControl vcon;
sewardj72c72812005-01-19 11:49:45 +000068 VexGuestExtents vge;
sewardjced9fe52004-07-07 11:55:36 +000069
70 if (argc != 2) {
71 fprintf(stderr, "usage: vex file.org\n");
72 exit(1);
73 }
74 f = fopen(argv[1], "r");
75 if (!f) {
76 fprintf(stderr, "can't open `%s'\n", argv[1]);
77 exit(1);
78 }
79
sewardjb5bf2e02004-10-25 13:06:17 +000080 /* Run with default params. However, we can't allow bb chasing
81 since that causes the front end to get segfaults when it tries
sewardj5bd4d162004-11-10 13:02:48 +000082 to read code outside the initial BB we hand it. So when calling
83 LibVEX_Translate, send in a chase-into predicate that always
84 returns False. */
sewardjb5bf2e02004-10-25 13:06:17 +000085 LibVEX_default_VexControl ( &vcon );
sewardjb4952402004-10-26 13:24:50 +000086 vcon.iropt_level = 2;
sewardjc279b3f2005-03-16 18:10:45 +000087 vcon.guest_max_insns = 50;
sewardjb5bf2e02004-10-25 13:06:17 +000088
sewardjced9fe52004-07-07 11:55:36 +000089 LibVEX_Init ( &failure_exit, &log_bytes,
sewardj1f40a0a2004-07-21 12:28:07 +000090 1, /* debug_paranoia */
sewardjabe017e2004-10-29 23:42:36 +000091 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +000092 &vcon );
sewardjced9fe52004-07-07 11:55:36 +000093
sewardjea64e142004-07-22 16:47:21 +000094
sewardjced9fe52004-07-07 11:55:36 +000095 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +000096
sewardjced9fe52004-07-07 11:55:36 +000097 fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +000098 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +000099 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +0000100
101 if (n_bbs_done == TEST_N_BBS) break;
102 n_bbs_done++;
103
sewardjced9fe52004-07-07 11:55:36 +0000104 /* first line is: . bb-number bb-addr n-bytes */
105 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
106 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000107 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000108 assert(orig_nbytes >= 1);
109 assert(!feof(f));
110 fgets(linebuf, N_LINEBUF,f);
111 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000112
sewardjced9fe52004-07-07 11:55:36 +0000113 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000114 if (verbose)
sewardj07a54cc2005-02-04 21:18:55 +0000115 printf("============ Basic Block %d, Done %d, "
sewardj4459baa2004-09-10 20:00:46 +0000116 "Start %x, nbytes %2d ============",
sewardj07a54cc2005-02-04 21:18:55 +0000117 bb_number, n_bbs_done-1, orig_addr, orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000118
sewardjced9fe52004-07-07 11:55:36 +0000119 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
120 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000121 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
122 origbuf[i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000123 }
124
sewardjabe017e2004-10-29 23:42:36 +0000125 for (i = 0; i < TEST_N_ITERS; i++)
126 tres
127 = LibVEX_Translate (
cerionaee45242005-03-17 14:03:36 +0000128#if 0 /* ppc32 -> ppc32 */
129 VexArchPPC32, VexSubArchPPC32_noAV,
130 VexArchPPC32, VexSubArchPPC32_noAV,
131#endif
sewardj07a54cc2005-02-04 21:18:55 +0000132#if 0 /* ppc32 -> x86 */
133 VexArchPPC32, VexSubArchPPC32_noAV,
sewardjc3263ee2004-12-29 17:48:22 +0000134 VexArchX86, VexSubArchX86_sse2,
sewardj07a54cc2005-02-04 21:18:55 +0000135#endif
sewardjc279b3f2005-03-16 18:10:45 +0000136#if 0 /* amd64 -> amd64 */
sewardj07a54cc2005-02-04 21:18:55 +0000137 VexArchAMD64, VexSubArch_NONE,
138 VexArchAMD64, VexSubArch_NONE,
139#endif
sewardjc279b3f2005-03-16 18:10:45 +0000140#if 1 /* x86 -> x86 */
141 VexArchX86, VexSubArchX86_sse1,
142 VexArchX86, VexSubArchX86_sse1,
143#endif
sewardj07a54cc2005-02-04 21:18:55 +0000144
sewardj5bd4d162004-11-10 13:02:48 +0000145 origbuf, (Addr64)orig_addr, chase_into_not_ok,
sewardj72c72812005-01-19 11:49:45 +0000146 &vge,
sewardjabe017e2004-10-29 23:42:36 +0000147 transbuf, N_TRANSBUF, &trans_used,
sewardj9e7448b2004-11-18 13:44:15 +0000148#if 1 /* no instrumentation */
149 NULL, /* instrument1 */
150 NULL, /* instrument2 */
151 False, /* cleanup after instrument */
152#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000153#if 0 /* addrcheck */
154 ac_instrument, /* instrument1 */
155 NULL, /* instrument2 */
156 False, /* cleanup after instrument */
157#endif
sewardj9e7448b2004-11-18 13:44:15 +0000158#if 0 /* memcheck */
sewardjde8a5ae2004-11-06 14:20:54 +0000159 mc_instrument, /* instrument1 */
160 NULL, /* instrument2 */
sewardj69f9e3e2004-12-30 02:05:34 +0000161 True, /* cleanup after instrument */
sewardjde8a5ae2004-11-06 14:20:54 +0000162#endif
sewardjabe017e2004-10-29 23:42:36 +0000163 NULL, /* access checker */
164 TEST_FLAGS
165 );
166
sewardjd887b862005-01-17 18:34:34 +0000167 if (tres != VexTransOK)
sewardj4459baa2004-09-10 20:00:46 +0000168 printf("\ntres = %d\n", (Int)tres);
sewardjd887b862005-01-17 18:34:34 +0000169 assert(tres == VexTransOK);
sewardj72c72812005-01-19 11:49:45 +0000170 assert(vge.n_used == 1);
171 assert((UInt)(vge.len[0]) == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000172
sewardj4459baa2004-09-10 20:00:46 +0000173 sum = 0;
174 for (i = 0; i < trans_used; i++)
175 sum += (UInt)transbuf[i];
sewardjde8c9872005-03-25 13:48:55 +0000176 printf ( " %6.2f ... %u\n",
177 (double)trans_used / (double)vge.len[0], sum );
sewardjced9fe52004-07-07 11:55:36 +0000178 }
179
180 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000181 printf("\n");
sewardjd887b862005-01-17 18:34:34 +0000182 LibVEX_ShowAllocStats();
sewardjced9fe52004-07-07 11:55:36 +0000183
sewardjce605f92004-07-05 14:39:15 +0000184 return 0;
185}
sewardj9b1004e2004-10-30 22:25:40 +0000186
187//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000188//////////////////////////////////////////////////////////////////////
189//////////////////////////////////////////////////////////////////////
190//////////////////////////////////////////////////////////////////////
191//////////////////////////////////////////////////////////////////////
192//////////////////////////////////////////////////////////////////////
193//////////////////////////////////////////////////////////////////////
194//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000195
196static
sewardjde8a5ae2004-11-06 14:20:54 +0000197__attribute((noreturn))
sewardjde8c9872005-03-25 13:48:55 +0000198void panic ( HChar* s )
sewardj9b1004e2004-10-30 22:25:40 +0000199{
200 printf("\npanic: %s\n", s);
201 failure_exit();
202}
203
cerionaee45242005-03-17 14:03:36 +0000204#if 0 /* UNUSED */
sewardj9b1004e2004-10-30 22:25:40 +0000205static
sewardj9578a8b2004-11-04 19:44:48 +0000206IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000207{
208/* Use this rather than eg. -1 because it's a UInt. */
209#define INVALID_DATA_SIZE 999999
210
211 Int i;
212 Int sz;
213 IRCallee* helper;
214 IRStmt* st;
215 IRExpr* data;
216 IRExpr* addr;
217 Bool needSz;
218
219 /* Set up BB */
220 IRBB* bb = emptyIRBB();
221 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
222 bb->next = dopyIRExpr(bb_in->next);
223 bb->jumpkind = bb_in->jumpkind;
224
225 /* No loads to consider in ->next. */
sewardj496a58d2005-03-20 18:44:44 +0000226 assert(isIRAtom(bb_in->next));
sewardj9b1004e2004-10-30 22:25:40 +0000227
228 for (i = 0; i < bb_in->stmts_used; i++) {
229 st = bb_in->stmts[i];
230 if (!st) continue;
231
232 switch (st->tag) {
233
234 case Ist_Tmp:
235 data = st->Ist.Tmp.data;
236 if (data->tag == Iex_LDle) {
237 addr = data->Iex.LDle.addr;
238 sz = sizeofIRType(data->Iex.LDle.ty);
239 needSz = False;
240 switch (sz) {
241 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000242 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000243 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000244 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000245 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000246 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000247 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000248 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000249 needSz = True; break;
250 }
251 if (needSz) {
252 addStmtToIRBB(
253 bb,
254 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000255 unsafeIRDirty_0_N( helper->regparms,
256 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000257 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
258 ));
259 } else {
260 addStmtToIRBB(
261 bb,
262 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000263 unsafeIRDirty_0_N( helper->regparms,
264 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000265 mkIRExprVec_1(addr) )
266 ));
267 }
268 }
269 break;
270
271 case Ist_STle:
272 data = st->Ist.STle.data;
273 addr = st->Ist.STle.addr;
sewardj496a58d2005-03-20 18:44:44 +0000274 assert(isIRAtom(data));
275 assert(isIRAtom(addr));
sewardj9b1004e2004-10-30 22:25:40 +0000276 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
277 needSz = False;
278 switch (sz) {
279 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000280 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000281 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000282 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000283 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000284 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000285 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000286 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000287 needSz = True; break;
288 }
289 if (needSz) {
290 addStmtToIRBB(
291 bb,
292 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000293 unsafeIRDirty_0_N( helper->regparms,
294 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000295 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
296 ));
297 } else {
298 addStmtToIRBB(
299 bb,
300 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000301 unsafeIRDirty_0_N( helper->regparms,
302 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000303 mkIRExprVec_1(addr) )
304 ));
305 }
306 break;
307
308 case Ist_Put:
sewardj496a58d2005-03-20 18:44:44 +0000309 assert(isIRAtom(st->Ist.Put.data));
sewardj9b1004e2004-10-30 22:25:40 +0000310 break;
311
312 case Ist_PutI:
sewardj496a58d2005-03-20 18:44:44 +0000313 assert(isIRAtom(st->Ist.PutI.ix));
314 assert(isIRAtom(st->Ist.PutI.data));
sewardj9b1004e2004-10-30 22:25:40 +0000315 break;
316
317 case Ist_Exit:
sewardj496a58d2005-03-20 18:44:44 +0000318 assert(isIRAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000319 break;
320
321 case Ist_Dirty:
322 /* If the call doesn't interact with memory, we ain't
323 interested. */
324 if (st->Ist.Dirty.details->mFx == Ifx_None)
325 break;
326 goto unhandled;
327
328 default:
329 unhandled:
330 printf("\n");
331 ppIRStmt(st);
332 printf("\n");
333 panic("addrcheck: unhandled IRStmt");
334 }
335
336 addStmtToIRBB( bb, dopyIRStmt(st));
337 }
338
339 return bb;
340}
cerionaee45242005-03-17 14:03:36 +0000341#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +0000342
343//////////////////////////////////////////////////////////////////////
344//////////////////////////////////////////////////////////////////////
345//////////////////////////////////////////////////////////////////////
346//////////////////////////////////////////////////////////////////////
347//////////////////////////////////////////////////////////////////////
348//////////////////////////////////////////////////////////////////////
349//////////////////////////////////////////////////////////////////////
350//////////////////////////////////////////////////////////////////////
351
sewardj69f9e3e2004-12-30 02:05:34 +0000352#define tl_assert(xxx) assert(xxx)
sewardjde8a5ae2004-11-06 14:20:54 +0000353#define VG_(xxxx) xxxx
sewardj69f9e3e2004-12-30 02:05:34 +0000354#define tool_panic(zzz) panic(zzz)
sewardjde8a5ae2004-11-06 14:20:54 +0000355#define MC_(zzzz) MC_##zzzz
sewardj69f9e3e2004-12-30 02:05:34 +0000356#define TL_(zzzz) SK_##zzzz
sewardjde8a5ae2004-11-06 14:20:54 +0000357
cerionaee45242005-03-17 14:03:36 +0000358
sewardjde8c9872005-03-25 13:48:55 +0000359static void MC_helperc_complain_undef ( void );
360static void MC_helperc_LOADV8 ( void );
361static void MC_helperc_LOADV4 ( void );
362static void MC_helperc_LOADV2 ( void );
363static void MC_helperc_LOADV1 ( void );
364//static void MC_helperc_STOREV8( void );
365//static void MC_helperc_STOREV4( void );
366//static void MC_helperc_STOREV2( void );
367//static void MC_helperc_STOREV1( void );
368static void MC_helperc_value_check0_fail( void );
369static void MC_helperc_value_check1_fail( void );
370static void MC_helperc_value_check4_fail( void );
371
372static void MC_helperc_complain_undef ( void ) { }
373static void MC_helperc_LOADV8 ( void ) { }
374static void MC_helperc_LOADV4 ( void ) { }
375static void MC_helperc_LOADV2 ( void ) { }
376static void MC_helperc_LOADV1 ( void ) { }
377//static void MC_helperc_STOREV8( void ) { }
378//static void MC_helperc_STOREV4( void ) { }
379//static void MC_helperc_STOREV2( void ) { }
380//static void MC_helperc_STOREV1( void ) { }
381static void MC_helperc_value_check0_fail( void ) { }
382static void MC_helperc_value_check1_fail( void ) { }
383static void MC_helperc_value_check4_fail( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000384
385
sewardj3598ef92004-11-11 02:13:30 +0000386/*--------------------------------------------------------------------*/
387/*--- Instrument IR to perform memory checking operations. ---*/
388/*--- mc_translate.c ---*/
389/*--------------------------------------------------------------------*/
390
391/*
392 This file is part of MemCheck, a heavyweight Valgrind tool for
393 detecting memory errors.
394
395 Copyright (C) 2000-2004 Julian Seward
396 jseward@acm.org
397
398 This program is free software; you can redistribute it and/or
399 modify it under the terms of the GNU General Public License as
400 published by the Free Software Foundation; either version 2 of the
401 License, or (at your option) any later version.
402
403 This program is distributed in the hope that it will be useful, but
404 WITHOUT ANY WARRANTY; without even the implied warranty of
405 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
406 General Public License for more details.
407
408 You should have received a copy of the GNU General Public License
409 along with this program; if not, write to the Free Software
410 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
411 02111-1307, USA.
412
413 The GNU General Public License is contained in the file COPYING.
414*/
415
416//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000417
418
419/*------------------------------------------------------------*/
420/*--- Forward decls ---*/
421/*------------------------------------------------------------*/
422
423struct _MCEnv;
424
425static IRType shadowType ( IRType ty );
426static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
427
428
429/*------------------------------------------------------------*/
430/*--- Memcheck running state, and tmp management. ---*/
431/*------------------------------------------------------------*/
432
433/* Carries around state during memcheck instrumentation. */
434typedef
435 struct _MCEnv {
436 /* MODIFIED: the bb being constructed. IRStmts are added. */
437 IRBB* bb;
438
439 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
440 original temps to their current their current shadow temp.
441 Initially all entries are IRTemp_INVALID. Entries are added
442 lazily since many original temps are not used due to
443 optimisation prior to instrumentation. Note that floating
444 point original tmps are shadowed by integer tmps of the same
445 size, and Bit-typed original tmps are shadowed by the type
446 Ity_I8. See comment below. */
447 IRTemp* tmpMap;
448 Int n_originalTmps; /* for range checking */
449
450 /* READONLY: the guest layout. This indicates which parts of
451 the guest state should be regarded as 'always defined'. */
452 VexGuestLayout* layout;
453 /* READONLY: the host word type. Needed for constructing
454 arguments of type 'HWord' to be passed to helper functions.
455 Ity_I32 or Ity_I64 only. */
456 IRType hWordTy;
457 }
458 MCEnv;
459
460/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
461 demand), as they are encountered. This is for two reasons.
462
463 (1) (less important reason): Many original tmps are unused due to
464 initial IR optimisation, and we do not want to spaces in tables
465 tracking them.
466
467 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
468 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj69f9e3e2004-12-30 02:05:34 +0000469 each original tmp, or INVALID_IRTEMP if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000470 It is necessary to support making multiple assignments to a shadow
471 -- specifically, after testing a shadow for definedness, it needs
472 to be made defined. But IR's SSA property disallows this.
473
474 (2) (more important reason): Therefore, when a shadow needs to get
475 a new value, a new temporary is created, the value is assigned to
476 that, and the tmpMap is updated to reflect the new binding.
477
478 A corollary is that if the tmpMap maps a given tmp to
sewardj69f9e3e2004-12-30 02:05:34 +0000479 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000480 there's a read-before-write error in the original tmps. The IR
481 sanity checker should catch all such anomalies, however.
482*/
483
484/* Find the tmp currently shadowing the given original tmp. If none
485 so far exists, allocate one. */
486static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
487{
sewardj69f9e3e2004-12-30 02:05:34 +0000488 tl_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000489 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000490 mce->tmpMap[orig]
491 = newIRTemp(mce->bb->tyenv,
492 shadowType(mce->bb->tyenv->types[orig]));
493 }
494 return mce->tmpMap[orig];
495}
496
497/* Allocate a new shadow for the given original tmp. This means any
498 previous shadow is abandoned. This is needed because it is
499 necessary to give a new value to a shadow once it has been tested
500 for undefinedness, but unfortunately IR's SSA property disallows
501 this. Instead we must abandon the old shadow, allocate a new one
502 and use that instead. */
503static void newShadowTmp ( MCEnv* mce, IRTemp orig )
504{
sewardj69f9e3e2004-12-30 02:05:34 +0000505 tl_assert(orig < mce->n_originalTmps);
sewardjde8a5ae2004-11-06 14:20:54 +0000506 mce->tmpMap[orig]
507 = newIRTemp(mce->bb->tyenv,
508 shadowType(mce->bb->tyenv->types[orig]));
509}
510
511
512/*------------------------------------------------------------*/
513/*--- IRAtoms -- a subset of IRExprs ---*/
514/*------------------------------------------------------------*/
515
516/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj496a58d2005-03-20 18:44:44 +0000517 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardjde8a5ae2004-11-06 14:20:54 +0000518 input, most of this code deals in atoms. Usefully, a value atom
519 always has a V-value which is also an atom: constants are shadowed
520 by constants, and temps are shadowed by the corresponding shadow
521 temporary. */
522
523typedef IRExpr IRAtom;
524
525/* (used for sanity checks only): is this an atom which looks
526 like it's from original code? */
527static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
528{
529 if (a1->tag == Iex_Const)
530 return True;
531 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
532 return True;
533 return False;
534}
535
536/* (used for sanity checks only): is this an atom which looks
537 like it's from shadow code? */
538static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
539{
540 if (a1->tag == Iex_Const)
541 return True;
542 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
543 return True;
544 return False;
545}
546
547/* (used for sanity checks only): check that both args are atoms and
548 are identically-kinded. */
549static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
550{
551 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
552 return True;
553 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
554 return True;
555 return False;
556}
557
558
559/*------------------------------------------------------------*/
560/*--- Type management ---*/
561/*------------------------------------------------------------*/
562
563/* Shadow state is always accessed using integer types. This returns
564 an integer type with the same size (as per sizeofIRType) as the
565 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj69f9e3e2004-12-30 02:05:34 +0000566 I64, V128. */
sewardjde8a5ae2004-11-06 14:20:54 +0000567
568static IRType shadowType ( IRType ty )
569{
570 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000571 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000572 case Ity_I8:
573 case Ity_I16:
574 case Ity_I32:
sewardj69f9e3e2004-12-30 02:05:34 +0000575 case Ity_I64: return ty;
576 case Ity_F32: return Ity_I32;
577 case Ity_F64: return Ity_I64;
578 case Ity_V128: return Ity_V128;
sewardjde8a5ae2004-11-06 14:20:54 +0000579 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000580 VG_(tool_panic)("memcheck:shadowType");
sewardjde8a5ae2004-11-06 14:20:54 +0000581 }
582}
583
584/* Produce a 'defined' value of the given shadow type. Should only be
585 supplied shadow types (Bit/I8/I16/I32/UI64). */
586static IRExpr* definedOfType ( IRType ty ) {
587 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000588 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
589 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
590 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
591 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
592 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
593 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
594 default: VG_(tool_panic)("memcheck:definedOfType");
sewardjde8a5ae2004-11-06 14:20:54 +0000595 }
596}
597
598
599/*------------------------------------------------------------*/
600/*--- Constructing IR fragments ---*/
601/*------------------------------------------------------------*/
602
603/* assign value to tmp */
604#define assign(_bb,_tmp,_expr) \
605 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
606
607/* add stmt to a bb */
608#define stmt(_bb,_stmt) \
609 addStmtToIRBB((_bb), (_stmt))
610
611/* build various kinds of expressions */
612#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
613#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
614#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
615#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
616#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
617#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj69f9e3e2004-12-30 02:05:34 +0000618#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardjde8a5ae2004-11-06 14:20:54 +0000619#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
620
621/* bind the given expression to a new temporary, and return the
622 temporary. This effectively converts an arbitrary expression into
623 an atom. */
624static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
625 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
626 assign(mce->bb, t, e);
627 return mkexpr(t);
628}
629
630
631/*------------------------------------------------------------*/
632/*--- Constructing definedness primitive ops ---*/
633/*------------------------------------------------------------*/
634
635/* --------- Defined-if-either-defined --------- */
636
637static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000638 tl_assert(isShadowAtom(mce,a1));
639 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000640 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
641}
642
643static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000644 tl_assert(isShadowAtom(mce,a1));
645 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000646 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
647}
648
649static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000650 tl_assert(isShadowAtom(mce,a1));
651 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000652 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
653}
654
sewardj69f9e3e2004-12-30 02:05:34 +0000655static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
656 tl_assert(isShadowAtom(mce,a1));
657 tl_assert(isShadowAtom(mce,a2));
658 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
659}
660
sewardjf0c1c582005-02-07 23:47:38 +0000661static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000662 tl_assert(isShadowAtom(mce,a1));
663 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000664 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000665}
666
sewardjde8a5ae2004-11-06 14:20:54 +0000667/* --------- Undefined-if-either-undefined --------- */
668
669static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000670 tl_assert(isShadowAtom(mce,a1));
671 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000672 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
673}
674
675static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000676 tl_assert(isShadowAtom(mce,a1));
677 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000678 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
679}
680
681static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000682 tl_assert(isShadowAtom(mce,a1));
683 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000684 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
685}
686
687static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000688 tl_assert(isShadowAtom(mce,a1));
689 tl_assert(isShadowAtom(mce,a2));
sewardjde8a5ae2004-11-06 14:20:54 +0000690 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
691}
692
sewardjf0c1c582005-02-07 23:47:38 +0000693static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000694 tl_assert(isShadowAtom(mce,a1));
695 tl_assert(isShadowAtom(mce,a2));
sewardjf0c1c582005-02-07 23:47:38 +0000696 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj69f9e3e2004-12-30 02:05:34 +0000697}
698
699static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardjde8a5ae2004-11-06 14:20:54 +0000700 switch (vty) {
sewardj69f9e3e2004-12-30 02:05:34 +0000701 case Ity_I8: return mkUifU8(mce, a1, a2);
702 case Ity_I16: return mkUifU16(mce, a1, a2);
703 case Ity_I32: return mkUifU32(mce, a1, a2);
704 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardjf0c1c582005-02-07 23:47:38 +0000705 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000706 default:
707 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +0000708 VG_(tool_panic)("memcheck:mkUifU");
sewardjde8a5ae2004-11-06 14:20:54 +0000709 }
710}
711
712/* --------- The Left-family of operations. --------- */
713
714static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000715 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000716 /* It's safe to duplicate a1 since it's only an atom */
717 return assignNew(mce, Ity_I8,
718 binop(Iop_Or8, a1,
719 assignNew(mce, Ity_I8,
720 /* unop(Iop_Neg8, a1)))); */
721 binop(Iop_Sub8, mkU8(0), a1) )));
722}
723
724static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000725 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000726 /* It's safe to duplicate a1 since it's only an atom */
727 return assignNew(mce, Ity_I16,
728 binop(Iop_Or16, a1,
729 assignNew(mce, Ity_I16,
730 /* unop(Iop_Neg16, a1)))); */
731 binop(Iop_Sub16, mkU16(0), a1) )));
732}
733
734static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
sewardj69f9e3e2004-12-30 02:05:34 +0000735 tl_assert(isShadowAtom(mce,a1));
sewardjde8a5ae2004-11-06 14:20:54 +0000736 /* It's safe to duplicate a1 since it's only an atom */
737 return assignNew(mce, Ity_I32,
738 binop(Iop_Or32, a1,
739 assignNew(mce, Ity_I32,
740 /* unop(Iop_Neg32, a1)))); */
741 binop(Iop_Sub32, mkU32(0), a1) )));
742}
743
744/* --------- 'Improvement' functions for AND/OR. --------- */
745
746/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
747 defined (0); all other -> undefined (1).
748*/
749static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
750{
sewardj69f9e3e2004-12-30 02:05:34 +0000751 tl_assert(isOriginalAtom(mce, data));
752 tl_assert(isShadowAtom(mce, vbits));
753 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000754 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
755}
756
sewardj3598ef92004-11-11 02:13:30 +0000757static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
758{
sewardj69f9e3e2004-12-30 02:05:34 +0000759 tl_assert(isOriginalAtom(mce, data));
760 tl_assert(isShadowAtom(mce, vbits));
761 tl_assert(sameKindedAtoms(data, vbits));
sewardj3598ef92004-11-11 02:13:30 +0000762 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
763}
764
sewardjde8a5ae2004-11-06 14:20:54 +0000765static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
766{
sewardj69f9e3e2004-12-30 02:05:34 +0000767 tl_assert(isOriginalAtom(mce, data));
768 tl_assert(isShadowAtom(mce, vbits));
769 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000770 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
771}
772
sewardj69f9e3e2004-12-30 02:05:34 +0000773static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
774{
775 tl_assert(isOriginalAtom(mce, data));
776 tl_assert(isShadowAtom(mce, vbits));
777 tl_assert(sameKindedAtoms(data, vbits));
778 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
779}
780
sewardjf0c1c582005-02-07 23:47:38 +0000781static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000782{
783 tl_assert(isOriginalAtom(mce, data));
784 tl_assert(isShadowAtom(mce, vbits));
785 tl_assert(sameKindedAtoms(data, vbits));
sewardjf0c1c582005-02-07 23:47:38 +0000786 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj69f9e3e2004-12-30 02:05:34 +0000787}
788
sewardjde8a5ae2004-11-06 14:20:54 +0000789/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
790 defined (0); all other -> undefined (1).
791*/
792static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
793{
sewardj69f9e3e2004-12-30 02:05:34 +0000794 tl_assert(isOriginalAtom(mce, data));
795 tl_assert(isShadowAtom(mce, vbits));
796 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000797 return assignNew(
798 mce, Ity_I8,
799 binop(Iop_Or8,
800 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
801 vbits) );
802}
803
804static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
805{
sewardj69f9e3e2004-12-30 02:05:34 +0000806 tl_assert(isOriginalAtom(mce, data));
807 tl_assert(isShadowAtom(mce, vbits));
808 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000809 return assignNew(
810 mce, Ity_I16,
811 binop(Iop_Or16,
812 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
813 vbits) );
814}
815
816static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
817{
sewardj69f9e3e2004-12-30 02:05:34 +0000818 tl_assert(isOriginalAtom(mce, data));
819 tl_assert(isShadowAtom(mce, vbits));
820 tl_assert(sameKindedAtoms(data, vbits));
sewardjde8a5ae2004-11-06 14:20:54 +0000821 return assignNew(
822 mce, Ity_I32,
823 binop(Iop_Or32,
824 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
825 vbits) );
826}
827
sewardj69f9e3e2004-12-30 02:05:34 +0000828static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
829{
830 tl_assert(isOriginalAtom(mce, data));
831 tl_assert(isShadowAtom(mce, vbits));
832 tl_assert(sameKindedAtoms(data, vbits));
833 return assignNew(
834 mce, Ity_I64,
835 binop(Iop_Or64,
836 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
837 vbits) );
838}
839
sewardjf0c1c582005-02-07 23:47:38 +0000840static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj69f9e3e2004-12-30 02:05:34 +0000841{
842 tl_assert(isOriginalAtom(mce, data));
843 tl_assert(isShadowAtom(mce, vbits));
844 tl_assert(sameKindedAtoms(data, vbits));
845 return assignNew(
846 mce, Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +0000847 binop(Iop_OrV128,
848 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj69f9e3e2004-12-30 02:05:34 +0000849 vbits) );
850}
851
sewardjde8a5ae2004-11-06 14:20:54 +0000852/* --------- Pessimising casts. --------- */
853
854static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
855{
sewardj8fc93742004-11-22 11:29:33 +0000856 IRType ty;
857 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000858 /* Note, dst_ty is a shadow type, not an original type. */
859 /* First of all, collapse vbits down to a single bit. */
sewardj69f9e3e2004-12-30 02:05:34 +0000860 tl_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000861 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
862 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000863 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000864 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000865 tmp1 = vbits;
866 break;
867 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000868 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000869 break;
870 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000871 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000872 break;
873 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000874 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000875 break;
876 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000877 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000878 break;
879 default:
sewardj69f9e3e2004-12-30 02:05:34 +0000880 VG_(tool_panic)("mkPCastTo(1)");
sewardjde8a5ae2004-11-06 14:20:54 +0000881 }
sewardj69f9e3e2004-12-30 02:05:34 +0000882 tl_assert(tmp1);
sewardjde8a5ae2004-11-06 14:20:54 +0000883 /* Now widen up to the dst type. */
884 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000885 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000886 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000887 case Ity_I8:
888 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000889 case Ity_I16:
890 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
891 case Ity_I32:
892 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
893 case Ity_I64:
894 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000895 case Ity_V128:
896 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardjf0c1c582005-02-07 23:47:38 +0000897 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardj69f9e3e2004-12-30 02:05:34 +0000898 return tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000899 default:
900 ppIRType(dst_ty);
sewardj69f9e3e2004-12-30 02:05:34 +0000901 VG_(tool_panic)("mkPCastTo(2)");
sewardjde8a5ae2004-11-06 14:20:54 +0000902 }
903}
904
905
906/*------------------------------------------------------------*/
907/*--- Emit a test and complaint if something is undefined. ---*/
908/*------------------------------------------------------------*/
909
910/* Set the annotations on a dirty helper to indicate that the stack
911 pointer and instruction pointers might be read. This is the
912 behaviour of all 'emit-a-complaint' style functions we might
913 call. */
914
915static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
916 di->nFxState = 2;
917 di->fxState[0].fx = Ifx_Read;
918 di->fxState[0].offset = mce->layout->offset_SP;
919 di->fxState[0].size = mce->layout->sizeof_SP;
920 di->fxState[1].fx = Ifx_Read;
921 di->fxState[1].offset = mce->layout->offset_IP;
922 di->fxState[1].size = mce->layout->sizeof_IP;
923}
924
925
926/* Check the supplied **original** atom for undefinedness, and emit a
927 complaint if so. Once that happens, mark it as defined. This is
928 possible because the atom is either a tmp or literal. If it's a
929 tmp, it will be shadowed by a tmp, and so we can set the shadow to
930 be defined. In fact as mentioned above, we will have to allocate a
931 new tmp to carry the new 'defined' shadow value, and update the
932 original->tmp mapping accordingly; we cannot simply assign a new
933 value to an existing shadow tmp as this breaks SSAness -- resulting
934 in the post-instrumentation sanity checker spluttering in disapproval.
935*/
936static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
937{
sewardj8fc93742004-11-22 11:29:33 +0000938 IRAtom* vatom;
sewardj69f9e3e2004-12-30 02:05:34 +0000939 IRType ty;
940 Int sz;
sewardj8fc93742004-11-22 11:29:33 +0000941 IRDirty* di;
sewardj69f9e3e2004-12-30 02:05:34 +0000942 IRAtom* cond;
sewardj8fc93742004-11-22 11:29:33 +0000943
sewardjde8a5ae2004-11-06 14:20:54 +0000944 /* Since the original expression is atomic, there's no duplicated
945 work generated by making multiple V-expressions for it. So we
946 don't really care about the possibility that someone else may
947 also create a V-interpretion for it. */
sewardj69f9e3e2004-12-30 02:05:34 +0000948 tl_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +0000949 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +0000950 tl_assert(isShadowAtom(mce, vatom));
951 tl_assert(sameKindedAtoms(atom, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +0000952
sewardj8fc93742004-11-22 11:29:33 +0000953 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +0000954
955 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +0000956 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +0000957
sewardj8fc93742004-11-22 11:29:33 +0000958 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +0000959 /* cond will be 0 if all defined, and 1 if any not defined. */
960
sewardj3598ef92004-11-11 02:13:30 +0000961 switch (sz) {
962 case 0:
963 di = unsafeIRDirty_0_N( 0/*regparms*/,
964 "MC_(helperc_value_check0_fail)",
965 &MC_(helperc_value_check0_fail),
966 mkIRExprVec_0()
967 );
968 break;
969 case 1:
970 di = unsafeIRDirty_0_N( 0/*regparms*/,
971 "MC_(helperc_value_check1_fail)",
972 &MC_(helperc_value_check1_fail),
973 mkIRExprVec_0()
974 );
975 break;
976 case 4:
977 di = unsafeIRDirty_0_N( 0/*regparms*/,
978 "MC_(helperc_value_check4_fail)",
979 &MC_(helperc_value_check4_fail),
980 mkIRExprVec_0()
981 );
982 break;
983 default:
984 di = unsafeIRDirty_0_N( 1/*regparms*/,
985 "MC_(helperc_complain_undef)",
986 &MC_(helperc_complain_undef),
987 mkIRExprVec_1( mkIRExpr_HWord( sz ))
988 );
989 break;
990 }
sewardjde8a5ae2004-11-06 14:20:54 +0000991 di->guard = cond;
992 setHelperAnns( mce, di );
993 stmt( mce->bb, IRStmt_Dirty(di));
994
995 /* Set the shadow tmp to be defined. First, update the
996 orig->shadow tmp mapping to reflect the fact that this shadow is
997 getting a new value. */
sewardj496a58d2005-03-20 18:44:44 +0000998 tl_assert(isIRAtom(vatom));
sewardjde8a5ae2004-11-06 14:20:54 +0000999 /* sameKindedAtoms ... */
1000 if (vatom->tag == Iex_Tmp) {
sewardj69f9e3e2004-12-30 02:05:34 +00001001 tl_assert(atom->tag == Iex_Tmp);
sewardjde8a5ae2004-11-06 14:20:54 +00001002 newShadowTmp(mce, atom->Iex.Tmp.tmp);
1003 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
1004 definedOfType(ty));
1005 }
1006}
1007
1008
1009/*------------------------------------------------------------*/
1010/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
1011/*------------------------------------------------------------*/
1012
1013/* Examine the always-defined sections declared in layout to see if
1014 the (offset,size) section is within one. Note, is is an error to
1015 partially fall into such a region: (offset,size) should either be
1016 completely in such a region or completely not-in such a region.
1017*/
1018static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1019{
1020 Int minoffD, maxoffD, i;
1021 Int minoff = offset;
1022 Int maxoff = minoff + size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001023 tl_assert((minoff & ~0xFFFF) == 0);
1024 tl_assert((maxoff & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001025
1026 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1027 minoffD = mce->layout->alwaysDefd[i].offset;
1028 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
sewardj69f9e3e2004-12-30 02:05:34 +00001029 tl_assert((minoffD & ~0xFFFF) == 0);
1030 tl_assert((maxoffD & ~0xFFFF) == 0);
sewardjde8a5ae2004-11-06 14:20:54 +00001031
1032 if (maxoff < minoffD || maxoffD < minoff)
1033 continue; /* no overlap */
1034 if (minoff >= minoffD && maxoff <= maxoffD)
1035 return True; /* completely contained in an always-defd section */
1036
sewardj69f9e3e2004-12-30 02:05:34 +00001037 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
sewardjde8a5ae2004-11-06 14:20:54 +00001038 }
1039 return False; /* could not find any containing section */
1040}
1041
1042
cerionaee45242005-03-17 14:03:36 +00001043#if 0 /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00001044/* Generate into bb suitable actions to shadow this Put. If the state
1045 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +00001046 supplied V bits to the shadow state. We can pass in either an
1047 original atom or a V-atom, but not both. In the former case the
1048 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +00001049*/
1050static
sewardj3598ef92004-11-11 02:13:30 +00001051void do_shadow_PUT ( MCEnv* mce, Int offset,
1052 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +00001053{
sewardj8fc93742004-11-22 11:29:33 +00001054 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +00001055 if (atom) {
sewardj69f9e3e2004-12-30 02:05:34 +00001056 tl_assert(!vatom);
1057 tl_assert(isOriginalAtom(mce, atom));
sewardj3598ef92004-11-11 02:13:30 +00001058 vatom = expr2vbits( mce, atom );
1059 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001060 tl_assert(vatom);
1061 tl_assert(isShadowAtom(mce, vatom));
sewardj3598ef92004-11-11 02:13:30 +00001062 }
1063
sewardj8fc93742004-11-22 11:29:33 +00001064 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj69f9e3e2004-12-30 02:05:34 +00001065 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001066 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1067 /* later: no ... */
1068 /* emit code to emit a complaint if any of the vbits are 1. */
1069 /* complainIfUndefined(mce, atom); */
1070 } else {
1071 /* Do a plain shadow Put. */
1072 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1073 }
1074}
1075
1076
1077/* Return an expression which contains the V bits corresponding to the
1078 given GETI (passed in in pieces).
1079*/
1080static
1081void do_shadow_PUTI ( MCEnv* mce,
1082 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
1083{
sewardj8fc93742004-11-22 11:29:33 +00001084 IRAtom* vatom;
1085 IRType ty, tyS;
sewardj69f9e3e2004-12-30 02:05:34 +00001086 Int arrSize;;
sewardj8fc93742004-11-22 11:29:33 +00001087
sewardj69f9e3e2004-12-30 02:05:34 +00001088 tl_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +00001089 vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001090 tl_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +00001091 ty = descr->elemTy;
1092 tyS = shadowType(ty);
1093 arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001094 tl_assert(ty != Ity_I1);
1095 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001096 complainIfUndefined(mce,ix);
1097 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1098 /* later: no ... */
1099 /* emit code to emit a complaint if any of the vbits are 1. */
1100 /* complainIfUndefined(mce, atom); */
1101 } else {
1102 /* Do a cloned version of the Put that refers to the shadow
1103 area. */
1104 IRArray* new_descr
1105 = mkIRArray( descr->base + mce->layout->total_sizeB,
1106 tyS, descr->nElems);
1107 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1108 }
1109}
cerionaee45242005-03-17 14:03:36 +00001110#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00001111
1112
1113/* Return an expression which contains the V bits corresponding to the
1114 given GET (passed in in pieces).
1115*/
1116static
1117IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1118{
1119 IRType tyS = shadowType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001120 tl_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001121 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1122 /* Always defined, return all zeroes of the relevant type */
1123 return definedOfType(tyS);
1124 } else {
1125 /* return a cloned version of the Get that refers to the shadow
1126 area. */
1127 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1128 }
1129}
1130
1131
1132/* Return an expression which contains the V bits corresponding to the
1133 given GETI (passed in in pieces).
1134*/
1135static
1136IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
1137{
1138 IRType ty = descr->elemTy;
1139 IRType tyS = shadowType(ty);
1140 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001141 tl_assert(ty != Ity_I1);
1142 tl_assert(isOriginalAtom(mce,ix));
sewardjde8a5ae2004-11-06 14:20:54 +00001143 complainIfUndefined(mce,ix);
1144 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1145 /* Always defined, return all zeroes of the relevant type */
1146 return definedOfType(tyS);
1147 } else {
1148 /* return a cloned version of the Get that refers to the shadow
1149 area. */
1150 IRArray* new_descr
1151 = mkIRArray( descr->base + mce->layout->total_sizeB,
1152 tyS, descr->nElems);
1153 return IRExpr_GetI( new_descr, ix, bias );
1154 }
1155}
1156
1157
1158/*------------------------------------------------------------*/
1159/*--- Generating approximations for unknown operations, ---*/
1160/*--- using lazy-propagate semantics ---*/
1161/*------------------------------------------------------------*/
1162
1163/* Lazy propagation of undefinedness from two values, resulting in the
1164 specified shadow type.
1165*/
1166static
1167IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1168{
1169 /* force everything via 32-bit intermediaries. */
1170 IRAtom* at;
sewardj69f9e3e2004-12-30 02:05:34 +00001171 tl_assert(isShadowAtom(mce,va1));
1172 tl_assert(isShadowAtom(mce,va2));
sewardjde8a5ae2004-11-06 14:20:54 +00001173 at = mkPCastTo(mce, Ity_I32, va1);
1174 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1175 at = mkPCastTo(mce, finalVty, at);
1176 return at;
1177}
1178
1179
1180/* Do the lazy propagation game from a null-terminated vector of
1181 atoms. This is presumably the arguments to a helper call, so the
1182 IRCallee info is also supplied in order that we can know which
1183 arguments should be ignored (via the .mcx_mask field).
1184*/
1185static
1186IRAtom* mkLazyN ( MCEnv* mce,
1187 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1188{
1189 Int i;
1190 IRAtom* here;
1191 IRAtom* curr = definedOfType(Ity_I32);
1192 for (i = 0; exprvec[i]; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00001193 tl_assert(i < 32);
1194 tl_assert(isOriginalAtom(mce, exprvec[i]));
sewardjde8a5ae2004-11-06 14:20:54 +00001195 /* Only take notice of this arg if the callee's mc-exclusion
1196 mask does not say it is to be excluded. */
1197 if (cee->mcx_mask & (1<<i)) {
1198 /* the arg is to be excluded from definedness checking. Do
1199 nothing. */
1200 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1201 } else {
1202 /* calculate the arg's definedness, and pessimistically merge
1203 it in. */
1204 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1205 curr = mkUifU32(mce, here, curr);
1206 }
1207 }
1208 return mkPCastTo(mce, finalVtype, curr );
1209}
1210
1211
cerionaee45242005-03-17 14:03:36 +00001212#if 0 /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00001213/*------------------------------------------------------------*/
1214/*--- Generating expensive sequences for exact carry-chain ---*/
1215/*--- propagation in add/sub and related operations. ---*/
1216/*------------------------------------------------------------*/
1217
1218static
1219IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1220 IRAtom* aa, IRAtom* bb )
1221{
sewardj69f9e3e2004-12-30 02:05:34 +00001222 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardj8fc93742004-11-22 11:29:33 +00001223 IRType ty;
1224 IROp opAND, opOR, opXOR, opNOT, opADD;
sewardj8fc93742004-11-22 11:29:33 +00001225
sewardj69f9e3e2004-12-30 02:05:34 +00001226 tl_assert(isShadowAtom(mce,qaa));
1227 tl_assert(isShadowAtom(mce,qbb));
1228 tl_assert(isOriginalAtom(mce,aa));
1229 tl_assert(isOriginalAtom(mce,bb));
1230 tl_assert(sameKindedAtoms(qaa,aa));
1231 tl_assert(sameKindedAtoms(qbb,bb));
sewardjde8a5ae2004-11-06 14:20:54 +00001232
sewardj8fc93742004-11-22 11:29:33 +00001233 ty = Ity_I32;
1234 opAND = Iop_And32;
1235 opOR = Iop_Or32;
1236 opXOR = Iop_Xor32;
1237 opNOT = Iop_Not32;
1238 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001239
1240 // a_min = aa & ~qaa
1241 a_min = assignNew(mce,ty,
1242 binop(opAND, aa,
1243 assignNew(mce,ty, unop(opNOT, qaa))));
1244
1245 // b_min = bb & ~qbb
1246 b_min = assignNew(mce,ty,
1247 binop(opAND, bb,
1248 assignNew(mce,ty, unop(opNOT, qbb))));
1249
1250 // a_max = aa | qaa
1251 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1252
1253 // b_max = bb | qbb
1254 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1255
1256 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1257 return
1258 assignNew(mce,ty,
1259 binop( opOR,
1260 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1261 assignNew(mce,ty,
1262 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1263 assignNew(mce,ty, binop(opADD, a_max, b_max))
1264 )
1265 )
1266 )
1267 );
1268}
cerionaee45242005-03-17 14:03:36 +00001269#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00001270
1271
1272/*------------------------------------------------------------*/
sewardj69f9e3e2004-12-30 02:05:34 +00001273/*--- Helpers for dealing with vector primops. ---*/
1274/*------------------------------------------------------------*/
1275
1276/* Vector pessimisation -- pessimise within each lane individually. */
1277
1278static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1279{
1280 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1281}
1282
1283static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1284{
1285 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1286}
1287
1288static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1289{
1290 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1291}
1292
1293static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1294{
1295 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1296}
1297
1298
1299/* Here's a simple scheme capable of handling ops derived from SSE1
1300 code and while only generating ops that can be efficiently
1301 implemented in SSE1. */
1302
1303/* All-lanes versions are straightforward:
1304
sewardjf0c1c582005-02-07 23:47:38 +00001305 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj69f9e3e2004-12-30 02:05:34 +00001306
1307 unary32Fx4(x,y) ==> PCast32x4(x#)
1308
1309 Lowest-lane-only versions are more complex:
1310
sewardjf0c1c582005-02-07 23:47:38 +00001311 binary32F0x4(x,y) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001312 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001313 PCast32(V128to32(UifUV128(x#,y#)))
sewardj69f9e3e2004-12-30 02:05:34 +00001314 )
1315
1316 This is perhaps not so obvious. In particular, it's faster to
sewardjf0c1c582005-02-07 23:47:38 +00001317 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj69f9e3e2004-12-30 02:05:34 +00001318 obvious scheme of taking the bottom 32 bits of each operand
1319 and doing a 32-bit UifU. Basically since UifU is fast and
1320 chopping lanes off vector values is slow.
1321
1322 Finally:
1323
sewardjf0c1c582005-02-07 23:47:38 +00001324 unary32F0x4(x) ==> SetV128lo32(
sewardj69f9e3e2004-12-30 02:05:34 +00001325 x#,
sewardjf0c1c582005-02-07 23:47:38 +00001326 PCast32(V128to32(x#))
sewardj69f9e3e2004-12-30 02:05:34 +00001327 )
1328
1329 Where:
1330
1331 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1332 PCast32x4(v#) = CmpNEZ32x4(v#)
1333*/
1334
1335static
1336IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1337{
1338 IRAtom* at;
1339 tl_assert(isShadowAtom(mce, vatomX));
1340 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001341 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001342 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
1343 return at;
1344}
1345
1346static
1347IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1348{
1349 IRAtom* at;
1350 tl_assert(isShadowAtom(mce, vatomX));
1351 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
1352 return at;
1353}
1354
1355static
1356IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1357{
1358 IRAtom* at;
1359 tl_assert(isShadowAtom(mce, vatomX));
1360 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001361 at = mkUifUV128(mce, vatomX, vatomY);
1362 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001363 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001364 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001365 return at;
1366}
1367
1368static
1369IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1370{
1371 IRAtom* at;
1372 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001373 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001374 at = mkPCastTo(mce, Ity_I32, at);
sewardjf0c1c582005-02-07 23:47:38 +00001375 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001376 return at;
1377}
1378
1379/* --- ... and ... 64Fx2 versions of the same ... --- */
1380
1381static
1382IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1383{
1384 IRAtom* at;
1385 tl_assert(isShadowAtom(mce, vatomX));
1386 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001387 at = mkUifUV128(mce, vatomX, vatomY);
sewardj69f9e3e2004-12-30 02:05:34 +00001388 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
1389 return at;
1390}
1391
1392static
1393IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1394{
1395 IRAtom* at;
1396 tl_assert(isShadowAtom(mce, vatomX));
1397 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
1398 return at;
1399}
1400
1401static
1402IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1403{
1404 IRAtom* at;
1405 tl_assert(isShadowAtom(mce, vatomX));
1406 tl_assert(isShadowAtom(mce, vatomY));
sewardjf0c1c582005-02-07 23:47:38 +00001407 at = mkUifUV128(mce, vatomX, vatomY);
1408 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001409 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001410 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001411 return at;
1412}
1413
1414static
1415IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1416{
1417 IRAtom* at;
1418 tl_assert(isShadowAtom(mce, vatomX));
sewardjf0c1c582005-02-07 23:47:38 +00001419 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj69f9e3e2004-12-30 02:05:34 +00001420 at = mkPCastTo(mce, Ity_I64, at);
sewardjf0c1c582005-02-07 23:47:38 +00001421 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj69f9e3e2004-12-30 02:05:34 +00001422 return at;
1423}
1424
1425/* --- --- Vector saturated narrowing --- --- */
1426
1427/* This is quite subtle. What to do is simple:
1428
1429 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1430
1431 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1432
1433 Why this is right is not so simple. Consider a lane in the args,
1434 vatom1 or 2, doesn't matter.
1435
1436 After the PCast, that lane is all 0s (defined) or all
1437 1s(undefined).
1438
1439 Both signed and unsigned saturating narrowing of all 0s produces
1440 all 0s, which is what we want.
1441
1442 The all-1s case is more complex. Unsigned narrowing interprets an
1443 all-1s input as the largest unsigned integer, and so produces all
1444 1s as a result since that is the largest unsigned value at the
1445 smaller width.
1446
1447 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1448 to -1, so we still wind up with all 1s at the smaller width.
1449
1450 So: In short, pessimise the args, then apply the original narrowing
1451 op.
1452*/
1453static
sewardjf0c1c582005-02-07 23:47:38 +00001454IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardj69f9e3e2004-12-30 02:05:34 +00001455 IRAtom* vatom1, IRAtom* vatom2)
1456{
1457 IRAtom *at1, *at2, *at3;
1458 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1459 switch (narrow_op) {
1460 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1461 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1462 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardjf0c1c582005-02-07 23:47:38 +00001463 default: VG_(tool_panic)("vectorNarrowV128");
sewardj69f9e3e2004-12-30 02:05:34 +00001464 }
1465 tl_assert(isShadowAtom(mce,vatom1));
1466 tl_assert(isShadowAtom(mce,vatom2));
1467 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1468 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1469 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1470 return at3;
1471}
1472
1473
1474/* --- --- Vector integer arithmetic --- --- */
1475
1476/* Simple ... UifU the args and per-lane pessimise the results. */
1477static
1478IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1479{
1480 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001481 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001482 at = mkPCast8x16(mce, at);
1483 return at;
1484}
1485
1486static
1487IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1488{
1489 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001490 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001491 at = mkPCast16x8(mce, at);
1492 return at;
1493}
1494
1495static
1496IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1497{
1498 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001499 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001500 at = mkPCast32x4(mce, at);
1501 return at;
1502}
1503
1504static
1505IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1506{
1507 IRAtom* at;
sewardjf0c1c582005-02-07 23:47:38 +00001508 at = mkUifUV128(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001509 at = mkPCast64x2(mce, at);
1510 return at;
1511}
1512
1513
1514/*------------------------------------------------------------*/
sewardjde8a5ae2004-11-06 14:20:54 +00001515/*--- Generate shadow values from all kinds of IRExprs. ---*/
1516/*------------------------------------------------------------*/
1517
1518static
1519IRAtom* expr2vbits_Binop ( MCEnv* mce,
1520 IROp op,
1521 IRAtom* atom1, IRAtom* atom2 )
1522{
1523 IRType and_or_ty;
1524 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1525 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1526 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1527
1528 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1529 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1530
sewardj69f9e3e2004-12-30 02:05:34 +00001531 tl_assert(isOriginalAtom(mce,atom1));
1532 tl_assert(isOriginalAtom(mce,atom2));
1533 tl_assert(isShadowAtom(mce,vatom1));
1534 tl_assert(isShadowAtom(mce,vatom2));
1535 tl_assert(sameKindedAtoms(atom1,vatom1));
1536 tl_assert(sameKindedAtoms(atom2,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001537 switch (op) {
1538
sewardjf0c1c582005-02-07 23:47:38 +00001539 /* V128-bit SIMD (SSE2-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001540
1541 case Iop_ShrN16x8:
1542 case Iop_ShrN32x4:
1543 case Iop_ShrN64x2:
1544 case Iop_SarN16x8:
1545 case Iop_SarN32x4:
1546 case Iop_ShlN16x8:
1547 case Iop_ShlN32x4:
1548 case Iop_ShlN64x2:
1549 /* Same scheme as with all other shifts. */
1550 complainIfUndefined(mce, atom2);
1551 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1552
1553 case Iop_QSub8Ux16:
1554 case Iop_QSub8Sx16:
1555 case Iop_Sub8x16:
1556 case Iop_Min8Ux16:
1557 case Iop_Max8Ux16:
1558 case Iop_CmpGT8Sx16:
1559 case Iop_CmpEQ8x16:
1560 case Iop_Avg8Ux16:
1561 case Iop_QAdd8Ux16:
1562 case Iop_QAdd8Sx16:
1563 case Iop_Add8x16:
1564 return binary8Ix16(mce, vatom1, vatom2);
1565
1566 case Iop_QSub16Ux8:
1567 case Iop_QSub16Sx8:
1568 case Iop_Sub16x8:
1569 case Iop_Mul16x8:
1570 case Iop_MulHi16Sx8:
1571 case Iop_MulHi16Ux8:
1572 case Iop_Min16Sx8:
1573 case Iop_Max16Sx8:
1574 case Iop_CmpGT16Sx8:
1575 case Iop_CmpEQ16x8:
1576 case Iop_Avg16Ux8:
1577 case Iop_QAdd16Ux8:
1578 case Iop_QAdd16Sx8:
1579 case Iop_Add16x8:
1580 return binary16Ix8(mce, vatom1, vatom2);
1581
1582 case Iop_Sub32x4:
1583 case Iop_CmpGT32Sx4:
1584 case Iop_CmpEQ32x4:
1585 case Iop_Add32x4:
1586 return binary32Ix4(mce, vatom1, vatom2);
1587
1588 case Iop_Sub64x2:
1589 case Iop_Add64x2:
1590 return binary64Ix2(mce, vatom1, vatom2);
1591
1592 case Iop_QNarrow32Sx4:
1593 case Iop_QNarrow16Sx8:
1594 case Iop_QNarrow16Ux8:
sewardjf0c1c582005-02-07 23:47:38 +00001595 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001596
1597 case Iop_Sub64Fx2:
1598 case Iop_Mul64Fx2:
1599 case Iop_Min64Fx2:
1600 case Iop_Max64Fx2:
1601 case Iop_Div64Fx2:
1602 case Iop_CmpLT64Fx2:
1603 case Iop_CmpLE64Fx2:
1604 case Iop_CmpEQ64Fx2:
1605 case Iop_Add64Fx2:
1606 return binary64Fx2(mce, vatom1, vatom2);
1607
1608 case Iop_Sub64F0x2:
1609 case Iop_Mul64F0x2:
1610 case Iop_Min64F0x2:
1611 case Iop_Max64F0x2:
1612 case Iop_Div64F0x2:
1613 case Iop_CmpLT64F0x2:
1614 case Iop_CmpLE64F0x2:
1615 case Iop_CmpEQ64F0x2:
1616 case Iop_Add64F0x2:
1617 return binary64F0x2(mce, vatom1, vatom2);
1618
sewardjf0c1c582005-02-07 23:47:38 +00001619 /* V128-bit SIMD (SSE1-esque) */
sewardj69f9e3e2004-12-30 02:05:34 +00001620
1621 case Iop_Sub32Fx4:
1622 case Iop_Mul32Fx4:
1623 case Iop_Min32Fx4:
1624 case Iop_Max32Fx4:
1625 case Iop_Div32Fx4:
1626 case Iop_CmpLT32Fx4:
1627 case Iop_CmpLE32Fx4:
1628 case Iop_CmpEQ32Fx4:
1629 case Iop_Add32Fx4:
1630 return binary32Fx4(mce, vatom1, vatom2);
1631
1632 case Iop_Sub32F0x4:
1633 case Iop_Mul32F0x4:
1634 case Iop_Min32F0x4:
1635 case Iop_Max32F0x4:
1636 case Iop_Div32F0x4:
1637 case Iop_CmpLT32F0x4:
1638 case Iop_CmpLE32F0x4:
1639 case Iop_CmpEQ32F0x4:
1640 case Iop_Add32F0x4:
1641 return binary32F0x4(mce, vatom1, vatom2);
1642
sewardjf0c1c582005-02-07 23:47:38 +00001643 /* V128-bit data-steering */
1644 case Iop_SetV128lo32:
1645 case Iop_SetV128lo64:
1646 case Iop_64HLtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001647 case Iop_InterleaveLO64x2:
1648 case Iop_InterleaveLO32x4:
1649 case Iop_InterleaveLO16x8:
1650 case Iop_InterleaveLO8x16:
1651 case Iop_InterleaveHI64x2:
1652 case Iop_InterleaveHI32x4:
1653 case Iop_InterleaveHI16x8:
1654 case Iop_InterleaveHI8x16:
1655 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1656
1657 /* Scalar floating point */
1658
sewardj3598ef92004-11-11 02:13:30 +00001659 case Iop_RoundF64:
1660 case Iop_F64toI64:
sewardj69f9e3e2004-12-30 02:05:34 +00001661 case Iop_I64toF64:
1662 /* First arg is I32 (rounding mode), second is F64 or I64
1663 (data). */
sewardj3598ef92004-11-11 02:13:30 +00001664 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1665
1666 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1667 /* Takes two F64 args. */
sewardjde8a5ae2004-11-06 14:20:54 +00001668 case Iop_F64toI32:
sewardj69f9e3e2004-12-30 02:05:34 +00001669 case Iop_F64toF32:
sewardjde8a5ae2004-11-06 14:20:54 +00001670 /* First arg is I32 (rounding mode), second is F64 (data). */
1671 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1672
1673 case Iop_F64toI16:
1674 /* First arg is I32 (rounding mode), second is F64 (data). */
1675 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1676
sewardj3598ef92004-11-11 02:13:30 +00001677 case Iop_ScaleF64:
1678 case Iop_Yl2xF64:
1679 case Iop_Yl2xp1F64:
1680 case Iop_PRemF64:
1681 case Iop_AtanF64:
1682 case Iop_AddF64:
1683 case Iop_DivF64:
1684 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001685 case Iop_MulF64:
1686 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1687
sewardj3598ef92004-11-11 02:13:30 +00001688 case Iop_CmpF64:
1689 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1690
sewardjde8a5ae2004-11-06 14:20:54 +00001691 /* non-FP after here */
1692
1693 case Iop_DivModU64to32:
1694 case Iop_DivModS64to32:
1695 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1696
sewardj3598ef92004-11-11 02:13:30 +00001697 case Iop_16HLto32:
sewardj69f9e3e2004-12-30 02:05:34 +00001698 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001699 case Iop_32HLto64:
sewardj69f9e3e2004-12-30 02:05:34 +00001700 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001701
1702 case Iop_MullS32:
1703 case Iop_MullU32: {
1704 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1705 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1706 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1707 }
1708
sewardj3598ef92004-11-11 02:13:30 +00001709 case Iop_MullS16:
1710 case Iop_MullU16: {
1711 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1712 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1713 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1714 }
1715
1716 case Iop_MullS8:
1717 case Iop_MullU8: {
1718 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1719 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1720 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1721 }
1722
sewardjde8a5ae2004-11-06 14:20:54 +00001723 case Iop_Add32:
1724# if 0
1725 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1726# endif
1727 case Iop_Sub32:
1728 case Iop_Mul32:
1729 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1730
sewardj3598ef92004-11-11 02:13:30 +00001731 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001732 case Iop_Add16:
1733 case Iop_Sub16:
1734 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1735
1736 case Iop_Sub8:
1737 case Iop_Add8:
1738 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1739
1740 case Iop_CmpLE32S: case Iop_CmpLE32U:
1741 case Iop_CmpLT32U: case Iop_CmpLT32S:
1742 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001743 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001744
sewardj3598ef92004-11-11 02:13:30 +00001745 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001746 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001747
1748 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001749 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001750
1751 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1752 /* Complain if the shift amount is undefined. Then simply
1753 shift the first arg's V bits by the real shift amount. */
1754 complainIfUndefined(mce, atom2);
1755 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1756
sewardj69f9e3e2004-12-30 02:05:34 +00001757 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjde8a5ae2004-11-06 14:20:54 +00001758 /* Same scheme as with 32-bit shifts. */
1759 complainIfUndefined(mce, atom2);
1760 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1761
sewardj3598ef92004-11-11 02:13:30 +00001762 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001763 /* Same scheme as with 32-bit shifts. */
1764 complainIfUndefined(mce, atom2);
1765 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1766
1767 case Iop_Shl64: case Iop_Shr64:
1768 /* Same scheme as with 32-bit shifts. */
1769 complainIfUndefined(mce, atom2);
1770 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1771
sewardjf0c1c582005-02-07 23:47:38 +00001772 case Iop_AndV128:
1773 uifu = mkUifUV128; difd = mkDifDV128;
1774 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001775 case Iop_And64:
1776 uifu = mkUifU64; difd = mkDifD64;
1777 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001778 case Iop_And32:
1779 uifu = mkUifU32; difd = mkDifD32;
1780 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001781 case Iop_And16:
1782 uifu = mkUifU16; difd = mkDifD16;
1783 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001784 case Iop_And8:
1785 uifu = mkUifU8; difd = mkDifD8;
1786 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1787
sewardjf0c1c582005-02-07 23:47:38 +00001788 case Iop_OrV128:
1789 uifu = mkUifUV128; difd = mkDifDV128;
1790 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj69f9e3e2004-12-30 02:05:34 +00001791 case Iop_Or64:
1792 uifu = mkUifU64; difd = mkDifD64;
1793 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001794 case Iop_Or32:
1795 uifu = mkUifU32; difd = mkDifD32;
1796 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1797 case Iop_Or16:
1798 uifu = mkUifU16; difd = mkDifD16;
1799 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1800 case Iop_Or8:
1801 uifu = mkUifU8; difd = mkDifD8;
1802 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1803
1804 do_And_Or:
1805 return
1806 assignNew(
1807 mce,
1808 and_or_ty,
1809 difd(mce, uifu(mce, vatom1, vatom2),
1810 difd(mce, improve(mce, atom1, vatom1),
1811 improve(mce, atom2, vatom2) ) ) );
1812
1813 case Iop_Xor8:
1814 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001815 case Iop_Xor16:
1816 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001817 case Iop_Xor32:
1818 return mkUifU32(mce, vatom1, vatom2);
sewardj69f9e3e2004-12-30 02:05:34 +00001819 case Iop_Xor64:
1820 return mkUifU64(mce, vatom1, vatom2);
sewardjf0c1c582005-02-07 23:47:38 +00001821 case Iop_XorV128:
1822 return mkUifUV128(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001823
1824 default:
1825 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001826 VG_(tool_panic)("memcheck:expr2vbits_Binop");
sewardjde8a5ae2004-11-06 14:20:54 +00001827 }
1828}
1829
1830
1831static
1832IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1833{
1834 IRAtom* vatom = expr2vbits( mce, atom );
sewardj69f9e3e2004-12-30 02:05:34 +00001835 tl_assert(isOriginalAtom(mce,atom));
sewardjde8a5ae2004-11-06 14:20:54 +00001836 switch (op) {
1837
sewardj69f9e3e2004-12-30 02:05:34 +00001838 case Iop_Sqrt64Fx2:
1839 return unary64Fx2(mce, vatom);
1840
1841 case Iop_Sqrt64F0x2:
1842 return unary64F0x2(mce, vatom);
1843
1844 case Iop_Sqrt32Fx4:
1845 case Iop_RSqrt32Fx4:
1846 case Iop_Recip32Fx4:
1847 return unary32Fx4(mce, vatom);
1848
1849 case Iop_Sqrt32F0x4:
1850 case Iop_RSqrt32F0x4:
1851 case Iop_Recip32F0x4:
1852 return unary32F0x4(mce, vatom);
1853
sewardjf0c1c582005-02-07 23:47:38 +00001854 case Iop_32UtoV128:
1855 case Iop_64UtoV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001856 return assignNew(mce, Ity_V128, unop(op, vatom));
1857
sewardjde8a5ae2004-11-06 14:20:54 +00001858 case Iop_F32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001859 case Iop_I32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001860 case Iop_NegF64:
1861 case Iop_SinF64:
1862 case Iop_CosF64:
1863 case Iop_TanF64:
1864 case Iop_SqrtF64:
1865 case Iop_AbsF64:
1866 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001867 return mkPCastTo(mce, Ity_I64, vatom);
1868
sewardj3598ef92004-11-11 02:13:30 +00001869 case Iop_Clz32:
1870 case Iop_Ctz32:
1871 return mkPCastTo(mce, Ity_I32, vatom);
1872
1873 case Iop_32Sto64:
1874 case Iop_32Uto64:
sewardjf0c1c582005-02-07 23:47:38 +00001875 case Iop_V128to64:
1876 case Iop_V128HIto64:
sewardj3598ef92004-11-11 02:13:30 +00001877 return assignNew(mce, Ity_I64, unop(op, vatom));
1878
sewardjde8a5ae2004-11-06 14:20:54 +00001879 case Iop_64to32:
1880 case Iop_64HIto32:
1881 case Iop_1Uto32:
1882 case Iop_8Uto32:
1883 case Iop_16Uto32:
1884 case Iop_16Sto32:
1885 case Iop_8Sto32:
1886 return assignNew(mce, Ity_I32, unop(op, vatom));
1887
1888 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001889 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001890 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001891 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001892 return assignNew(mce, Ity_I16, unop(op, vatom));
1893
1894 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001895 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001896 case Iop_32to8:
1897 return assignNew(mce, Ity_I8, unop(op, vatom));
1898
1899 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001900 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001901
sewardj3598ef92004-11-11 02:13:30 +00001902 case Iop_ReinterpF64asI64:
1903 case Iop_ReinterpI64asF64:
sewardj69f9e3e2004-12-30 02:05:34 +00001904 case Iop_ReinterpI32asF32:
sewardjf0c1c582005-02-07 23:47:38 +00001905 case Iop_NotV128:
sewardj69f9e3e2004-12-30 02:05:34 +00001906 case Iop_Not64:
sewardjde8a5ae2004-11-06 14:20:54 +00001907 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001908 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001909 case Iop_Not8:
1910 case Iop_Not1:
1911 return vatom;
sewardj69f9e3e2004-12-30 02:05:34 +00001912
sewardjde8a5ae2004-11-06 14:20:54 +00001913 default:
1914 ppIROp(op);
sewardj69f9e3e2004-12-30 02:05:34 +00001915 VG_(tool_panic)("memcheck:expr2vbits_Unop");
sewardjde8a5ae2004-11-06 14:20:54 +00001916 }
1917}
1918
1919
sewardj69f9e3e2004-12-30 02:05:34 +00001920/* Worker function; do not call directly. */
sewardjde8a5ae2004-11-06 14:20:54 +00001921static
sewardj69f9e3e2004-12-30 02:05:34 +00001922IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001923{
1924 void* helper;
sewardjde8c9872005-03-25 13:48:55 +00001925 HChar* hname;
sewardjde8a5ae2004-11-06 14:20:54 +00001926 IRDirty* di;
1927 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00001928 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001929
sewardj69f9e3e2004-12-30 02:05:34 +00001930 tl_assert(isOriginalAtom(mce,addr));
sewardjde8a5ae2004-11-06 14:20:54 +00001931
1932 /* First, emit a definedness test for the address. This also sets
1933 the address (shadow) to 'defined' following the test. */
1934 complainIfUndefined( mce, addr );
1935
1936 /* Now cook up a call to the relevant helper function, to read the
1937 data V bits from shadow memory. */
1938 ty = shadowType(ty);
1939 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001940 case Ity_I64: helper = &MC_(helperc_LOADV8);
1941 hname = "MC_(helperc_LOADV8)";
1942 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001943 case Ity_I32: helper = &MC_(helperc_LOADV4);
1944 hname = "MC_(helperc_LOADV4)";
1945 break;
1946 case Ity_I16: helper = &MC_(helperc_LOADV2);
1947 hname = "MC_(helperc_LOADV2)";
1948 break;
1949 case Ity_I8: helper = &MC_(helperc_LOADV1);
1950 hname = "MC_(helperc_LOADV1)";
1951 break;
1952 default: ppIRType(ty);
sewardj69f9e3e2004-12-30 02:05:34 +00001953 VG_(tool_panic)("memcheck:do_shadow_LDle");
sewardjde8a5ae2004-11-06 14:20:54 +00001954 }
1955
sewardj3598ef92004-11-11 02:13:30 +00001956 /* Generate the actual address into addrAct. */
1957 if (bias == 0) {
1958 addrAct = addr;
1959 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00001960 IROp mkAdd;
1961 IRAtom* eBias;
sewardj3598ef92004-11-11 02:13:30 +00001962 IRType tyAddr = mce->hWordTy;
sewardj69f9e3e2004-12-30 02:05:34 +00001963 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
1964 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1965 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj3598ef92004-11-11 02:13:30 +00001966 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1967 }
1968
sewardjde8a5ae2004-11-06 14:20:54 +00001969 /* We need to have a place to park the V bits we're just about to
1970 read. */
1971 datavbits = newIRTemp(mce->bb->tyenv, ty);
1972 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00001973 1/*regparms*/, hname, helper,
1974 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00001975 setHelperAnns( mce, di );
1976 stmt( mce->bb, IRStmt_Dirty(di) );
1977
1978 return mkexpr(datavbits);
1979}
1980
1981
1982static
sewardj69f9e3e2004-12-30 02:05:34 +00001983IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
1984{
1985 IRAtom *v64hi, *v64lo;
1986 switch (shadowType(ty)) {
1987 case Ity_I8:
1988 case Ity_I16:
1989 case Ity_I32:
1990 case Ity_I64:
1991 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
1992 case Ity_V128:
1993 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
1994 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
1995 return assignNew( mce,
1996 Ity_V128,
sewardjf0c1c582005-02-07 23:47:38 +00001997 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj69f9e3e2004-12-30 02:05:34 +00001998 default:
1999 VG_(tool_panic)("expr2vbits_LDle");
2000 }
2001}
2002
2003
2004static
sewardjde8a5ae2004-11-06 14:20:54 +00002005IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00002006 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00002007{
2008 IRAtom *vbitsC, *vbits0, *vbitsX;
2009 IRType ty;
2010 /* Given Mux0X(cond,expr0,exprX), generate
2011 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2012 That is, steer the V bits like the originals, but trash the
2013 result if the steering value is undefined. This gives
2014 lazy propagation. */
sewardj69f9e3e2004-12-30 02:05:34 +00002015 tl_assert(isOriginalAtom(mce, cond));
2016 tl_assert(isOriginalAtom(mce, expr0));
2017 tl_assert(isOriginalAtom(mce, exprX));
sewardjde8a5ae2004-11-06 14:20:54 +00002018
2019 vbitsC = expr2vbits(mce, cond);
2020 vbits0 = expr2vbits(mce, expr0);
2021 vbitsX = expr2vbits(mce, exprX);
2022 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2023
2024 return
2025 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2026 mkPCastTo(mce, ty, vbitsC) );
2027}
2028
2029/* --------- This is the main expression-handling function. --------- */
2030
2031static
2032IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2033{
2034 switch (e->tag) {
2035
2036 case Iex_Get:
2037 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2038
2039 case Iex_GetI:
2040 return shadow_GETI( mce, e->Iex.GetI.descr,
2041 e->Iex.GetI.ix, e->Iex.GetI.bias );
2042
2043 case Iex_Tmp:
2044 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
2045
2046 case Iex_Const:
2047 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2048
2049 case Iex_Binop:
2050 return expr2vbits_Binop(
2051 mce,
2052 e->Iex.Binop.op,
2053 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2054 );
2055
2056 case Iex_Unop:
2057 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2058
2059 case Iex_LDle:
sewardj3598ef92004-11-11 02:13:30 +00002060 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
2061 e->Iex.LDle.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00002062
2063 case Iex_CCall:
2064 return mkLazyN( mce, e->Iex.CCall.args,
2065 e->Iex.CCall.retty,
2066 e->Iex.CCall.cee );
2067
2068 case Iex_Mux0X:
2069 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2070 e->Iex.Mux0X.exprX);
2071
2072 default:
2073 VG_(printf)("\n");
2074 ppIRExpr(e);
2075 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002076 VG_(tool_panic)("memcheck: expr2vbits");
sewardjde8a5ae2004-11-06 14:20:54 +00002077 }
2078}
2079
cerionaee45242005-03-17 14:03:36 +00002080#if 0 /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002081/*------------------------------------------------------------*/
2082/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
2083/*------------------------------------------------------------*/
2084
2085/* Widen a value to the host word size. */
2086
2087static
2088IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
2089{
sewardj69f9e3e2004-12-30 02:05:34 +00002090 IRType ty, tyH;
sewardjde8a5ae2004-11-06 14:20:54 +00002091
sewardj8fc93742004-11-22 11:29:33 +00002092 /* vatom is vbits-value and as such can only have a shadow type. */
sewardj69f9e3e2004-12-30 02:05:34 +00002093 tl_assert(isShadowAtom(mce,vatom));
2094
2095 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2096 tyH = mce->hWordTy;
sewardj8fc93742004-11-22 11:29:33 +00002097
sewardjde8a5ae2004-11-06 14:20:54 +00002098 if (tyH == Ity_I32) {
2099 switch (ty) {
2100 case Ity_I32: return vatom;
2101 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2102 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2103 default: goto unhandled;
2104 }
2105 } else {
2106 goto unhandled;
2107 }
2108 unhandled:
2109 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002110 VG_(tool_panic)("zwidenToHostWord");
sewardjde8a5ae2004-11-06 14:20:54 +00002111}
2112
2113
sewardj3598ef92004-11-11 02:13:30 +00002114/* Generate a shadow store. addr is always the original address atom.
2115 You can pass in either originals or V-bits for the data atom, but
2116 obviously not both. */
2117
sewardjde8a5ae2004-11-06 14:20:54 +00002118static
sewardj3598ef92004-11-11 02:13:30 +00002119void do_shadow_STle ( MCEnv* mce,
2120 IRAtom* addr, UInt bias,
2121 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00002122{
sewardj69f9e3e2004-12-30 02:05:34 +00002123 IROp mkAdd;
2124 IRType ty, tyAddr;
2125 IRDirty *di, *diLo64, *diHi64;
2126 IRAtom *addrAct, *addrLo64, *addrHi64;
2127 IRAtom *vdataLo64, *vdataHi64;
2128 IRAtom *eBias, *eBias0, *eBias8;
sewardjde8a5ae2004-11-06 14:20:54 +00002129 void* helper = NULL;
2130 Char* hname = NULL;
sewardj69f9e3e2004-12-30 02:05:34 +00002131
2132 tyAddr = mce->hWordTy;
2133 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2134 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2135
2136 di = diLo64 = diHi64 = NULL;
2137 eBias = eBias0 = eBias8 = NULL;
2138 addrAct = addrLo64 = addrHi64 = NULL;
2139 vdataLo64 = vdataHi64 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +00002140
sewardj3598ef92004-11-11 02:13:30 +00002141 if (data) {
sewardj69f9e3e2004-12-30 02:05:34 +00002142 tl_assert(!vdata);
2143 tl_assert(isOriginalAtom(mce, data));
2144 tl_assert(bias == 0);
sewardj3598ef92004-11-11 02:13:30 +00002145 vdata = expr2vbits( mce, data );
2146 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002147 tl_assert(vdata);
sewardj3598ef92004-11-11 02:13:30 +00002148 }
sewardjde8a5ae2004-11-06 14:20:54 +00002149
sewardj69f9e3e2004-12-30 02:05:34 +00002150 tl_assert(isOriginalAtom(mce,addr));
2151 tl_assert(isShadowAtom(mce,vdata));
sewardj3598ef92004-11-11 02:13:30 +00002152
2153 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00002154
2155 /* First, emit a definedness test for the address. This also sets
2156 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00002157 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00002158
sewardj69f9e3e2004-12-30 02:05:34 +00002159 /* Now decide which helper function to call to write the data V
2160 bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00002161 switch (ty) {
sewardj69f9e3e2004-12-30 02:05:34 +00002162 case Ity_V128: /* we'll use the helper twice */
sewardj3598ef92004-11-11 02:13:30 +00002163 case Ity_I64: helper = &MC_(helperc_STOREV8);
2164 hname = "MC_(helperc_STOREV8)";
2165 break;
sewardjde8a5ae2004-11-06 14:20:54 +00002166 case Ity_I32: helper = &MC_(helperc_STOREV4);
2167 hname = "MC_(helperc_STOREV4)";
2168 break;
2169 case Ity_I16: helper = &MC_(helperc_STOREV2);
2170 hname = "MC_(helperc_STOREV2)";
2171 break;
2172 case Ity_I8: helper = &MC_(helperc_STOREV1);
2173 hname = "MC_(helperc_STOREV1)";
2174 break;
sewardj69f9e3e2004-12-30 02:05:34 +00002175 default: VG_(tool_panic)("memcheck:do_shadow_STle");
sewardjde8a5ae2004-11-06 14:20:54 +00002176 }
2177
sewardj69f9e3e2004-12-30 02:05:34 +00002178 if (ty == Ity_V128) {
2179
sewardjf0c1c582005-02-07 23:47:38 +00002180 /* V128-bit case */
sewardj69f9e3e2004-12-30 02:05:34 +00002181 /* See comment in next clause re 64-bit regparms */
2182 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2183 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
sewardjf0c1c582005-02-07 23:47:38 +00002184 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002185 diLo64 = unsafeIRDirty_0_N(
2186 1/*regparms*/, hname, helper,
2187 mkIRExprVec_2( addrLo64, vdataLo64 ));
2188
2189 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2190 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
sewardjf0c1c582005-02-07 23:47:38 +00002191 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj69f9e3e2004-12-30 02:05:34 +00002192 diHi64 = unsafeIRDirty_0_N(
2193 1/*regparms*/, hname, helper,
2194 mkIRExprVec_2( addrHi64, vdataHi64 ));
2195
2196 setHelperAnns( mce, diLo64 );
2197 setHelperAnns( mce, diHi64 );
2198 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2199 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2200
sewardj3598ef92004-11-11 02:13:30 +00002201 } else {
sewardj69f9e3e2004-12-30 02:05:34 +00002202
2203 /* 8/16/32/64-bit cases */
2204 /* Generate the actual address into addrAct. */
2205 if (bias == 0) {
2206 addrAct = addr;
2207 } else {
2208 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2209 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2210 }
2211
2212 if (ty == Ity_I64) {
2213 /* We can't do this with regparm 2 on 32-bit platforms, since
2214 the back ends aren't clever enough to handle 64-bit
2215 regparm args. Therefore be different. */
2216 di = unsafeIRDirty_0_N(
2217 1/*regparms*/, hname, helper,
2218 mkIRExprVec_2( addrAct, vdata ));
2219 } else {
2220 di = unsafeIRDirty_0_N(
2221 2/*regparms*/, hname, helper,
2222 mkIRExprVec_2( addrAct,
2223 zwidenToHostWord( mce, vdata )));
2224 }
2225 setHelperAnns( mce, di );
2226 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj3598ef92004-11-11 02:13:30 +00002227 }
2228
sewardjde8a5ae2004-11-06 14:20:54 +00002229}
2230
2231
sewardj3598ef92004-11-11 02:13:30 +00002232/* Do lazy pessimistic propagation through a dirty helper call, by
2233 looking at the annotations on it. This is the most complex part of
2234 Memcheck. */
2235
2236static IRType szToITy ( Int n )
2237{
2238 switch (n) {
2239 case 1: return Ity_I8;
2240 case 2: return Ity_I16;
2241 case 4: return Ity_I32;
2242 case 8: return Ity_I64;
sewardj69f9e3e2004-12-30 02:05:34 +00002243 default: VG_(tool_panic)("szToITy(memcheck)");
sewardj3598ef92004-11-11 02:13:30 +00002244 }
2245}
2246
2247static
2248void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2249{
sewardj69f9e3e2004-12-30 02:05:34 +00002250 Int i, n, offset, toDo, gSz, gOff;
2251 IRAtom *src, *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00002252 IRType tyAddr, tySrc, tyDst;
2253 IRTemp dst;
2254
2255 /* First check the guard. */
2256 complainIfUndefined(mce, d->guard);
2257
2258 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00002259 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00002260
2261 /* Inputs: unmasked args */
2262 for (i = 0; d->args[i]; i++) {
2263 if (d->cee->mcx_mask & (1<<i)) {
2264 /* ignore this arg */
2265 } else {
2266 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2267 curr = mkUifU32(mce, here, curr);
2268 }
2269 }
2270
2271 /* Inputs: guest state that we read. */
2272 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002273 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002274 if (d->fxState[i].fx == Ifx_Write)
2275 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002276
2277 /* Ignore any sections marked as 'always defined'. */
2278 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
2279 if (0)
2280 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2281 d->fxState[i].offset, d->fxState[i].size );
2282 continue;
2283 }
2284
sewardj3598ef92004-11-11 02:13:30 +00002285 /* This state element is read or modified. So we need to
sewardj69f9e3e2004-12-30 02:05:34 +00002286 consider it. If larger than 8 bytes, deal with it in 8-byte
2287 chunks. */
2288 gSz = d->fxState[i].size;
2289 gOff = d->fxState[i].offset;
2290 tl_assert(gSz > 0);
2291 while (True) {
2292 if (gSz == 0) break;
2293 n = gSz <= 8 ? gSz : 8;
2294 /* update 'curr' with UifU of the state slice
2295 gOff .. gOff+n-1 */
2296 tySrc = szToITy( n );
2297 src = assignNew( mce, tySrc,
2298 shadow_GET(mce, gOff, tySrc ) );
2299 here = mkPCastTo( mce, Ity_I32, src );
2300 curr = mkUifU32(mce, here, curr);
2301 gSz -= n;
2302 gOff += n;
2303 }
2304
sewardj3598ef92004-11-11 02:13:30 +00002305 }
2306
2307 /* Inputs: memory. First set up some info needed regardless of
2308 whether we're doing reads or writes. */
2309 tyAddr = Ity_INVALID;
2310
2311 if (d->mFx != Ifx_None) {
2312 /* Because we may do multiple shadow loads/stores from the same
2313 base address, it's best to do a single test of its
2314 definedness right now. Post-instrumentation optimisation
2315 should remove all but this test. */
sewardj69f9e3e2004-12-30 02:05:34 +00002316 tl_assert(d->mAddr);
sewardj3598ef92004-11-11 02:13:30 +00002317 complainIfUndefined(mce, d->mAddr);
2318
2319 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
sewardj69f9e3e2004-12-30 02:05:34 +00002320 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2321 tl_assert(tyAddr == mce->hWordTy); /* not really right */
sewardj3598ef92004-11-11 02:13:30 +00002322 }
2323
2324 /* Deal with memory inputs (reads or modifies) */
2325 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2326 offset = 0;
2327 toDo = d->mSize;
2328 /* chew off 32-bit chunks */
2329 while (toDo >= 4) {
2330 here = mkPCastTo(
2331 mce, Ity_I32,
2332 expr2vbits_LDle ( mce, Ity_I32,
2333 d->mAddr, d->mSize - toDo )
2334 );
2335 curr = mkUifU32(mce, here, curr);
2336 toDo -= 4;
2337 }
2338 /* chew off 16-bit chunks */
2339 while (toDo >= 2) {
2340 here = mkPCastTo(
2341 mce, Ity_I32,
2342 expr2vbits_LDle ( mce, Ity_I16,
2343 d->mAddr, d->mSize - toDo )
2344 );
2345 curr = mkUifU32(mce, here, curr);
2346 toDo -= 2;
2347 }
sewardj69f9e3e2004-12-30 02:05:34 +00002348 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002349 }
2350
2351 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2352 all the inputs to the helper. Now we need to re-distribute the
2353 results to all destinations. */
2354
2355 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00002356 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00002357 dst = findShadowTmp(mce, d->tmp);
2358 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2359 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2360 }
2361
2362 /* Outputs: guest state that we write or modify. */
2363 for (i = 0; i < d->nFxState; i++) {
sewardj69f9e3e2004-12-30 02:05:34 +00002364 tl_assert(d->fxState[i].fx != Ifx_None);
sewardj3598ef92004-11-11 02:13:30 +00002365 if (d->fxState[i].fx == Ifx_Read)
2366 continue;
sewardj69f9e3e2004-12-30 02:05:34 +00002367 /* Ignore any sections marked as 'always defined'. */
2368 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2369 continue;
2370 /* This state element is written or modified. So we need to
2371 consider it. If larger than 8 bytes, deal with it in 8-byte
2372 chunks. */
2373 gSz = d->fxState[i].size;
2374 gOff = d->fxState[i].offset;
2375 tl_assert(gSz > 0);
2376 while (True) {
2377 if (gSz == 0) break;
2378 n = gSz <= 8 ? gSz : 8;
2379 /* Write suitably-casted 'curr' to the state slice
2380 gOff .. gOff+n-1 */
2381 tyDst = szToITy( n );
2382 do_shadow_PUT( mce, gOff,
2383 NULL, /* original atom */
2384 mkPCastTo( mce, tyDst, curr ) );
2385 gSz -= n;
2386 gOff += n;
2387 }
sewardj3598ef92004-11-11 02:13:30 +00002388 }
2389
2390 /* Outputs: memory that we write or modify. */
2391 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2392 offset = 0;
2393 toDo = d->mSize;
2394 /* chew off 32-bit chunks */
2395 while (toDo >= 4) {
2396 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2397 NULL, /* original data */
2398 mkPCastTo( mce, Ity_I32, curr ) );
2399 toDo -= 4;
2400 }
2401 /* chew off 16-bit chunks */
2402 while (toDo >= 2) {
2403 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2404 NULL, /* original data */
2405 mkPCastTo( mce, Ity_I16, curr ) );
2406 toDo -= 2;
2407 }
sewardj69f9e3e2004-12-30 02:05:34 +00002408 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj3598ef92004-11-11 02:13:30 +00002409 }
2410
2411}
cerionaee45242005-03-17 14:03:36 +00002412#endif /* UNUSED */
sewardj3598ef92004-11-11 02:13:30 +00002413
2414
sewardjde8a5ae2004-11-06 14:20:54 +00002415/*------------------------------------------------------------*/
2416/*--- Memcheck main ---*/
2417/*------------------------------------------------------------*/
2418
sewardj3598ef92004-11-11 02:13:30 +00002419#if 0 /* UNUSED */
2420static Bool isBogusAtom ( IRAtom* at )
2421{
2422 ULong n = 0;
2423 IRConst* con;
sewardj496a58d2005-03-20 18:44:44 +00002424 tl_assert(isIRAtom(at));
sewardj3598ef92004-11-11 02:13:30 +00002425 if (at->tag == Iex_Tmp)
2426 return False;
sewardj69f9e3e2004-12-30 02:05:34 +00002427 tl_assert(at->tag == Iex_Const);
sewardj3598ef92004-11-11 02:13:30 +00002428 con = at->Iex.Const.con;
2429 switch (con->tag) {
2430 case Ico_U8: n = (ULong)con->Ico.U8; break;
2431 case Ico_U16: n = (ULong)con->Ico.U16; break;
2432 case Ico_U32: n = (ULong)con->Ico.U32; break;
2433 case Ico_U64: n = (ULong)con->Ico.U64; break;
sewardj69f9e3e2004-12-30 02:05:34 +00002434 default: ppIRExpr(at); tl_assert(0);
sewardj3598ef92004-11-11 02:13:30 +00002435 }
2436 /* VG_(printf)("%llx\n", n); */
2437 return (n == 0xFEFEFEFF
2438 || n == 0x80808080
2439 || n == 0x1010101
2440 || n == 1010100);
2441}
2442
2443static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2444{
2445 Int i;
2446 IRExpr* e;
2447 switch (st->tag) {
2448 case Ist_Tmp:
2449 e = st->Ist.Tmp.data;
2450 switch (e->tag) {
2451 case Iex_Get:
2452 case Iex_Tmp:
2453 return False;
2454 case Iex_Unop:
2455 return isBogusAtom(e->Iex.Unop.arg);
2456 case Iex_Binop:
2457 return isBogusAtom(e->Iex.Binop.arg1)
2458 || isBogusAtom(e->Iex.Binop.arg2);
2459 case Iex_Mux0X:
2460 return isBogusAtom(e->Iex.Mux0X.cond)
2461 || isBogusAtom(e->Iex.Mux0X.expr0)
2462 || isBogusAtom(e->Iex.Mux0X.exprX);
2463 case Iex_LDle:
2464 return isBogusAtom(e->Iex.LDle.addr);
2465 case Iex_CCall:
2466 for (i = 0; e->Iex.CCall.args[i]; i++)
2467 if (isBogusAtom(e->Iex.CCall.args[i]))
2468 return True;
2469 return False;
2470 default:
2471 goto unhandled;
2472 }
2473 case Ist_Put:
2474 return isBogusAtom(st->Ist.Put.data);
2475 case Ist_STle:
2476 return isBogusAtom(st->Ist.STle.addr)
2477 || isBogusAtom(st->Ist.STle.data);
2478 case Ist_Exit:
sewardj69f9e3e2004-12-30 02:05:34 +00002479 return isBogusAtom(st->Ist.Exit.cond);
sewardj3598ef92004-11-11 02:13:30 +00002480 default:
2481 unhandled:
2482 ppIRStmt(st);
sewardj69f9e3e2004-12-30 02:05:34 +00002483 VG_(tool_panic)("hasBogusLiterals");
sewardj3598ef92004-11-11 02:13:30 +00002484 }
2485}
2486#endif /* UNUSED */
2487
2488
cerionaee45242005-03-17 14:03:36 +00002489#if 0 /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002490IRBB* mc_instrument ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
2491{
sewardj3598ef92004-11-11 02:13:30 +00002492 Bool verboze = False; //True;
2493
2494 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00002495
2496 Int i, j, first_stmt;
2497 IRStmt* st;
2498 MCEnv mce;
2499
2500 /* Set up BB */
2501 IRBB* bb = emptyIRBB();
2502 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
2503 bb->next = dopyIRExpr(bb_in->next);
2504 bb->jumpkind = bb_in->jumpkind;
2505
2506 /* Set up the running environment. Only .bb is modified as we go
2507 along. */
2508 mce.bb = bb;
2509 mce.layout = layout;
2510 mce.n_originalTmps = bb->tyenv->types_used;
2511 mce.hWordTy = hWordTy;
2512 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2513 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00002514 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00002515
2516 /* Iterate over the stmts. */
2517
2518 for (i = 0; i < bb_in->stmts_used; i++) {
2519 st = bb_in->stmts[i];
2520 if (!st) continue;
2521
sewardj69f9e3e2004-12-30 02:05:34 +00002522 tl_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00002523
2524 /*
2525 if (!hasBogusLiterals) {
2526 hasBogusLiterals = checkForBogusLiterals(st);
2527 if (hasBogusLiterals) {
2528 VG_(printf)("bogus: ");
2529 ppIRStmt(st);
2530 VG_(printf)("\n");
2531 }
2532 }
2533 */
sewardjde8a5ae2004-11-06 14:20:54 +00002534 first_stmt = bb->stmts_used;
2535
2536 if (verboze) {
2537 ppIRStmt(st);
2538 VG_(printf)("\n\n");
2539 }
2540
2541 switch (st->tag) {
2542
2543 case Ist_Tmp:
2544 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
2545 expr2vbits( &mce, st->Ist.Tmp.data) );
2546 break;
2547
2548 case Ist_Put:
2549 do_shadow_PUT( &mce,
2550 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00002551 st->Ist.Put.data,
2552 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002553 break;
2554
2555 case Ist_PutI:
2556 do_shadow_PUTI( &mce,
2557 st->Ist.PutI.descr,
2558 st->Ist.PutI.ix,
2559 st->Ist.PutI.bias,
2560 st->Ist.PutI.data );
2561 break;
2562
2563 case Ist_STle:
sewardj3598ef92004-11-11 02:13:30 +00002564 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
2565 st->Ist.STle.data,
2566 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00002567 break;
2568
2569 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00002570 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00002571 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00002572 break;
2573
2574 case Ist_Dirty:
2575 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00002576 break;
2577
2578 default:
2579 VG_(printf)("\n");
2580 ppIRStmt(st);
2581 VG_(printf)("\n");
sewardj69f9e3e2004-12-30 02:05:34 +00002582 VG_(tool_panic)("memcheck: unhandled IRStmt");
sewardjde8a5ae2004-11-06 14:20:54 +00002583
2584 } /* switch (st->tag) */
2585
2586 if (verboze) {
2587 for (j = first_stmt; j < bb->stmts_used; j++) {
2588 VG_(printf)(" ");
2589 ppIRStmt(bb->stmts[j]);
2590 VG_(printf)("\n");
2591 }
2592 VG_(printf)("\n");
2593 }
2594
2595 addStmtToIRBB(bb, st);
2596
2597 }
2598
2599 /* Now we need to complain if the jump target is undefined. */
2600 first_stmt = bb->stmts_used;
2601
2602 if (verboze) {
2603 VG_(printf)("bb->next = ");
2604 ppIRExpr(bb->next);
2605 VG_(printf)("\n\n");
2606 }
2607
2608 complainIfUndefined( &mce, bb->next );
2609
2610 if (verboze) {
2611 for (j = first_stmt; j < bb->stmts_used; j++) {
2612 VG_(printf)(" ");
2613 ppIRStmt(bb->stmts[j]);
2614 VG_(printf)("\n");
2615 }
2616 VG_(printf)("\n");
2617 }
2618
2619 return bb;
2620}
cerionaee45242005-03-17 14:03:36 +00002621#endif /* UNUSED */
sewardjde8a5ae2004-11-06 14:20:54 +00002622
2623/*--------------------------------------------------------------------*/
2624/*--- end mc_translate.c ---*/
2625/*--------------------------------------------------------------------*/