blob: 5243a10553658ae9cbc341587fbd7da2377a6ae0 [file] [log] [blame]
nethercotebb1c9912004-01-04 16:43:23 +00001
njn25e49d8e72002-09-23 09:36:25 +00002/*--------------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00003/*--- Instrument IR to perform memory checking operations. ---*/
njn25cac76cb2002-09-23 11:21:57 +00004/*--- mc_translate.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00005/*--------------------------------------------------------------------*/
njnc9539842002-10-02 13:26:35 +00006
njn25e49d8e72002-09-23 09:36:25 +00007/*
nethercote137bc552003-11-14 17:47:54 +00008 This file is part of MemCheck, a heavyweight Valgrind tool for
njnc9539842002-10-02 13:26:35 +00009 detecting memory errors.
njn25e49d8e72002-09-23 09:36:25 +000010
sewardj9ebd6e02007-01-08 06:01:59 +000011 Copyright (C) 2000-2007 Julian Seward
njn25e49d8e72002-09-23 09:36:25 +000012 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
31
njnc7561b92005-06-19 01:24:32 +000032#include "pub_tool_basics.h"
njn1d0825f2006-03-27 11:37:07 +000033#include "pub_tool_hashtable.h" // For mc_include.h
njn132bfcc2005-06-04 19:16:06 +000034#include "pub_tool_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000035#include "pub_tool_libcprint.h"
njnc7561b92005-06-19 01:24:32 +000036#include "pub_tool_tooliface.h"
sewardj53ee1fc2005-12-23 02:29:58 +000037#include "pub_tool_machine.h" // VG_(fnptr_to_fnentry)
njnc7561b92005-06-19 01:24:32 +000038#include "mc_include.h"
njn25e49d8e72002-09-23 09:36:25 +000039
sewardj81651dc2007-08-28 06:05:20 +000040#include "pub_tool_xarray.h"
41#include "pub_tool_mallocfree.h"
42#include "pub_tool_libcbase.h"
njn25e49d8e72002-09-23 09:36:25 +000043
sewardj992dff92005-10-07 11:08:55 +000044/* This file implements the Memcheck instrumentation, and in
45 particular contains the core of its undefined value detection
46 machinery. For a comprehensive background of the terminology,
47 algorithms and rationale used herein, read:
48
49 Using Valgrind to detect undefined value errors with
50 bit-precision
51
52 Julian Seward and Nicholas Nethercote
53
54 2005 USENIX Annual Technical Conference (General Track),
55 Anaheim, CA, USA, April 10-15, 2005.
njn6665ea22007-05-24 23:14:41 +000056
57 ----
58
59 Here is as good a place as any to record exactly when V bits are and
60 should be checked, why, and what function is responsible.
61
62
63 Memcheck complains when an undefined value is used:
64
65 1. In the condition of a conditional branch. Because it could cause
66 incorrect control flow, and thus cause incorrect externally-visible
67 behaviour. [mc_translate.c:complainIfUndefined]
68
69 2. As an argument to a system call, or as the value that specifies
70 the system call number. Because it could cause an incorrect
71 externally-visible side effect. [mc_translate.c:mc_pre_reg_read]
72
73 3. As the address in a load or store. Because it could cause an
74 incorrect value to be used later, which could cause externally-visible
75 behaviour (eg. via incorrect control flow or an incorrect system call
76 argument) [complainIfUndefined]
77
78 4. As the target address of a branch. Because it could cause incorrect
79 control flow. [complainIfUndefined]
80
81 5. As an argument to setenv, unsetenv, or putenv. Because it could put
82 an incorrect value into the external environment.
83 [mc_replace_strmem.c:VG_WRAP_FUNCTION_ZU(*, *env)]
84
85 6. As the index in a GETI or PUTI operation. I'm not sure why... (njn).
86 [complainIfUndefined]
87
88 7. As an argument to the VALGRIND_CHECK_MEM_IS_DEFINED and
89 VALGRIND_CHECK_VALUE_IS_DEFINED client requests. Because the user
90 requested it. [in memcheck.h]
91
92
93 Memcheck also complains, but should not, when an undefined value is used:
94
95 8. As the shift value in certain SIMD shift operations (but not in the
96 standard integer shift operations). This inconsistency is due to
97 historical reasons.) [complainIfUndefined]
98
99
100 Memcheck does not complain, but should, when an undefined value is used:
101
102 9. As an input to a client request. Because the client request may
103 affect the visible behaviour -- see bug #144362 for an example
104 involving the malloc replacements in vg_replace_malloc.c and
105 VALGRIND_NON_SIMD_CALL* requests, where an uninitialised argument
106 isn't identified. That bug report also has some info on how to solve
107 the problem. [valgrind.h:VALGRIND_DO_CLIENT_REQUEST]
108
109
110 In practice, 1 and 2 account for the vast majority of cases.
sewardj992dff92005-10-07 11:08:55 +0000111*/
112
sewardj95448072004-11-22 20:19:51 +0000113/*------------------------------------------------------------*/
114/*--- Forward decls ---*/
115/*------------------------------------------------------------*/
116
117struct _MCEnv;
118
119static IRType shadowType ( IRType ty );
120static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
121
122
123/*------------------------------------------------------------*/
124/*--- Memcheck running state, and tmp management. ---*/
125/*------------------------------------------------------------*/
126
127/* Carries around state during memcheck instrumentation. */
128typedef
129 struct _MCEnv {
sewardj0b9d74a2006-12-24 02:24:11 +0000130 /* MODIFIED: the superblock being constructed. IRStmts are
131 added. */
132 IRSB* bb;
sewardj95448072004-11-22 20:19:51 +0000133
134 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
135 original temps to their current their current shadow temp.
136 Initially all entries are IRTemp_INVALID. Entries are added
137 lazily since many original temps are not used due to
138 optimisation prior to instrumentation. Note that floating
139 point original tmps are shadowed by integer tmps of the same
140 size, and Bit-typed original tmps are shadowed by the type
141 Ity_I8. See comment below. */
142 IRTemp* tmpMap;
143 Int n_originalTmps; /* for range checking */
144
sewardjd5204dc2004-12-31 01:16:11 +0000145 /* MODIFIED: indicates whether "bogus" literals have so far been
146 found. Starts off False, and may change to True. */
147 Bool bogusLiterals;
148
sewardj95448072004-11-22 20:19:51 +0000149 /* READONLY: the guest layout. This indicates which parts of
150 the guest state should be regarded as 'always defined'. */
151 VexGuestLayout* layout;
sewardj634ba772006-10-15 12:47:37 +0000152
sewardj95448072004-11-22 20:19:51 +0000153 /* READONLY: the host word type. Needed for constructing
154 arguments of type 'HWord' to be passed to helper functions.
155 Ity_I32 or Ity_I64 only. */
156 IRType hWordTy;
157 }
158 MCEnv;
159
160/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
161 demand), as they are encountered. This is for two reasons.
162
163 (1) (less important reason): Many original tmps are unused due to
164 initial IR optimisation, and we do not want to spaces in tables
165 tracking them.
166
167 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
168 table indexed [0 .. n_types-1], which gives the current shadow for
169 each original tmp, or INVALID_IRTEMP if none is so far assigned.
170 It is necessary to support making multiple assignments to a shadow
171 -- specifically, after testing a shadow for definedness, it needs
172 to be made defined. But IR's SSA property disallows this.
173
174 (2) (more important reason): Therefore, when a shadow needs to get
175 a new value, a new temporary is created, the value is assigned to
176 that, and the tmpMap is updated to reflect the new binding.
177
178 A corollary is that if the tmpMap maps a given tmp to
sewardjf1962d32006-10-19 13:22:16 +0000179 IRTemp_INVALID and we are hoping to read that shadow tmp, it means
sewardj95448072004-11-22 20:19:51 +0000180 there's a read-before-write error in the original tmps. The IR
181 sanity checker should catch all such anomalies, however.
njn25e49d8e72002-09-23 09:36:25 +0000182*/
sewardj95448072004-11-22 20:19:51 +0000183
184/* Find the tmp currently shadowing the given original tmp. If none
185 so far exists, allocate one. */
186static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
njn25e49d8e72002-09-23 09:36:25 +0000187{
sewardj95448072004-11-22 20:19:51 +0000188 tl_assert(orig < mce->n_originalTmps);
189 if (mce->tmpMap[orig] == IRTemp_INVALID) {
190 mce->tmpMap[orig]
191 = newIRTemp(mce->bb->tyenv,
192 shadowType(mce->bb->tyenv->types[orig]));
njn25e49d8e72002-09-23 09:36:25 +0000193 }
sewardj95448072004-11-22 20:19:51 +0000194 return mce->tmpMap[orig];
njn25e49d8e72002-09-23 09:36:25 +0000195}
196
sewardj95448072004-11-22 20:19:51 +0000197/* Allocate a new shadow for the given original tmp. This means any
198 previous shadow is abandoned. This is needed because it is
199 necessary to give a new value to a shadow once it has been tested
200 for undefinedness, but unfortunately IR's SSA property disallows
201 this. Instead we must abandon the old shadow, allocate a new one
202 and use that instead. */
203static void newShadowTmp ( MCEnv* mce, IRTemp orig )
njn25e49d8e72002-09-23 09:36:25 +0000204{
sewardj95448072004-11-22 20:19:51 +0000205 tl_assert(orig < mce->n_originalTmps);
206 mce->tmpMap[orig]
207 = newIRTemp(mce->bb->tyenv,
208 shadowType(mce->bb->tyenv->types[orig]));
209}
210
211
212/*------------------------------------------------------------*/
213/*--- IRAtoms -- a subset of IRExprs ---*/
214/*------------------------------------------------------------*/
215
216/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj710d6c22005-03-20 18:55:15 +0000217 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardj95448072004-11-22 20:19:51 +0000218 input, most of this code deals in atoms. Usefully, a value atom
219 always has a V-value which is also an atom: constants are shadowed
220 by constants, and temps are shadowed by the corresponding shadow
221 temporary. */
222
223typedef IRExpr IRAtom;
224
225/* (used for sanity checks only): is this an atom which looks
226 like it's from original code? */
227static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
228{
229 if (a1->tag == Iex_Const)
230 return True;
sewardj0b9d74a2006-12-24 02:24:11 +0000231 if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < mce->n_originalTmps)
sewardj95448072004-11-22 20:19:51 +0000232 return True;
233 return False;
234}
235
236/* (used for sanity checks only): is this an atom which looks
237 like it's from shadow code? */
238static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
239{
240 if (a1->tag == Iex_Const)
241 return True;
sewardj0b9d74a2006-12-24 02:24:11 +0000242 if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= mce->n_originalTmps)
sewardj95448072004-11-22 20:19:51 +0000243 return True;
244 return False;
245}
246
247/* (used for sanity checks only): check that both args are atoms and
248 are identically-kinded. */
249static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
250{
sewardj0b9d74a2006-12-24 02:24:11 +0000251 if (a1->tag == Iex_RdTmp && a2->tag == Iex_RdTmp)
sewardj95448072004-11-22 20:19:51 +0000252 return True;
sewardjbef552a2005-08-30 12:54:36 +0000253 if (a1->tag == Iex_Const && a2->tag == Iex_Const)
sewardj95448072004-11-22 20:19:51 +0000254 return True;
255 return False;
256}
257
258
259/*------------------------------------------------------------*/
260/*--- Type management ---*/
261/*------------------------------------------------------------*/
262
263/* Shadow state is always accessed using integer types. This returns
264 an integer type with the same size (as per sizeofIRType) as the
265 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj3245c912004-12-10 14:58:26 +0000266 I64, V128. */
sewardj95448072004-11-22 20:19:51 +0000267
268static IRType shadowType ( IRType ty )
269{
270 switch (ty) {
271 case Ity_I1:
272 case Ity_I8:
273 case Ity_I16:
274 case Ity_I32:
sewardj6cf40ff2005-04-20 22:31:26 +0000275 case Ity_I64:
276 case Ity_I128: return ty;
sewardj3245c912004-12-10 14:58:26 +0000277 case Ity_F32: return Ity_I32;
278 case Ity_F64: return Ity_I64;
279 case Ity_V128: return Ity_V128;
sewardj95448072004-11-22 20:19:51 +0000280 default: ppIRType(ty);
281 VG_(tool_panic)("memcheck:shadowType");
282 }
283}
284
285/* Produce a 'defined' value of the given shadow type. Should only be
286 supplied shadow types (Bit/I8/I16/I32/UI64). */
287static IRExpr* definedOfType ( IRType ty ) {
288 switch (ty) {
sewardj170ee212004-12-10 18:57:51 +0000289 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
290 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
291 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
292 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
293 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
294 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
sewardjf1962d32006-10-19 13:22:16 +0000295 default: VG_(tool_panic)("memcheck:definedOfType");
njn25e49d8e72002-09-23 09:36:25 +0000296 }
297}
298
299
sewardj95448072004-11-22 20:19:51 +0000300/*------------------------------------------------------------*/
301/*--- Constructing IR fragments ---*/
302/*------------------------------------------------------------*/
303
304/* assign value to tmp */
305#define assign(_bb,_tmp,_expr) \
sewardj0b9d74a2006-12-24 02:24:11 +0000306 addStmtToIRSB((_bb), IRStmt_WrTmp((_tmp),(_expr)))
sewardj95448072004-11-22 20:19:51 +0000307
308/* add stmt to a bb */
309#define stmt(_bb,_stmt) \
sewardj0b9d74a2006-12-24 02:24:11 +0000310 addStmtToIRSB((_bb), (_stmt))
sewardj95448072004-11-22 20:19:51 +0000311
312/* build various kinds of expressions */
313#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
314#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
315#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
316#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
317#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
318#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj170ee212004-12-10 18:57:51 +0000319#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardj0b9d74a2006-12-24 02:24:11 +0000320#define mkexpr(_tmp) IRExpr_RdTmp((_tmp))
sewardj95448072004-11-22 20:19:51 +0000321
322/* bind the given expression to a new temporary, and return the
323 temporary. This effectively converts an arbitrary expression into
324 an atom. */
325static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
326 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
327 assign(mce->bb, t, e);
328 return mkexpr(t);
329}
330
331
332/*------------------------------------------------------------*/
333/*--- Constructing definedness primitive ops ---*/
334/*------------------------------------------------------------*/
335
336/* --------- Defined-if-either-defined --------- */
337
338static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
339 tl_assert(isShadowAtom(mce,a1));
340 tl_assert(isShadowAtom(mce,a2));
341 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
342}
343
344static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
345 tl_assert(isShadowAtom(mce,a1));
346 tl_assert(isShadowAtom(mce,a2));
347 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
348}
349
350static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
351 tl_assert(isShadowAtom(mce,a1));
352 tl_assert(isShadowAtom(mce,a2));
353 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
354}
355
sewardj7010f6e2004-12-10 13:35:22 +0000356static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
357 tl_assert(isShadowAtom(mce,a1));
358 tl_assert(isShadowAtom(mce,a2));
359 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
360}
361
sewardj20d38f22005-02-07 23:50:18 +0000362static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj170ee212004-12-10 18:57:51 +0000363 tl_assert(isShadowAtom(mce,a1));
364 tl_assert(isShadowAtom(mce,a2));
sewardj20d38f22005-02-07 23:50:18 +0000365 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj170ee212004-12-10 18:57:51 +0000366}
367
sewardj95448072004-11-22 20:19:51 +0000368/* --------- Undefined-if-either-undefined --------- */
369
370static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
371 tl_assert(isShadowAtom(mce,a1));
372 tl_assert(isShadowAtom(mce,a2));
373 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
374}
375
376static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
377 tl_assert(isShadowAtom(mce,a1));
378 tl_assert(isShadowAtom(mce,a2));
379 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
380}
381
382static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
383 tl_assert(isShadowAtom(mce,a1));
384 tl_assert(isShadowAtom(mce,a2));
385 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
386}
387
388static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
389 tl_assert(isShadowAtom(mce,a1));
390 tl_assert(isShadowAtom(mce,a2));
391 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
392}
393
sewardj20d38f22005-02-07 23:50:18 +0000394static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj3245c912004-12-10 14:58:26 +0000395 tl_assert(isShadowAtom(mce,a1));
396 tl_assert(isShadowAtom(mce,a2));
sewardj20d38f22005-02-07 23:50:18 +0000397 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj3245c912004-12-10 14:58:26 +0000398}
399
sewardje50a1b12004-12-17 01:24:54 +0000400static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardj95448072004-11-22 20:19:51 +0000401 switch (vty) {
sewardje50a1b12004-12-17 01:24:54 +0000402 case Ity_I8: return mkUifU8(mce, a1, a2);
sewardja1d93302004-12-12 16:45:06 +0000403 case Ity_I16: return mkUifU16(mce, a1, a2);
404 case Ity_I32: return mkUifU32(mce, a1, a2);
405 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardj20d38f22005-02-07 23:50:18 +0000406 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardj95448072004-11-22 20:19:51 +0000407 default:
408 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
409 VG_(tool_panic)("memcheck:mkUifU");
njn25e49d8e72002-09-23 09:36:25 +0000410 }
411}
412
sewardj95448072004-11-22 20:19:51 +0000413/* --------- The Left-family of operations. --------- */
njn25e49d8e72002-09-23 09:36:25 +0000414
sewardj95448072004-11-22 20:19:51 +0000415static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
416 tl_assert(isShadowAtom(mce,a1));
sewardj4cc684b2007-08-25 23:09:36 +0000417 return assignNew(mce, Ity_I8, unop(Iop_Left8, a1));
sewardj95448072004-11-22 20:19:51 +0000418}
419
420static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
421 tl_assert(isShadowAtom(mce,a1));
sewardj4cc684b2007-08-25 23:09:36 +0000422 return assignNew(mce, Ity_I16, unop(Iop_Left16, a1));
sewardj95448072004-11-22 20:19:51 +0000423}
424
425static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
426 tl_assert(isShadowAtom(mce,a1));
sewardj4cc684b2007-08-25 23:09:36 +0000427 return assignNew(mce, Ity_I32, unop(Iop_Left32, a1));
sewardj95448072004-11-22 20:19:51 +0000428}
429
sewardj681be302005-01-15 20:43:58 +0000430static IRAtom* mkLeft64 ( MCEnv* mce, IRAtom* a1 ) {
431 tl_assert(isShadowAtom(mce,a1));
sewardj4cc684b2007-08-25 23:09:36 +0000432 return assignNew(mce, Ity_I64, unop(Iop_Left64, a1));
sewardj681be302005-01-15 20:43:58 +0000433}
434
sewardj95448072004-11-22 20:19:51 +0000435/* --------- 'Improvement' functions for AND/OR. --------- */
436
437/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
438 defined (0); all other -> undefined (1).
439*/
440static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
njn25e49d8e72002-09-23 09:36:25 +0000441{
sewardj95448072004-11-22 20:19:51 +0000442 tl_assert(isOriginalAtom(mce, data));
443 tl_assert(isShadowAtom(mce, vbits));
444 tl_assert(sameKindedAtoms(data, vbits));
445 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
446}
njn25e49d8e72002-09-23 09:36:25 +0000447
sewardj95448072004-11-22 20:19:51 +0000448static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
449{
450 tl_assert(isOriginalAtom(mce, data));
451 tl_assert(isShadowAtom(mce, vbits));
452 tl_assert(sameKindedAtoms(data, vbits));
453 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
454}
njn25e49d8e72002-09-23 09:36:25 +0000455
sewardj95448072004-11-22 20:19:51 +0000456static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
457{
458 tl_assert(isOriginalAtom(mce, data));
459 tl_assert(isShadowAtom(mce, vbits));
460 tl_assert(sameKindedAtoms(data, vbits));
461 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
462}
njn25e49d8e72002-09-23 09:36:25 +0000463
sewardj7010f6e2004-12-10 13:35:22 +0000464static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
465{
466 tl_assert(isOriginalAtom(mce, data));
467 tl_assert(isShadowAtom(mce, vbits));
468 tl_assert(sameKindedAtoms(data, vbits));
469 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
470}
471
sewardj20d38f22005-02-07 23:50:18 +0000472static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj170ee212004-12-10 18:57:51 +0000473{
474 tl_assert(isOriginalAtom(mce, data));
475 tl_assert(isShadowAtom(mce, vbits));
476 tl_assert(sameKindedAtoms(data, vbits));
sewardj20d38f22005-02-07 23:50:18 +0000477 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj170ee212004-12-10 18:57:51 +0000478}
479
sewardj95448072004-11-22 20:19:51 +0000480/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
481 defined (0); all other -> undefined (1).
482*/
483static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
484{
485 tl_assert(isOriginalAtom(mce, data));
486 tl_assert(isShadowAtom(mce, vbits));
487 tl_assert(sameKindedAtoms(data, vbits));
488 return assignNew(
489 mce, Ity_I8,
490 binop(Iop_Or8,
491 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
492 vbits) );
493}
njn25e49d8e72002-09-23 09:36:25 +0000494
sewardj95448072004-11-22 20:19:51 +0000495static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
496{
497 tl_assert(isOriginalAtom(mce, data));
498 tl_assert(isShadowAtom(mce, vbits));
499 tl_assert(sameKindedAtoms(data, vbits));
500 return assignNew(
501 mce, Ity_I16,
502 binop(Iop_Or16,
503 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
504 vbits) );
505}
njn25e49d8e72002-09-23 09:36:25 +0000506
sewardj95448072004-11-22 20:19:51 +0000507static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
508{
509 tl_assert(isOriginalAtom(mce, data));
510 tl_assert(isShadowAtom(mce, vbits));
511 tl_assert(sameKindedAtoms(data, vbits));
512 return assignNew(
513 mce, Ity_I32,
514 binop(Iop_Or32,
515 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
516 vbits) );
517}
518
sewardj7010f6e2004-12-10 13:35:22 +0000519static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
520{
521 tl_assert(isOriginalAtom(mce, data));
522 tl_assert(isShadowAtom(mce, vbits));
523 tl_assert(sameKindedAtoms(data, vbits));
524 return assignNew(
525 mce, Ity_I64,
526 binop(Iop_Or64,
527 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
528 vbits) );
529}
530
sewardj20d38f22005-02-07 23:50:18 +0000531static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj170ee212004-12-10 18:57:51 +0000532{
533 tl_assert(isOriginalAtom(mce, data));
534 tl_assert(isShadowAtom(mce, vbits));
535 tl_assert(sameKindedAtoms(data, vbits));
536 return assignNew(
537 mce, Ity_V128,
sewardj20d38f22005-02-07 23:50:18 +0000538 binop(Iop_OrV128,
539 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj170ee212004-12-10 18:57:51 +0000540 vbits) );
541}
542
sewardj95448072004-11-22 20:19:51 +0000543/* --------- Pessimising casts. --------- */
544
545static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
546{
sewardj4cc684b2007-08-25 23:09:36 +0000547 IRType src_ty;
sewardj7cf97ee2004-11-28 14:25:01 +0000548 IRAtom* tmp1;
sewardj95448072004-11-22 20:19:51 +0000549 /* Note, dst_ty is a shadow type, not an original type. */
550 /* First of all, collapse vbits down to a single bit. */
551 tl_assert(isShadowAtom(mce,vbits));
sewardj4cc684b2007-08-25 23:09:36 +0000552 src_ty = typeOfIRExpr(mce->bb->tyenv, vbits);
553
554 /* Fast-track some common cases */
555 if (src_ty == Ity_I32 && dst_ty == Ity_I32)
556 return assignNew(mce, Ity_I32, unop(Iop_CmpwNEZ32, vbits));
557
558 if (src_ty == Ity_I64 && dst_ty == Ity_I64)
559 return assignNew(mce, Ity_I64, unop(Iop_CmpwNEZ64, vbits));
560
561 if (src_ty == Ity_I32 && dst_ty == Ity_I64) {
562 IRAtom* tmp = assignNew(mce, Ity_I32, unop(Iop_CmpwNEZ32, vbits));
563 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, tmp, tmp));
564 }
565
566 /* Else do it the slow way .. */
567 tmp1 = NULL;
568 switch (src_ty) {
sewardj95448072004-11-22 20:19:51 +0000569 case Ity_I1:
570 tmp1 = vbits;
njn25e49d8e72002-09-23 09:36:25 +0000571 break;
sewardj95448072004-11-22 20:19:51 +0000572 case Ity_I8:
sewardj37c31cc2005-04-26 23:49:24 +0000573 tmp1 = assignNew(mce, Ity_I1, unop(Iop_CmpNEZ8, vbits));
sewardj95448072004-11-22 20:19:51 +0000574 break;
575 case Ity_I16:
sewardj37c31cc2005-04-26 23:49:24 +0000576 tmp1 = assignNew(mce, Ity_I1, unop(Iop_CmpNEZ16, vbits));
sewardj95448072004-11-22 20:19:51 +0000577 break;
578 case Ity_I32:
sewardj37c31cc2005-04-26 23:49:24 +0000579 tmp1 = assignNew(mce, Ity_I1, unop(Iop_CmpNEZ32, vbits));
sewardj95448072004-11-22 20:19:51 +0000580 break;
581 case Ity_I64:
sewardj37c31cc2005-04-26 23:49:24 +0000582 tmp1 = assignNew(mce, Ity_I1, unop(Iop_CmpNEZ64, vbits));
sewardj95448072004-11-22 20:19:51 +0000583 break;
sewardj69a13322005-04-23 01:14:51 +0000584 case Ity_I128: {
585 /* Gah. Chop it in half, OR the halves together, and compare
586 that with zero. */
587 IRAtom* tmp2 = assignNew(mce, Ity_I64, unop(Iop_128HIto64, vbits));
588 IRAtom* tmp3 = assignNew(mce, Ity_I64, unop(Iop_128to64, vbits));
589 IRAtom* tmp4 = assignNew(mce, Ity_I64, binop(Iop_Or64, tmp2, tmp3));
590 tmp1 = assignNew(mce, Ity_I1,
sewardj37c31cc2005-04-26 23:49:24 +0000591 unop(Iop_CmpNEZ64, tmp4));
sewardj69a13322005-04-23 01:14:51 +0000592 break;
593 }
sewardj95448072004-11-22 20:19:51 +0000594 default:
sewardj4cc684b2007-08-25 23:09:36 +0000595 ppIRType(src_ty);
sewardj95448072004-11-22 20:19:51 +0000596 VG_(tool_panic)("mkPCastTo(1)");
597 }
598 tl_assert(tmp1);
599 /* Now widen up to the dst type. */
600 switch (dst_ty) {
601 case Ity_I1:
602 return tmp1;
603 case Ity_I8:
604 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
605 case Ity_I16:
606 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
607 case Ity_I32:
608 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
609 case Ity_I64:
610 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardja1d93302004-12-12 16:45:06 +0000611 case Ity_V128:
612 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj20d38f22005-02-07 23:50:18 +0000613 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardja1d93302004-12-12 16:45:06 +0000614 return tmp1;
sewardj69a13322005-04-23 01:14:51 +0000615 case Ity_I128:
616 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
617 tmp1 = assignNew(mce, Ity_I128, binop(Iop_64HLto128, tmp1, tmp1));
618 return tmp1;
sewardj95448072004-11-22 20:19:51 +0000619 default:
620 ppIRType(dst_ty);
621 VG_(tool_panic)("mkPCastTo(2)");
622 }
623}
624
sewardjd5204dc2004-12-31 01:16:11 +0000625/* --------- Accurate interpretation of CmpEQ/CmpNE. --------- */
626/*
627 Normally, we can do CmpEQ/CmpNE by doing UifU on the arguments, and
628 PCasting to Ity_U1. However, sometimes it is necessary to be more
629 accurate. The insight is that the result is defined if two
630 corresponding bits can be found, one from each argument, so that
631 both bits are defined but are different -- that makes EQ say "No"
632 and NE say "Yes". Hence, we compute an improvement term and DifD
633 it onto the "normal" (UifU) result.
634
635 The result is:
636
637 PCastTo<1> (
sewardje6f8af42005-07-06 18:48:59 +0000638 -- naive version
639 PCastTo<sz>( UifU<sz>(vxx, vyy) )
640
sewardjd5204dc2004-12-31 01:16:11 +0000641 `DifD<sz>`
sewardje6f8af42005-07-06 18:48:59 +0000642
643 -- improvement term
644 PCastTo<sz>( PCast<sz>( CmpEQ<sz> ( vec, 1...1 ) ) )
sewardjd5204dc2004-12-31 01:16:11 +0000645 )
sewardje6f8af42005-07-06 18:48:59 +0000646
sewardjd5204dc2004-12-31 01:16:11 +0000647 where
648 vec contains 0 (defined) bits where the corresponding arg bits
sewardje6f8af42005-07-06 18:48:59 +0000649 are defined but different, and 1 bits otherwise.
sewardjd5204dc2004-12-31 01:16:11 +0000650
sewardje6f8af42005-07-06 18:48:59 +0000651 vec = Or<sz>( vxx, // 0 iff bit defined
652 vyy, // 0 iff bit defined
653 Not<sz>(Xor<sz>( xx, yy )) // 0 iff bits different
654 )
655
656 If any bit of vec is 0, the result is defined and so the
657 improvement term should produce 0...0, else it should produce
658 1...1.
659
660 Hence require for the improvement term:
661
662 if vec == 1...1 then 1...1 else 0...0
663 ->
664 PCast<sz>( CmpEQ<sz> ( vec, 1...1 ) )
665
666 This was extensively re-analysed and checked on 6 July 05.
sewardjd5204dc2004-12-31 01:16:11 +0000667*/
668static IRAtom* expensiveCmpEQorNE ( MCEnv* mce,
669 IRType ty,
670 IRAtom* vxx, IRAtom* vyy,
671 IRAtom* xx, IRAtom* yy )
672{
sewardje6f8af42005-07-06 18:48:59 +0000673 IRAtom *naive, *vec, *improvement_term;
674 IRAtom *improved, *final_cast, *top;
675 IROp opDIFD, opUIFU, opXOR, opNOT, opCMP, opOR;
sewardjd5204dc2004-12-31 01:16:11 +0000676
677 tl_assert(isShadowAtom(mce,vxx));
678 tl_assert(isShadowAtom(mce,vyy));
679 tl_assert(isOriginalAtom(mce,xx));
680 tl_assert(isOriginalAtom(mce,yy));
681 tl_assert(sameKindedAtoms(vxx,xx));
682 tl_assert(sameKindedAtoms(vyy,yy));
683
684 switch (ty) {
685 case Ity_I32:
sewardje6f8af42005-07-06 18:48:59 +0000686 opOR = Iop_Or32;
sewardjd5204dc2004-12-31 01:16:11 +0000687 opDIFD = Iop_And32;
688 opUIFU = Iop_Or32;
689 opNOT = Iop_Not32;
690 opXOR = Iop_Xor32;
691 opCMP = Iop_CmpEQ32;
692 top = mkU32(0xFFFFFFFF);
693 break;
tomcd986332005-04-26 07:44:48 +0000694 case Ity_I64:
sewardje6f8af42005-07-06 18:48:59 +0000695 opOR = Iop_Or64;
tomcd986332005-04-26 07:44:48 +0000696 opDIFD = Iop_And64;
697 opUIFU = Iop_Or64;
698 opNOT = Iop_Not64;
699 opXOR = Iop_Xor64;
700 opCMP = Iop_CmpEQ64;
sewardj37c31cc2005-04-26 23:49:24 +0000701 top = mkU64(0xFFFFFFFFFFFFFFFFULL);
tomcd986332005-04-26 07:44:48 +0000702 break;
sewardjd5204dc2004-12-31 01:16:11 +0000703 default:
704 VG_(tool_panic)("expensiveCmpEQorNE");
705 }
706
707 naive
708 = mkPCastTo(mce,ty, assignNew(mce, ty, binop(opUIFU, vxx, vyy)));
709
710 vec
711 = assignNew(
712 mce,ty,
sewardje6f8af42005-07-06 18:48:59 +0000713 binop( opOR,
714 assignNew(mce,ty, binop(opOR, vxx, vyy)),
sewardjd5204dc2004-12-31 01:16:11 +0000715 assignNew(
716 mce,ty,
717 unop( opNOT,
718 assignNew(mce,ty, binop(opXOR, xx, yy))))));
719
sewardje6f8af42005-07-06 18:48:59 +0000720 improvement_term
sewardjd5204dc2004-12-31 01:16:11 +0000721 = mkPCastTo( mce,ty, assignNew(mce,Ity_I1, binop(opCMP, vec, top)));
722
723 improved
sewardje6f8af42005-07-06 18:48:59 +0000724 = assignNew( mce,ty, binop(opDIFD, naive, improvement_term) );
sewardjd5204dc2004-12-31 01:16:11 +0000725
726 final_cast
727 = mkPCastTo( mce, Ity_I1, improved );
728
729 return final_cast;
730}
731
sewardj95448072004-11-22 20:19:51 +0000732
sewardj992dff92005-10-07 11:08:55 +0000733/* --------- Semi-accurate interpretation of CmpORD. --------- */
734
735/* CmpORD32{S,U} does PowerPC-style 3-way comparisons:
736
737 CmpORD32S(x,y) = 1<<3 if x <s y
738 = 1<<2 if x >s y
739 = 1<<1 if x == y
740
741 and similarly the unsigned variant. The default interpretation is:
742
743 CmpORD32{S,U}#(x,y,x#,y#) = PCast(x# `UifU` y#)
sewardj1bc82102005-12-23 00:16:24 +0000744 & (7<<1)
sewardj992dff92005-10-07 11:08:55 +0000745
746 The "& (7<<1)" reflects the fact that all result bits except 3,2,1
747 are zero and therefore defined (viz, zero).
sewardja9e62a92005-10-07 12:13:21 +0000748
749 Also deal with a special case better:
750
751 CmpORD32S(x,0)
752
753 Here, bit 3 (LT) of the result is a copy of the top bit of x and
754 will be defined even if the rest of x isn't. In which case we do:
755
756 CmpORD32S#(x,x#,0,{impliedly 0}#)
sewardj1bc82102005-12-23 00:16:24 +0000757 = PCast(x#) & (3<<1) -- standard interp for GT#,EQ#
758 | (x# >>u 31) << 3 -- LT# = x#[31]
sewardja9e62a92005-10-07 12:13:21 +0000759
sewardj1bc82102005-12-23 00:16:24 +0000760 Analogous handling for CmpORD64{S,U}.
sewardj992dff92005-10-07 11:08:55 +0000761*/
sewardja9e62a92005-10-07 12:13:21 +0000762static Bool isZeroU32 ( IRAtom* e )
763{
764 return
765 toBool( e->tag == Iex_Const
766 && e->Iex.Const.con->tag == Ico_U32
767 && e->Iex.Const.con->Ico.U32 == 0 );
768}
769
sewardj1bc82102005-12-23 00:16:24 +0000770static Bool isZeroU64 ( IRAtom* e )
sewardj992dff92005-10-07 11:08:55 +0000771{
sewardj1bc82102005-12-23 00:16:24 +0000772 return
773 toBool( e->tag == Iex_Const
774 && e->Iex.Const.con->tag == Ico_U64
775 && e->Iex.Const.con->Ico.U64 == 0 );
776}
777
778static IRAtom* doCmpORD ( MCEnv* mce,
779 IROp cmp_op,
780 IRAtom* xxhash, IRAtom* yyhash,
781 IRAtom* xx, IRAtom* yy )
782{
783 Bool m64 = cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD64U;
784 Bool syned = cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD32S;
785 IROp opOR = m64 ? Iop_Or64 : Iop_Or32;
786 IROp opAND = m64 ? Iop_And64 : Iop_And32;
787 IROp opSHL = m64 ? Iop_Shl64 : Iop_Shl32;
788 IROp opSHR = m64 ? Iop_Shr64 : Iop_Shr32;
789 IRType ty = m64 ? Ity_I64 : Ity_I32;
790 Int width = m64 ? 64 : 32;
791
792 Bool (*isZero)(IRAtom*) = m64 ? isZeroU64 : isZeroU32;
793
794 IRAtom* threeLeft1 = NULL;
795 IRAtom* sevenLeft1 = NULL;
796
sewardj992dff92005-10-07 11:08:55 +0000797 tl_assert(isShadowAtom(mce,xxhash));
798 tl_assert(isShadowAtom(mce,yyhash));
799 tl_assert(isOriginalAtom(mce,xx));
800 tl_assert(isOriginalAtom(mce,yy));
801 tl_assert(sameKindedAtoms(xxhash,xx));
802 tl_assert(sameKindedAtoms(yyhash,yy));
sewardj1bc82102005-12-23 00:16:24 +0000803 tl_assert(cmp_op == Iop_CmpORD32S || cmp_op == Iop_CmpORD32U
804 || cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD64U);
sewardj992dff92005-10-07 11:08:55 +0000805
sewardja9e62a92005-10-07 12:13:21 +0000806 if (0) {
807 ppIROp(cmp_op); VG_(printf)(" ");
808 ppIRExpr(xx); VG_(printf)(" "); ppIRExpr( yy ); VG_(printf)("\n");
809 }
810
sewardj1bc82102005-12-23 00:16:24 +0000811 if (syned && isZero(yy)) {
sewardja9e62a92005-10-07 12:13:21 +0000812 /* fancy interpretation */
813 /* if yy is zero, then it must be fully defined (zero#). */
sewardj1bc82102005-12-23 00:16:24 +0000814 tl_assert(isZero(yyhash));
815 threeLeft1 = m64 ? mkU64(3<<1) : mkU32(3<<1);
sewardja9e62a92005-10-07 12:13:21 +0000816 return
817 binop(
sewardj1bc82102005-12-23 00:16:24 +0000818 opOR,
sewardja9e62a92005-10-07 12:13:21 +0000819 assignNew(
sewardj1bc82102005-12-23 00:16:24 +0000820 mce,ty,
sewardja9e62a92005-10-07 12:13:21 +0000821 binop(
sewardj1bc82102005-12-23 00:16:24 +0000822 opAND,
823 mkPCastTo(mce,ty, xxhash),
824 threeLeft1
sewardja9e62a92005-10-07 12:13:21 +0000825 )),
826 assignNew(
sewardj1bc82102005-12-23 00:16:24 +0000827 mce,ty,
sewardja9e62a92005-10-07 12:13:21 +0000828 binop(
sewardj1bc82102005-12-23 00:16:24 +0000829 opSHL,
sewardja9e62a92005-10-07 12:13:21 +0000830 assignNew(
sewardj1bc82102005-12-23 00:16:24 +0000831 mce,ty,
832 binop(opSHR, xxhash, mkU8(width-1))),
sewardja9e62a92005-10-07 12:13:21 +0000833 mkU8(3)
834 ))
835 );
836 } else {
837 /* standard interpretation */
sewardj1bc82102005-12-23 00:16:24 +0000838 sevenLeft1 = m64 ? mkU64(7<<1) : mkU32(7<<1);
sewardja9e62a92005-10-07 12:13:21 +0000839 return
840 binop(
sewardj1bc82102005-12-23 00:16:24 +0000841 opAND,
842 mkPCastTo( mce,ty,
843 mkUifU(mce,ty, xxhash,yyhash)),
844 sevenLeft1
sewardja9e62a92005-10-07 12:13:21 +0000845 );
846 }
sewardj992dff92005-10-07 11:08:55 +0000847}
848
849
sewardj95448072004-11-22 20:19:51 +0000850/*------------------------------------------------------------*/
851/*--- Emit a test and complaint if something is undefined. ---*/
852/*------------------------------------------------------------*/
853
854/* Set the annotations on a dirty helper to indicate that the stack
855 pointer and instruction pointers might be read. This is the
856 behaviour of all 'emit-a-complaint' style functions we might
857 call. */
858
859static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
860 di->nFxState = 2;
861 di->fxState[0].fx = Ifx_Read;
862 di->fxState[0].offset = mce->layout->offset_SP;
863 di->fxState[0].size = mce->layout->sizeof_SP;
864 di->fxState[1].fx = Ifx_Read;
865 di->fxState[1].offset = mce->layout->offset_IP;
866 di->fxState[1].size = mce->layout->sizeof_IP;
867}
868
869
870/* Check the supplied **original** atom for undefinedness, and emit a
871 complaint if so. Once that happens, mark it as defined. This is
872 possible because the atom is either a tmp or literal. If it's a
873 tmp, it will be shadowed by a tmp, and so we can set the shadow to
874 be defined. In fact as mentioned above, we will have to allocate a
875 new tmp to carry the new 'defined' shadow value, and update the
876 original->tmp mapping accordingly; we cannot simply assign a new
877 value to an existing shadow tmp as this breaks SSAness -- resulting
878 in the post-instrumentation sanity checker spluttering in disapproval.
879*/
880static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
881{
sewardj7cf97ee2004-11-28 14:25:01 +0000882 IRAtom* vatom;
883 IRType ty;
884 Int sz;
885 IRDirty* di;
886 IRAtom* cond;
887
njn1d0825f2006-03-27 11:37:07 +0000888 // Don't do V bit tests if we're not reporting undefined value errors.
889 if (!MC_(clo_undef_value_errors))
890 return;
891
sewardj95448072004-11-22 20:19:51 +0000892 /* Since the original expression is atomic, there's no duplicated
893 work generated by making multiple V-expressions for it. So we
894 don't really care about the possibility that someone else may
895 also create a V-interpretion for it. */
896 tl_assert(isOriginalAtom(mce, atom));
sewardj7cf97ee2004-11-28 14:25:01 +0000897 vatom = expr2vbits( mce, atom );
sewardj95448072004-11-22 20:19:51 +0000898 tl_assert(isShadowAtom(mce, vatom));
899 tl_assert(sameKindedAtoms(atom, vatom));
900
sewardj7cf97ee2004-11-28 14:25:01 +0000901 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj95448072004-11-22 20:19:51 +0000902
903 /* sz is only used for constructing the error message */
sewardj7cf97ee2004-11-28 14:25:01 +0000904 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardj95448072004-11-22 20:19:51 +0000905
sewardj7cf97ee2004-11-28 14:25:01 +0000906 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardj95448072004-11-22 20:19:51 +0000907 /* cond will be 0 if all defined, and 1 if any not defined. */
908
sewardj95448072004-11-22 20:19:51 +0000909 switch (sz) {
910 case 0:
sewardj53ee1fc2005-12-23 02:29:58 +0000911 di = unsafeIRDirty_0_N(
912 0/*regparms*/,
913 "MC_(helperc_value_check0_fail)",
914 VG_(fnptr_to_fnentry)( &MC_(helperc_value_check0_fail) ),
915 mkIRExprVec_0()
916 );
sewardj95448072004-11-22 20:19:51 +0000917 break;
918 case 1:
sewardj53ee1fc2005-12-23 02:29:58 +0000919 di = unsafeIRDirty_0_N(
920 0/*regparms*/,
921 "MC_(helperc_value_check1_fail)",
922 VG_(fnptr_to_fnentry)( &MC_(helperc_value_check1_fail) ),
923 mkIRExprVec_0()
924 );
sewardj95448072004-11-22 20:19:51 +0000925 break;
926 case 4:
sewardj53ee1fc2005-12-23 02:29:58 +0000927 di = unsafeIRDirty_0_N(
928 0/*regparms*/,
929 "MC_(helperc_value_check4_fail)",
930 VG_(fnptr_to_fnentry)( &MC_(helperc_value_check4_fail) ),
931 mkIRExprVec_0()
932 );
sewardj95448072004-11-22 20:19:51 +0000933 break;
sewardj11bcc4e2005-04-23 22:38:38 +0000934 case 8:
sewardj53ee1fc2005-12-23 02:29:58 +0000935 di = unsafeIRDirty_0_N(
936 0/*regparms*/,
937 "MC_(helperc_value_check8_fail)",
938 VG_(fnptr_to_fnentry)( &MC_(helperc_value_check8_fail) ),
939 mkIRExprVec_0()
940 );
sewardj11bcc4e2005-04-23 22:38:38 +0000941 break;
sewardj95448072004-11-22 20:19:51 +0000942 default:
sewardj53ee1fc2005-12-23 02:29:58 +0000943 di = unsafeIRDirty_0_N(
944 1/*regparms*/,
945 "MC_(helperc_complain_undef)",
946 VG_(fnptr_to_fnentry)( &MC_(helperc_complain_undef) ),
947 mkIRExprVec_1( mkIRExpr_HWord( sz ))
948 );
sewardj95448072004-11-22 20:19:51 +0000949 break;
950 }
951 di->guard = cond;
952 setHelperAnns( mce, di );
953 stmt( mce->bb, IRStmt_Dirty(di));
954
955 /* Set the shadow tmp to be defined. First, update the
956 orig->shadow tmp mapping to reflect the fact that this shadow is
957 getting a new value. */
sewardj710d6c22005-03-20 18:55:15 +0000958 tl_assert(isIRAtom(vatom));
sewardj95448072004-11-22 20:19:51 +0000959 /* sameKindedAtoms ... */
sewardj0b9d74a2006-12-24 02:24:11 +0000960 if (vatom->tag == Iex_RdTmp) {
961 tl_assert(atom->tag == Iex_RdTmp);
962 newShadowTmp(mce, atom->Iex.RdTmp.tmp);
963 assign(mce->bb, findShadowTmp(mce, atom->Iex.RdTmp.tmp),
sewardj95448072004-11-22 20:19:51 +0000964 definedOfType(ty));
965 }
966}
967
968
969/*------------------------------------------------------------*/
970/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
971/*------------------------------------------------------------*/
972
973/* Examine the always-defined sections declared in layout to see if
974 the (offset,size) section is within one. Note, is is an error to
975 partially fall into such a region: (offset,size) should either be
976 completely in such a region or completely not-in such a region.
977*/
978static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
979{
980 Int minoffD, maxoffD, i;
981 Int minoff = offset;
982 Int maxoff = minoff + size - 1;
983 tl_assert((minoff & ~0xFFFF) == 0);
984 tl_assert((maxoff & ~0xFFFF) == 0);
985
986 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
987 minoffD = mce->layout->alwaysDefd[i].offset;
988 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
989 tl_assert((minoffD & ~0xFFFF) == 0);
990 tl_assert((maxoffD & ~0xFFFF) == 0);
991
992 if (maxoff < minoffD || maxoffD < minoff)
993 continue; /* no overlap */
994 if (minoff >= minoffD && maxoff <= maxoffD)
995 return True; /* completely contained in an always-defd section */
996
997 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
998 }
999 return False; /* could not find any containing section */
1000}
1001
1002
1003/* Generate into bb suitable actions to shadow this Put. If the state
1004 slice is marked 'always defined', do nothing. Otherwise, write the
1005 supplied V bits to the shadow state. We can pass in either an
1006 original atom or a V-atom, but not both. In the former case the
1007 relevant V-bits are then generated from the original.
1008*/
1009static
1010void do_shadow_PUT ( MCEnv* mce, Int offset,
1011 IRAtom* atom, IRAtom* vatom )
1012{
sewardj7cf97ee2004-11-28 14:25:01 +00001013 IRType ty;
njn1d0825f2006-03-27 11:37:07 +00001014
1015 // Don't do shadow PUTs if we're not doing undefined value checking.
1016 // Their absence lets Vex's optimiser remove all the shadow computation
1017 // that they depend on, which includes GETs of the shadow registers.
1018 if (!MC_(clo_undef_value_errors))
1019 return;
1020
sewardj95448072004-11-22 20:19:51 +00001021 if (atom) {
1022 tl_assert(!vatom);
1023 tl_assert(isOriginalAtom(mce, atom));
1024 vatom = expr2vbits( mce, atom );
1025 } else {
1026 tl_assert(vatom);
1027 tl_assert(isShadowAtom(mce, vatom));
1028 }
1029
sewardj7cf97ee2004-11-28 14:25:01 +00001030 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj95448072004-11-22 20:19:51 +00001031 tl_assert(ty != Ity_I1);
1032 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1033 /* later: no ... */
1034 /* emit code to emit a complaint if any of the vbits are 1. */
1035 /* complainIfUndefined(mce, atom); */
1036 } else {
1037 /* Do a plain shadow Put. */
1038 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1039 }
1040}
1041
1042
1043/* Return an expression which contains the V bits corresponding to the
1044 given GETI (passed in in pieces).
1045*/
1046static
1047void do_shadow_PUTI ( MCEnv* mce,
sewardj0b9d74a2006-12-24 02:24:11 +00001048 IRRegArray* descr,
1049 IRAtom* ix, Int bias, IRAtom* atom )
sewardj95448072004-11-22 20:19:51 +00001050{
sewardj7cf97ee2004-11-28 14:25:01 +00001051 IRAtom* vatom;
1052 IRType ty, tyS;
1053 Int arrSize;;
1054
njn1d0825f2006-03-27 11:37:07 +00001055 // Don't do shadow PUTIs if we're not doing undefined value checking.
1056 // Their absence lets Vex's optimiser remove all the shadow computation
1057 // that they depend on, which includes GETIs of the shadow registers.
1058 if (!MC_(clo_undef_value_errors))
1059 return;
1060
sewardj95448072004-11-22 20:19:51 +00001061 tl_assert(isOriginalAtom(mce,atom));
sewardj7cf97ee2004-11-28 14:25:01 +00001062 vatom = expr2vbits( mce, atom );
sewardj95448072004-11-22 20:19:51 +00001063 tl_assert(sameKindedAtoms(atom, vatom));
sewardj7cf97ee2004-11-28 14:25:01 +00001064 ty = descr->elemTy;
1065 tyS = shadowType(ty);
1066 arrSize = descr->nElems * sizeofIRType(ty);
sewardj95448072004-11-22 20:19:51 +00001067 tl_assert(ty != Ity_I1);
1068 tl_assert(isOriginalAtom(mce,ix));
1069 complainIfUndefined(mce,ix);
1070 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1071 /* later: no ... */
1072 /* emit code to emit a complaint if any of the vbits are 1. */
1073 /* complainIfUndefined(mce, atom); */
1074 } else {
1075 /* Do a cloned version of the Put that refers to the shadow
1076 area. */
sewardj0b9d74a2006-12-24 02:24:11 +00001077 IRRegArray* new_descr
1078 = mkIRRegArray( descr->base + mce->layout->total_sizeB,
1079 tyS, descr->nElems);
sewardj95448072004-11-22 20:19:51 +00001080 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1081 }
1082}
1083
1084
1085/* Return an expression which contains the V bits corresponding to the
1086 given GET (passed in in pieces).
1087*/
1088static
1089IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1090{
1091 IRType tyS = shadowType(ty);
1092 tl_assert(ty != Ity_I1);
1093 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1094 /* Always defined, return all zeroes of the relevant type */
1095 return definedOfType(tyS);
1096 } else {
1097 /* return a cloned version of the Get that refers to the shadow
1098 area. */
1099 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1100 }
1101}
1102
1103
1104/* Return an expression which contains the V bits corresponding to the
1105 given GETI (passed in in pieces).
1106*/
1107static
sewardj0b9d74a2006-12-24 02:24:11 +00001108IRExpr* shadow_GETI ( MCEnv* mce,
1109 IRRegArray* descr, IRAtom* ix, Int bias )
sewardj95448072004-11-22 20:19:51 +00001110{
1111 IRType ty = descr->elemTy;
1112 IRType tyS = shadowType(ty);
1113 Int arrSize = descr->nElems * sizeofIRType(ty);
1114 tl_assert(ty != Ity_I1);
1115 tl_assert(isOriginalAtom(mce,ix));
1116 complainIfUndefined(mce,ix);
1117 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1118 /* Always defined, return all zeroes of the relevant type */
1119 return definedOfType(tyS);
1120 } else {
1121 /* return a cloned version of the Get that refers to the shadow
1122 area. */
sewardj0b9d74a2006-12-24 02:24:11 +00001123 IRRegArray* new_descr
1124 = mkIRRegArray( descr->base + mce->layout->total_sizeB,
1125 tyS, descr->nElems);
sewardj95448072004-11-22 20:19:51 +00001126 return IRExpr_GetI( new_descr, ix, bias );
1127 }
1128}
1129
1130
1131/*------------------------------------------------------------*/
1132/*--- Generating approximations for unknown operations, ---*/
1133/*--- using lazy-propagate semantics ---*/
1134/*------------------------------------------------------------*/
1135
1136/* Lazy propagation of undefinedness from two values, resulting in the
1137 specified shadow type.
1138*/
1139static
1140IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1141{
sewardj95448072004-11-22 20:19:51 +00001142 IRAtom* at;
sewardj37c31cc2005-04-26 23:49:24 +00001143 IRType t1 = typeOfIRExpr(mce->bb->tyenv, va1);
1144 IRType t2 = typeOfIRExpr(mce->bb->tyenv, va2);
sewardj95448072004-11-22 20:19:51 +00001145 tl_assert(isShadowAtom(mce,va1));
1146 tl_assert(isShadowAtom(mce,va2));
sewardj37c31cc2005-04-26 23:49:24 +00001147
1148 /* The general case is inefficient because PCast is an expensive
1149 operation. Here are some special cases which use PCast only
1150 once rather than twice. */
1151
1152 /* I64 x I64 -> I64 */
1153 if (t1 == Ity_I64 && t2 == Ity_I64 && finalVty == Ity_I64) {
1154 if (0) VG_(printf)("mkLazy2: I64 x I64 -> I64\n");
1155 at = mkUifU(mce, Ity_I64, va1, va2);
1156 at = mkPCastTo(mce, Ity_I64, at);
1157 return at;
1158 }
1159
1160 /* I64 x I64 -> I32 */
1161 if (t1 == Ity_I64 && t2 == Ity_I64 && finalVty == Ity_I32) {
1162 if (0) VG_(printf)("mkLazy2: I64 x I64 -> I32\n");
1163 at = mkUifU(mce, Ity_I64, va1, va2);
1164 at = mkPCastTo(mce, Ity_I32, at);
1165 return at;
1166 }
1167
1168 if (0) {
1169 VG_(printf)("mkLazy2 ");
1170 ppIRType(t1);
1171 VG_(printf)("_");
1172 ppIRType(t2);
1173 VG_(printf)("_");
1174 ppIRType(finalVty);
1175 VG_(printf)("\n");
1176 }
1177
1178 /* General case: force everything via 32-bit intermediaries. */
sewardj95448072004-11-22 20:19:51 +00001179 at = mkPCastTo(mce, Ity_I32, va1);
1180 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1181 at = mkPCastTo(mce, finalVty, at);
1182 return at;
1183}
1184
1185
sewardjed69fdb2006-02-03 16:12:27 +00001186/* 3-arg version of the above. */
1187static
1188IRAtom* mkLazy3 ( MCEnv* mce, IRType finalVty,
1189 IRAtom* va1, IRAtom* va2, IRAtom* va3 )
1190{
1191 IRAtom* at;
1192 IRType t1 = typeOfIRExpr(mce->bb->tyenv, va1);
1193 IRType t2 = typeOfIRExpr(mce->bb->tyenv, va2);
1194 IRType t3 = typeOfIRExpr(mce->bb->tyenv, va3);
1195 tl_assert(isShadowAtom(mce,va1));
1196 tl_assert(isShadowAtom(mce,va2));
1197 tl_assert(isShadowAtom(mce,va3));
1198
1199 /* The general case is inefficient because PCast is an expensive
1200 operation. Here are some special cases which use PCast only
1201 twice rather than three times. */
1202
1203 /* I32 x I64 x I64 -> I64 */
1204 /* Standard FP idiom: rm x FParg1 x FParg2 -> FPresult */
1205 if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64
1206 && finalVty == Ity_I64) {
1207 if (0) VG_(printf)("mkLazy3: I32 x I64 x I64 -> I64\n");
1208 /* Widen 1st arg to I64. Since 1st arg is typically a rounding
1209 mode indication which is fully defined, this should get
1210 folded out later. */
1211 at = mkPCastTo(mce, Ity_I64, va1);
1212 /* Now fold in 2nd and 3rd args. */
1213 at = mkUifU(mce, Ity_I64, at, va2);
1214 at = mkUifU(mce, Ity_I64, at, va3);
1215 /* and PCast once again. */
1216 at = mkPCastTo(mce, Ity_I64, at);
1217 return at;
1218 }
1219
sewardj453e8f82006-02-09 03:25:06 +00001220 /* I32 x I64 x I64 -> I32 */
1221 if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64
1222 && finalVty == Ity_I32) {
1223 if (0) VG_(printf)("mkLazy3: I32 x I64 x I64 -> I64\n");
1224 at = mkPCastTo(mce, Ity_I64, va1);
1225 at = mkUifU(mce, Ity_I64, at, va2);
1226 at = mkUifU(mce, Ity_I64, at, va3);
1227 at = mkPCastTo(mce, Ity_I32, at);
1228 return at;
1229 }
1230
1231 if (1) {
1232 VG_(printf)("mkLazy3: ");
sewardjed69fdb2006-02-03 16:12:27 +00001233 ppIRType(t1);
sewardj453e8f82006-02-09 03:25:06 +00001234 VG_(printf)(" x ");
sewardjed69fdb2006-02-03 16:12:27 +00001235 ppIRType(t2);
sewardj453e8f82006-02-09 03:25:06 +00001236 VG_(printf)(" x ");
sewardjed69fdb2006-02-03 16:12:27 +00001237 ppIRType(t3);
sewardj453e8f82006-02-09 03:25:06 +00001238 VG_(printf)(" -> ");
sewardjed69fdb2006-02-03 16:12:27 +00001239 ppIRType(finalVty);
1240 VG_(printf)("\n");
1241 }
1242
sewardj453e8f82006-02-09 03:25:06 +00001243 tl_assert(0);
sewardjed69fdb2006-02-03 16:12:27 +00001244 /* General case: force everything via 32-bit intermediaries. */
sewardj453e8f82006-02-09 03:25:06 +00001245 /*
sewardjed69fdb2006-02-03 16:12:27 +00001246 at = mkPCastTo(mce, Ity_I32, va1);
1247 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1248 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va3));
1249 at = mkPCastTo(mce, finalVty, at);
1250 return at;
sewardj453e8f82006-02-09 03:25:06 +00001251 */
sewardjed69fdb2006-02-03 16:12:27 +00001252}
1253
1254
sewardje91cea72006-02-08 19:32:02 +00001255/* 4-arg version of the above. */
1256static
1257IRAtom* mkLazy4 ( MCEnv* mce, IRType finalVty,
1258 IRAtom* va1, IRAtom* va2, IRAtom* va3, IRAtom* va4 )
1259{
1260 IRAtom* at;
1261 IRType t1 = typeOfIRExpr(mce->bb->tyenv, va1);
1262 IRType t2 = typeOfIRExpr(mce->bb->tyenv, va2);
1263 IRType t3 = typeOfIRExpr(mce->bb->tyenv, va3);
1264 IRType t4 = typeOfIRExpr(mce->bb->tyenv, va4);
1265 tl_assert(isShadowAtom(mce,va1));
1266 tl_assert(isShadowAtom(mce,va2));
1267 tl_assert(isShadowAtom(mce,va3));
1268 tl_assert(isShadowAtom(mce,va4));
1269
1270 /* The general case is inefficient because PCast is an expensive
1271 operation. Here are some special cases which use PCast only
1272 twice rather than three times. */
1273
1274 /* I32 x I64 x I64 x I64 -> I64 */
1275 /* Standard FP idiom: rm x FParg1 x FParg2 x FParg3 -> FPresult */
1276 if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64 && t4 == Ity_I64
1277 && finalVty == Ity_I64) {
1278 if (0) VG_(printf)("mkLazy4: I32 x I64 x I64 x I64 -> I64\n");
1279 /* Widen 1st arg to I64. Since 1st arg is typically a rounding
1280 mode indication which is fully defined, this should get
1281 folded out later. */
1282 at = mkPCastTo(mce, Ity_I64, va1);
1283 /* Now fold in 2nd, 3rd, 4th args. */
1284 at = mkUifU(mce, Ity_I64, at, va2);
1285 at = mkUifU(mce, Ity_I64, at, va3);
1286 at = mkUifU(mce, Ity_I64, at, va4);
1287 /* and PCast once again. */
1288 at = mkPCastTo(mce, Ity_I64, at);
1289 return at;
1290 }
1291
1292 if (1) {
sewardj453e8f82006-02-09 03:25:06 +00001293 VG_(printf)("mkLazy4: ");
sewardje91cea72006-02-08 19:32:02 +00001294 ppIRType(t1);
1295 VG_(printf)(" x ");
1296 ppIRType(t2);
1297 VG_(printf)(" x ");
1298 ppIRType(t3);
1299 VG_(printf)(" x ");
1300 ppIRType(t4);
1301 VG_(printf)(" -> ");
1302 ppIRType(finalVty);
1303 VG_(printf)("\n");
1304 }
1305
1306 tl_assert(0);
1307}
1308
1309
sewardj95448072004-11-22 20:19:51 +00001310/* Do the lazy propagation game from a null-terminated vector of
1311 atoms. This is presumably the arguments to a helper call, so the
1312 IRCallee info is also supplied in order that we can know which
1313 arguments should be ignored (via the .mcx_mask field).
1314*/
1315static
1316IRAtom* mkLazyN ( MCEnv* mce,
1317 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1318{
sewardj4cc684b2007-08-25 23:09:36 +00001319 Int i;
sewardj95448072004-11-22 20:19:51 +00001320 IRAtom* here;
sewardj4cc684b2007-08-25 23:09:36 +00001321 IRAtom* curr;
1322 IRType mergeTy;
1323 IRType mergeTy64 = True;
1324
1325 /* Decide on the type of the merge intermediary. If all relevant
1326 args are I64, then it's I64. In all other circumstances, use
1327 I32. */
1328 for (i = 0; exprvec[i]; i++) {
1329 tl_assert(i < 32);
1330 tl_assert(isOriginalAtom(mce, exprvec[i]));
1331 if (cee->mcx_mask & (1<<i))
1332 continue;
1333 if (typeOfIRExpr(mce->bb->tyenv, exprvec[i]) != Ity_I64)
1334 mergeTy64 = False;
1335 }
1336
1337 mergeTy = mergeTy64 ? Ity_I64 : Ity_I32;
1338 curr = definedOfType(mergeTy);
1339
sewardj95448072004-11-22 20:19:51 +00001340 for (i = 0; exprvec[i]; i++) {
1341 tl_assert(i < 32);
1342 tl_assert(isOriginalAtom(mce, exprvec[i]));
1343 /* Only take notice of this arg if the callee's mc-exclusion
1344 mask does not say it is to be excluded. */
1345 if (cee->mcx_mask & (1<<i)) {
1346 /* the arg is to be excluded from definedness checking. Do
1347 nothing. */
1348 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1349 } else {
1350 /* calculate the arg's definedness, and pessimistically merge
1351 it in. */
sewardj4cc684b2007-08-25 23:09:36 +00001352 here = mkPCastTo( mce, mergeTy, expr2vbits(mce, exprvec[i]) );
1353 curr = mergeTy64
1354 ? mkUifU64(mce, here, curr)
1355 : mkUifU32(mce, here, curr);
sewardj95448072004-11-22 20:19:51 +00001356 }
1357 }
1358 return mkPCastTo(mce, finalVtype, curr );
1359}
1360
1361
1362/*------------------------------------------------------------*/
1363/*--- Generating expensive sequences for exact carry-chain ---*/
1364/*--- propagation in add/sub and related operations. ---*/
1365/*------------------------------------------------------------*/
1366
1367static
sewardjd5204dc2004-12-31 01:16:11 +00001368IRAtom* expensiveAddSub ( MCEnv* mce,
1369 Bool add,
1370 IRType ty,
1371 IRAtom* qaa, IRAtom* qbb,
1372 IRAtom* aa, IRAtom* bb )
sewardj95448072004-11-22 20:19:51 +00001373{
sewardj7cf97ee2004-11-28 14:25:01 +00001374 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardjd5204dc2004-12-31 01:16:11 +00001375 IROp opAND, opOR, opXOR, opNOT, opADD, opSUB;
sewardj7cf97ee2004-11-28 14:25:01 +00001376
sewardj95448072004-11-22 20:19:51 +00001377 tl_assert(isShadowAtom(mce,qaa));
1378 tl_assert(isShadowAtom(mce,qbb));
1379 tl_assert(isOriginalAtom(mce,aa));
1380 tl_assert(isOriginalAtom(mce,bb));
1381 tl_assert(sameKindedAtoms(qaa,aa));
1382 tl_assert(sameKindedAtoms(qbb,bb));
1383
sewardjd5204dc2004-12-31 01:16:11 +00001384 switch (ty) {
1385 case Ity_I32:
1386 opAND = Iop_And32;
1387 opOR = Iop_Or32;
1388 opXOR = Iop_Xor32;
1389 opNOT = Iop_Not32;
1390 opADD = Iop_Add32;
1391 opSUB = Iop_Sub32;
1392 break;
tomd9774d72005-06-27 08:11:01 +00001393 case Ity_I64:
1394 opAND = Iop_And64;
1395 opOR = Iop_Or64;
1396 opXOR = Iop_Xor64;
1397 opNOT = Iop_Not64;
1398 opADD = Iop_Add64;
1399 opSUB = Iop_Sub64;
1400 break;
sewardjd5204dc2004-12-31 01:16:11 +00001401 default:
1402 VG_(tool_panic)("expensiveAddSub");
1403 }
sewardj95448072004-11-22 20:19:51 +00001404
1405 // a_min = aa & ~qaa
1406 a_min = assignNew(mce,ty,
1407 binop(opAND, aa,
1408 assignNew(mce,ty, unop(opNOT, qaa))));
1409
1410 // b_min = bb & ~qbb
1411 b_min = assignNew(mce,ty,
1412 binop(opAND, bb,
1413 assignNew(mce,ty, unop(opNOT, qbb))));
1414
1415 // a_max = aa | qaa
1416 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1417
1418 // b_max = bb | qbb
1419 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1420
sewardjd5204dc2004-12-31 01:16:11 +00001421 if (add) {
1422 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1423 return
1424 assignNew(mce,ty,
1425 binop( opOR,
1426 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1427 assignNew(mce,ty,
1428 binop( opXOR,
1429 assignNew(mce,ty, binop(opADD, a_min, b_min)),
1430 assignNew(mce,ty, binop(opADD, a_max, b_max))
1431 )
sewardj95448072004-11-22 20:19:51 +00001432 )
sewardjd5204dc2004-12-31 01:16:11 +00001433 )
1434 );
1435 } else {
1436 // result = (qaa | qbb) | ((a_min - b_max) ^ (a_max + b_min))
1437 return
1438 assignNew(mce,ty,
1439 binop( opOR,
1440 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1441 assignNew(mce,ty,
1442 binop( opXOR,
1443 assignNew(mce,ty, binop(opSUB, a_min, b_max)),
1444 assignNew(mce,ty, binop(opSUB, a_max, b_min))
1445 )
1446 )
1447 )
1448 );
1449 }
1450
sewardj95448072004-11-22 20:19:51 +00001451}
1452
1453
1454/*------------------------------------------------------------*/
sewardjaaddbc22005-10-07 09:49:53 +00001455/*--- Scalar shifts. ---*/
1456/*------------------------------------------------------------*/
1457
1458/* Produce an interpretation for (aa << bb) (or >>s, >>u). The basic
1459 idea is to shift the definedness bits by the original shift amount.
1460 This introduces 0s ("defined") in new positions for left shifts and
1461 unsigned right shifts, and copies the top definedness bit for
1462 signed right shifts. So, conveniently, applying the original shift
1463 operator to the definedness bits for the left arg is exactly the
1464 right thing to do:
1465
1466 (qaa << bb)
1467
1468 However if the shift amount is undefined then the whole result
1469 is undefined. Hence need:
1470
1471 (qaa << bb) `UifU` PCast(qbb)
1472
1473 If the shift amount bb is a literal than qbb will say 'all defined'
1474 and the UifU and PCast will get folded out by post-instrumentation
1475 optimisation.
1476*/
1477static IRAtom* scalarShift ( MCEnv* mce,
1478 IRType ty,
1479 IROp original_op,
1480 IRAtom* qaa, IRAtom* qbb,
1481 IRAtom* aa, IRAtom* bb )
1482{
1483 tl_assert(isShadowAtom(mce,qaa));
1484 tl_assert(isShadowAtom(mce,qbb));
1485 tl_assert(isOriginalAtom(mce,aa));
1486 tl_assert(isOriginalAtom(mce,bb));
1487 tl_assert(sameKindedAtoms(qaa,aa));
1488 tl_assert(sameKindedAtoms(qbb,bb));
1489 return
1490 assignNew(
1491 mce, ty,
1492 mkUifU( mce, ty,
1493 assignNew(mce, ty, binop(original_op, qaa, bb)),
1494 mkPCastTo(mce, ty, qbb)
1495 )
1496 );
1497}
1498
1499
1500/*------------------------------------------------------------*/
1501/*--- Helpers for dealing with vector primops. ---*/
sewardj3245c912004-12-10 14:58:26 +00001502/*------------------------------------------------------------*/
1503
sewardja1d93302004-12-12 16:45:06 +00001504/* Vector pessimisation -- pessimise within each lane individually. */
1505
1506static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1507{
1508 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1509}
1510
1511static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1512{
1513 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1514}
1515
1516static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1517{
1518 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1519}
1520
1521static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1522{
1523 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1524}
1525
sewardjacd2e912005-01-13 19:17:06 +00001526static IRAtom* mkPCast32x2 ( MCEnv* mce, IRAtom* at )
1527{
1528 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ32x2, at));
1529}
1530
1531static IRAtom* mkPCast16x4 ( MCEnv* mce, IRAtom* at )
1532{
1533 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ16x4, at));
1534}
1535
1536static IRAtom* mkPCast8x8 ( MCEnv* mce, IRAtom* at )
1537{
1538 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ8x8, at));
1539}
1540
sewardja1d93302004-12-12 16:45:06 +00001541
sewardj3245c912004-12-10 14:58:26 +00001542/* Here's a simple scheme capable of handling ops derived from SSE1
1543 code and while only generating ops that can be efficiently
1544 implemented in SSE1. */
1545
1546/* All-lanes versions are straightforward:
1547
sewardj20d38f22005-02-07 23:50:18 +00001548 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj3245c912004-12-10 14:58:26 +00001549
1550 unary32Fx4(x,y) ==> PCast32x4(x#)
1551
1552 Lowest-lane-only versions are more complex:
1553
sewardj20d38f22005-02-07 23:50:18 +00001554 binary32F0x4(x,y) ==> SetV128lo32(
sewardj3245c912004-12-10 14:58:26 +00001555 x#,
sewardj20d38f22005-02-07 23:50:18 +00001556 PCast32(V128to32(UifUV128(x#,y#)))
sewardj3245c912004-12-10 14:58:26 +00001557 )
1558
1559 This is perhaps not so obvious. In particular, it's faster to
sewardj20d38f22005-02-07 23:50:18 +00001560 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj3245c912004-12-10 14:58:26 +00001561 obvious scheme of taking the bottom 32 bits of each operand
1562 and doing a 32-bit UifU. Basically since UifU is fast and
1563 chopping lanes off vector values is slow.
1564
1565 Finally:
1566
sewardj20d38f22005-02-07 23:50:18 +00001567 unary32F0x4(x) ==> SetV128lo32(
sewardj3245c912004-12-10 14:58:26 +00001568 x#,
sewardj20d38f22005-02-07 23:50:18 +00001569 PCast32(V128to32(x#))
sewardj3245c912004-12-10 14:58:26 +00001570 )
1571
1572 Where:
1573
1574 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1575 PCast32x4(v#) = CmpNEZ32x4(v#)
1576*/
1577
1578static
1579IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1580{
1581 IRAtom* at;
1582 tl_assert(isShadowAtom(mce, vatomX));
1583 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001584 at = mkUifUV128(mce, vatomX, vatomY);
sewardja1d93302004-12-12 16:45:06 +00001585 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
sewardj3245c912004-12-10 14:58:26 +00001586 return at;
1587}
1588
1589static
1590IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1591{
1592 IRAtom* at;
1593 tl_assert(isShadowAtom(mce, vatomX));
sewardja1d93302004-12-12 16:45:06 +00001594 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
sewardj3245c912004-12-10 14:58:26 +00001595 return at;
1596}
1597
1598static
1599IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1600{
1601 IRAtom* at;
1602 tl_assert(isShadowAtom(mce, vatomX));
1603 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001604 at = mkUifUV128(mce, vatomX, vatomY);
1605 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj3245c912004-12-10 14:58:26 +00001606 at = mkPCastTo(mce, Ity_I32, at);
sewardj20d38f22005-02-07 23:50:18 +00001607 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj3245c912004-12-10 14:58:26 +00001608 return at;
1609}
1610
1611static
1612IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1613{
1614 IRAtom* at;
1615 tl_assert(isShadowAtom(mce, vatomX));
sewardj20d38f22005-02-07 23:50:18 +00001616 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj3245c912004-12-10 14:58:26 +00001617 at = mkPCastTo(mce, Ity_I32, at);
sewardj20d38f22005-02-07 23:50:18 +00001618 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj3245c912004-12-10 14:58:26 +00001619 return at;
1620}
1621
sewardj0b070592004-12-10 21:44:22 +00001622/* --- ... and ... 64Fx2 versions of the same ... --- */
1623
1624static
1625IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1626{
1627 IRAtom* at;
1628 tl_assert(isShadowAtom(mce, vatomX));
1629 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001630 at = mkUifUV128(mce, vatomX, vatomY);
sewardja1d93302004-12-12 16:45:06 +00001631 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
sewardj0b070592004-12-10 21:44:22 +00001632 return at;
1633}
1634
1635static
1636IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1637{
1638 IRAtom* at;
1639 tl_assert(isShadowAtom(mce, vatomX));
sewardja1d93302004-12-12 16:45:06 +00001640 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
sewardj0b070592004-12-10 21:44:22 +00001641 return at;
1642}
1643
1644static
1645IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1646{
1647 IRAtom* at;
1648 tl_assert(isShadowAtom(mce, vatomX));
1649 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001650 at = mkUifUV128(mce, vatomX, vatomY);
1651 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj0b070592004-12-10 21:44:22 +00001652 at = mkPCastTo(mce, Ity_I64, at);
sewardj20d38f22005-02-07 23:50:18 +00001653 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj0b070592004-12-10 21:44:22 +00001654 return at;
1655}
1656
1657static
1658IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1659{
1660 IRAtom* at;
1661 tl_assert(isShadowAtom(mce, vatomX));
sewardj20d38f22005-02-07 23:50:18 +00001662 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj0b070592004-12-10 21:44:22 +00001663 at = mkPCastTo(mce, Ity_I64, at);
sewardj20d38f22005-02-07 23:50:18 +00001664 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj0b070592004-12-10 21:44:22 +00001665 return at;
1666}
1667
sewardja1d93302004-12-12 16:45:06 +00001668/* --- --- Vector saturated narrowing --- --- */
1669
1670/* This is quite subtle. What to do is simple:
1671
1672 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1673
1674 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1675
1676 Why this is right is not so simple. Consider a lane in the args,
1677 vatom1 or 2, doesn't matter.
1678
1679 After the PCast, that lane is all 0s (defined) or all
1680 1s(undefined).
1681
1682 Both signed and unsigned saturating narrowing of all 0s produces
1683 all 0s, which is what we want.
1684
1685 The all-1s case is more complex. Unsigned narrowing interprets an
1686 all-1s input as the largest unsigned integer, and so produces all
1687 1s as a result since that is the largest unsigned value at the
1688 smaller width.
1689
1690 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1691 to -1, so we still wind up with all 1s at the smaller width.
1692
1693 So: In short, pessimise the args, then apply the original narrowing
1694 op.
1695*/
1696static
sewardj20d38f22005-02-07 23:50:18 +00001697IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardja1d93302004-12-12 16:45:06 +00001698 IRAtom* vatom1, IRAtom* vatom2)
1699{
1700 IRAtom *at1, *at2, *at3;
1701 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1702 switch (narrow_op) {
1703 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
sewardj43d60752005-11-10 18:13:01 +00001704 case Iop_QNarrow32Ux4: pcast = mkPCast32x4; break;
sewardja1d93302004-12-12 16:45:06 +00001705 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1706 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardj20d38f22005-02-07 23:50:18 +00001707 default: VG_(tool_panic)("vectorNarrowV128");
sewardja1d93302004-12-12 16:45:06 +00001708 }
1709 tl_assert(isShadowAtom(mce,vatom1));
1710 tl_assert(isShadowAtom(mce,vatom2));
1711 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1712 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1713 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1714 return at3;
1715}
1716
sewardjacd2e912005-01-13 19:17:06 +00001717static
1718IRAtom* vectorNarrow64 ( MCEnv* mce, IROp narrow_op,
1719 IRAtom* vatom1, IRAtom* vatom2)
1720{
1721 IRAtom *at1, *at2, *at3;
1722 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1723 switch (narrow_op) {
1724 case Iop_QNarrow32Sx2: pcast = mkPCast32x2; break;
1725 case Iop_QNarrow16Sx4: pcast = mkPCast16x4; break;
1726 case Iop_QNarrow16Ux4: pcast = mkPCast16x4; break;
1727 default: VG_(tool_panic)("vectorNarrow64");
1728 }
1729 tl_assert(isShadowAtom(mce,vatom1));
1730 tl_assert(isShadowAtom(mce,vatom2));
1731 at1 = assignNew(mce, Ity_I64, pcast(mce, vatom1));
1732 at2 = assignNew(mce, Ity_I64, pcast(mce, vatom2));
1733 at3 = assignNew(mce, Ity_I64, binop(narrow_op, at1, at2));
1734 return at3;
1735}
1736
sewardja1d93302004-12-12 16:45:06 +00001737
1738/* --- --- Vector integer arithmetic --- --- */
1739
1740/* Simple ... UifU the args and per-lane pessimise the results. */
sewardjacd2e912005-01-13 19:17:06 +00001741
sewardj20d38f22005-02-07 23:50:18 +00001742/* --- V128-bit versions --- */
sewardjacd2e912005-01-13 19:17:06 +00001743
sewardja1d93302004-12-12 16:45:06 +00001744static
1745IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1746{
1747 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001748 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001749 at = mkPCast8x16(mce, at);
1750 return at;
1751}
1752
1753static
1754IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1755{
1756 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001757 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001758 at = mkPCast16x8(mce, at);
1759 return at;
1760}
1761
1762static
1763IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1764{
1765 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001766 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001767 at = mkPCast32x4(mce, at);
1768 return at;
1769}
1770
1771static
1772IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1773{
1774 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001775 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001776 at = mkPCast64x2(mce, at);
1777 return at;
1778}
sewardj3245c912004-12-10 14:58:26 +00001779
sewardjacd2e912005-01-13 19:17:06 +00001780/* --- 64-bit versions --- */
1781
1782static
1783IRAtom* binary8Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1784{
1785 IRAtom* at;
1786 at = mkUifU64(mce, vatom1, vatom2);
1787 at = mkPCast8x8(mce, at);
1788 return at;
1789}
1790
1791static
1792IRAtom* binary16Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1793{
1794 IRAtom* at;
1795 at = mkUifU64(mce, vatom1, vatom2);
1796 at = mkPCast16x4(mce, at);
1797 return at;
1798}
1799
1800static
1801IRAtom* binary32Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1802{
1803 IRAtom* at;
1804 at = mkUifU64(mce, vatom1, vatom2);
1805 at = mkPCast32x2(mce, at);
1806 return at;
1807}
1808
sewardj3245c912004-12-10 14:58:26 +00001809
1810/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00001811/*--- Generate shadow values from all kinds of IRExprs. ---*/
1812/*------------------------------------------------------------*/
1813
1814static
sewardje91cea72006-02-08 19:32:02 +00001815IRAtom* expr2vbits_Qop ( MCEnv* mce,
1816 IROp op,
1817 IRAtom* atom1, IRAtom* atom2,
1818 IRAtom* atom3, IRAtom* atom4 )
1819{
1820 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1821 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1822 IRAtom* vatom3 = expr2vbits( mce, atom3 );
1823 IRAtom* vatom4 = expr2vbits( mce, atom4 );
1824
1825 tl_assert(isOriginalAtom(mce,atom1));
1826 tl_assert(isOriginalAtom(mce,atom2));
1827 tl_assert(isOriginalAtom(mce,atom3));
1828 tl_assert(isOriginalAtom(mce,atom4));
1829 tl_assert(isShadowAtom(mce,vatom1));
1830 tl_assert(isShadowAtom(mce,vatom2));
1831 tl_assert(isShadowAtom(mce,vatom3));
1832 tl_assert(isShadowAtom(mce,vatom4));
1833 tl_assert(sameKindedAtoms(atom1,vatom1));
1834 tl_assert(sameKindedAtoms(atom2,vatom2));
1835 tl_assert(sameKindedAtoms(atom3,vatom3));
1836 tl_assert(sameKindedAtoms(atom4,vatom4));
1837 switch (op) {
1838 case Iop_MAddF64:
1839 case Iop_MAddF64r32:
1840 case Iop_MSubF64:
1841 case Iop_MSubF64r32:
1842 /* I32(rm) x F64 x F64 x F64 -> F64 */
1843 return mkLazy4(mce, Ity_I64, vatom1, vatom2, vatom3, vatom4);
1844 default:
1845 ppIROp(op);
1846 VG_(tool_panic)("memcheck:expr2vbits_Qop");
1847 }
1848}
1849
1850
1851static
sewardjed69fdb2006-02-03 16:12:27 +00001852IRAtom* expr2vbits_Triop ( MCEnv* mce,
1853 IROp op,
1854 IRAtom* atom1, IRAtom* atom2, IRAtom* atom3 )
1855{
sewardjed69fdb2006-02-03 16:12:27 +00001856 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1857 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1858 IRAtom* vatom3 = expr2vbits( mce, atom3 );
1859
1860 tl_assert(isOriginalAtom(mce,atom1));
1861 tl_assert(isOriginalAtom(mce,atom2));
1862 tl_assert(isOriginalAtom(mce,atom3));
1863 tl_assert(isShadowAtom(mce,vatom1));
1864 tl_assert(isShadowAtom(mce,vatom2));
1865 tl_assert(isShadowAtom(mce,vatom3));
1866 tl_assert(sameKindedAtoms(atom1,vatom1));
1867 tl_assert(sameKindedAtoms(atom2,vatom2));
1868 tl_assert(sameKindedAtoms(atom3,vatom3));
1869 switch (op) {
1870 case Iop_AddF64:
1871 case Iop_AddF64r32:
1872 case Iop_SubF64:
1873 case Iop_SubF64r32:
1874 case Iop_MulF64:
1875 case Iop_MulF64r32:
1876 case Iop_DivF64:
1877 case Iop_DivF64r32:
sewardj22ac5f42006-02-03 22:55:04 +00001878 case Iop_ScaleF64:
1879 case Iop_Yl2xF64:
1880 case Iop_Yl2xp1F64:
1881 case Iop_AtanF64:
sewardjd6075eb2006-02-04 15:25:23 +00001882 case Iop_PRemF64:
1883 case Iop_PRem1F64:
sewardj22ac5f42006-02-03 22:55:04 +00001884 /* I32(rm) x F64 x F64 -> F64 */
sewardjed69fdb2006-02-03 16:12:27 +00001885 return mkLazy3(mce, Ity_I64, vatom1, vatom2, vatom3);
sewardjd6075eb2006-02-04 15:25:23 +00001886 case Iop_PRemC3210F64:
1887 case Iop_PRem1C3210F64:
1888 /* I32(rm) x F64 x F64 -> I32 */
1889 return mkLazy3(mce, Ity_I32, vatom1, vatom2, vatom3);
sewardjed69fdb2006-02-03 16:12:27 +00001890 default:
1891 ppIROp(op);
1892 VG_(tool_panic)("memcheck:expr2vbits_Triop");
1893 }
1894}
1895
1896
1897static
sewardj95448072004-11-22 20:19:51 +00001898IRAtom* expr2vbits_Binop ( MCEnv* mce,
1899 IROp op,
1900 IRAtom* atom1, IRAtom* atom2 )
1901{
1902 IRType and_or_ty;
1903 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1904 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1905 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1906
1907 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1908 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1909
1910 tl_assert(isOriginalAtom(mce,atom1));
1911 tl_assert(isOriginalAtom(mce,atom2));
1912 tl_assert(isShadowAtom(mce,vatom1));
1913 tl_assert(isShadowAtom(mce,vatom2));
1914 tl_assert(sameKindedAtoms(atom1,vatom1));
1915 tl_assert(sameKindedAtoms(atom2,vatom2));
1916 switch (op) {
1917
sewardjacd2e912005-01-13 19:17:06 +00001918 /* 64-bit SIMD */
1919
1920 case Iop_ShrN16x4:
1921 case Iop_ShrN32x2:
sewardj03809ae2006-12-27 01:16:58 +00001922 case Iop_SarN8x8:
sewardjacd2e912005-01-13 19:17:06 +00001923 case Iop_SarN16x4:
1924 case Iop_SarN32x2:
1925 case Iop_ShlN16x4:
1926 case Iop_ShlN32x2:
sewardj114a9172008-02-09 01:49:32 +00001927 case Iop_ShlN8x8:
sewardjacd2e912005-01-13 19:17:06 +00001928 /* Same scheme as with all other shifts. */
1929 complainIfUndefined(mce, atom2);
1930 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1931
1932 case Iop_QNarrow32Sx2:
1933 case Iop_QNarrow16Sx4:
1934 case Iop_QNarrow16Ux4:
1935 return vectorNarrow64(mce, op, vatom1, vatom2);
1936
1937 case Iop_Min8Ux8:
1938 case Iop_Max8Ux8:
1939 case Iop_Avg8Ux8:
1940 case Iop_QSub8Sx8:
1941 case Iop_QSub8Ux8:
1942 case Iop_Sub8x8:
1943 case Iop_CmpGT8Sx8:
1944 case Iop_CmpEQ8x8:
1945 case Iop_QAdd8Sx8:
1946 case Iop_QAdd8Ux8:
1947 case Iop_Add8x8:
1948 return binary8Ix8(mce, vatom1, vatom2);
1949
1950 case Iop_Min16Sx4:
1951 case Iop_Max16Sx4:
1952 case Iop_Avg16Ux4:
1953 case Iop_QSub16Ux4:
1954 case Iop_QSub16Sx4:
1955 case Iop_Sub16x4:
1956 case Iop_Mul16x4:
1957 case Iop_MulHi16Sx4:
1958 case Iop_MulHi16Ux4:
1959 case Iop_CmpGT16Sx4:
1960 case Iop_CmpEQ16x4:
1961 case Iop_QAdd16Sx4:
1962 case Iop_QAdd16Ux4:
1963 case Iop_Add16x4:
1964 return binary16Ix4(mce, vatom1, vatom2);
1965
1966 case Iop_Sub32x2:
sewardj114a9172008-02-09 01:49:32 +00001967 case Iop_Mul32x2:
sewardjacd2e912005-01-13 19:17:06 +00001968 case Iop_CmpGT32Sx2:
1969 case Iop_CmpEQ32x2:
1970 case Iop_Add32x2:
1971 return binary32Ix2(mce, vatom1, vatom2);
1972
1973 /* 64-bit data-steering */
1974 case Iop_InterleaveLO32x2:
1975 case Iop_InterleaveLO16x4:
1976 case Iop_InterleaveLO8x8:
1977 case Iop_InterleaveHI32x2:
1978 case Iop_InterleaveHI16x4:
1979 case Iop_InterleaveHI8x8:
sewardj114a9172008-02-09 01:49:32 +00001980 case Iop_CatOddLanes16x4:
1981 case Iop_CatEvenLanes16x4:
sewardjacd2e912005-01-13 19:17:06 +00001982 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
1983
sewardj114a9172008-02-09 01:49:32 +00001984 /* Perm8x8: rearrange values in left arg using steering values
1985 from right arg. So rearrange the vbits in the same way but
1986 pessimise wrt steering values. */
1987 case Iop_Perm8x8:
1988 return mkUifU64(
1989 mce,
1990 assignNew(mce, Ity_I64, binop(op, vatom1, atom2)),
1991 mkPCast8x8(mce, vatom2)
1992 );
1993
sewardj20d38f22005-02-07 23:50:18 +00001994 /* V128-bit SIMD */
sewardj0b070592004-12-10 21:44:22 +00001995
sewardja1d93302004-12-12 16:45:06 +00001996 case Iop_ShrN16x8:
1997 case Iop_ShrN32x4:
1998 case Iop_ShrN64x2:
1999 case Iop_SarN16x8:
2000 case Iop_SarN32x4:
2001 case Iop_ShlN16x8:
2002 case Iop_ShlN32x4:
2003 case Iop_ShlN64x2:
sewardj620eb5b2005-10-22 12:50:43 +00002004 case Iop_ShlN8x16:
2005 case Iop_SarN8x16:
2006 /* Same scheme as with all other shifts. Note: 22 Oct 05:
2007 this is wrong now, scalar shifts are done properly lazily.
2008 Vector shifts should be fixed too. */
sewardja1d93302004-12-12 16:45:06 +00002009 complainIfUndefined(mce, atom2);
2010 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
2011
sewardjcbf8be72005-11-10 18:34:41 +00002012 /* V x V shifts/rotates are done using the standard lazy scheme. */
sewardj43d60752005-11-10 18:13:01 +00002013 case Iop_Shl8x16:
2014 case Iop_Shr8x16:
2015 case Iop_Sar8x16:
sewardjcbf8be72005-11-10 18:34:41 +00002016 case Iop_Rol8x16:
sewardj43d60752005-11-10 18:13:01 +00002017 return mkUifUV128(mce,
2018 assignNew(mce, Ity_V128, binop(op, vatom1, atom2)),
2019 mkPCast8x16(mce,vatom2)
2020 );
2021
2022 case Iop_Shl16x8:
2023 case Iop_Shr16x8:
2024 case Iop_Sar16x8:
sewardjcbf8be72005-11-10 18:34:41 +00002025 case Iop_Rol16x8:
sewardj43d60752005-11-10 18:13:01 +00002026 return mkUifUV128(mce,
2027 assignNew(mce, Ity_V128, binop(op, vatom1, atom2)),
2028 mkPCast16x8(mce,vatom2)
2029 );
2030
2031 case Iop_Shl32x4:
2032 case Iop_Shr32x4:
2033 case Iop_Sar32x4:
sewardjcbf8be72005-11-10 18:34:41 +00002034 case Iop_Rol32x4:
sewardj43d60752005-11-10 18:13:01 +00002035 return mkUifUV128(mce,
2036 assignNew(mce, Ity_V128, binop(op, vatom1, atom2)),
2037 mkPCast32x4(mce,vatom2)
2038 );
2039
sewardja1d93302004-12-12 16:45:06 +00002040 case Iop_QSub8Ux16:
2041 case Iop_QSub8Sx16:
2042 case Iop_Sub8x16:
2043 case Iop_Min8Ux16:
sewardj43d60752005-11-10 18:13:01 +00002044 case Iop_Min8Sx16:
sewardja1d93302004-12-12 16:45:06 +00002045 case Iop_Max8Ux16:
sewardj43d60752005-11-10 18:13:01 +00002046 case Iop_Max8Sx16:
sewardja1d93302004-12-12 16:45:06 +00002047 case Iop_CmpGT8Sx16:
sewardj43d60752005-11-10 18:13:01 +00002048 case Iop_CmpGT8Ux16:
sewardja1d93302004-12-12 16:45:06 +00002049 case Iop_CmpEQ8x16:
2050 case Iop_Avg8Ux16:
sewardj43d60752005-11-10 18:13:01 +00002051 case Iop_Avg8Sx16:
sewardja1d93302004-12-12 16:45:06 +00002052 case Iop_QAdd8Ux16:
2053 case Iop_QAdd8Sx16:
2054 case Iop_Add8x16:
2055 return binary8Ix16(mce, vatom1, vatom2);
2056
2057 case Iop_QSub16Ux8:
2058 case Iop_QSub16Sx8:
2059 case Iop_Sub16x8:
2060 case Iop_Mul16x8:
2061 case Iop_MulHi16Sx8:
2062 case Iop_MulHi16Ux8:
2063 case Iop_Min16Sx8:
sewardj43d60752005-11-10 18:13:01 +00002064 case Iop_Min16Ux8:
sewardja1d93302004-12-12 16:45:06 +00002065 case Iop_Max16Sx8:
sewardj43d60752005-11-10 18:13:01 +00002066 case Iop_Max16Ux8:
sewardja1d93302004-12-12 16:45:06 +00002067 case Iop_CmpGT16Sx8:
sewardj43d60752005-11-10 18:13:01 +00002068 case Iop_CmpGT16Ux8:
sewardja1d93302004-12-12 16:45:06 +00002069 case Iop_CmpEQ16x8:
2070 case Iop_Avg16Ux8:
sewardj43d60752005-11-10 18:13:01 +00002071 case Iop_Avg16Sx8:
sewardja1d93302004-12-12 16:45:06 +00002072 case Iop_QAdd16Ux8:
2073 case Iop_QAdd16Sx8:
2074 case Iop_Add16x8:
2075 return binary16Ix8(mce, vatom1, vatom2);
2076
2077 case Iop_Sub32x4:
2078 case Iop_CmpGT32Sx4:
sewardj43d60752005-11-10 18:13:01 +00002079 case Iop_CmpGT32Ux4:
sewardja1d93302004-12-12 16:45:06 +00002080 case Iop_CmpEQ32x4:
sewardj43d60752005-11-10 18:13:01 +00002081 case Iop_QAdd32Sx4:
2082 case Iop_QAdd32Ux4:
2083 case Iop_QSub32Sx4:
2084 case Iop_QSub32Ux4:
2085 case Iop_Avg32Ux4:
2086 case Iop_Avg32Sx4:
sewardja1d93302004-12-12 16:45:06 +00002087 case Iop_Add32x4:
sewardj43d60752005-11-10 18:13:01 +00002088 case Iop_Max32Ux4:
2089 case Iop_Max32Sx4:
2090 case Iop_Min32Ux4:
2091 case Iop_Min32Sx4:
sewardja1d93302004-12-12 16:45:06 +00002092 return binary32Ix4(mce, vatom1, vatom2);
2093
2094 case Iop_Sub64x2:
2095 case Iop_Add64x2:
2096 return binary64Ix2(mce, vatom1, vatom2);
2097
2098 case Iop_QNarrow32Sx4:
sewardj43d60752005-11-10 18:13:01 +00002099 case Iop_QNarrow32Ux4:
sewardja1d93302004-12-12 16:45:06 +00002100 case Iop_QNarrow16Sx8:
2101 case Iop_QNarrow16Ux8:
sewardj20d38f22005-02-07 23:50:18 +00002102 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00002103
sewardj0b070592004-12-10 21:44:22 +00002104 case Iop_Sub64Fx2:
2105 case Iop_Mul64Fx2:
2106 case Iop_Min64Fx2:
2107 case Iop_Max64Fx2:
2108 case Iop_Div64Fx2:
2109 case Iop_CmpLT64Fx2:
2110 case Iop_CmpLE64Fx2:
2111 case Iop_CmpEQ64Fx2:
sewardj545663e2005-11-05 01:55:04 +00002112 case Iop_CmpUN64Fx2:
sewardj0b070592004-12-10 21:44:22 +00002113 case Iop_Add64Fx2:
2114 return binary64Fx2(mce, vatom1, vatom2);
2115
2116 case Iop_Sub64F0x2:
2117 case Iop_Mul64F0x2:
2118 case Iop_Min64F0x2:
2119 case Iop_Max64F0x2:
2120 case Iop_Div64F0x2:
2121 case Iop_CmpLT64F0x2:
2122 case Iop_CmpLE64F0x2:
2123 case Iop_CmpEQ64F0x2:
sewardj545663e2005-11-05 01:55:04 +00002124 case Iop_CmpUN64F0x2:
sewardj0b070592004-12-10 21:44:22 +00002125 case Iop_Add64F0x2:
2126 return binary64F0x2(mce, vatom1, vatom2);
2127
sewardj170ee212004-12-10 18:57:51 +00002128 case Iop_Sub32Fx4:
2129 case Iop_Mul32Fx4:
2130 case Iop_Min32Fx4:
2131 case Iop_Max32Fx4:
2132 case Iop_Div32Fx4:
2133 case Iop_CmpLT32Fx4:
2134 case Iop_CmpLE32Fx4:
2135 case Iop_CmpEQ32Fx4:
sewardj545663e2005-11-05 01:55:04 +00002136 case Iop_CmpUN32Fx4:
cerione78ba2a2005-11-14 03:00:35 +00002137 case Iop_CmpGT32Fx4:
2138 case Iop_CmpGE32Fx4:
sewardj3245c912004-12-10 14:58:26 +00002139 case Iop_Add32Fx4:
2140 return binary32Fx4(mce, vatom1, vatom2);
2141
sewardj170ee212004-12-10 18:57:51 +00002142 case Iop_Sub32F0x4:
2143 case Iop_Mul32F0x4:
2144 case Iop_Min32F0x4:
2145 case Iop_Max32F0x4:
2146 case Iop_Div32F0x4:
2147 case Iop_CmpLT32F0x4:
2148 case Iop_CmpLE32F0x4:
2149 case Iop_CmpEQ32F0x4:
sewardj545663e2005-11-05 01:55:04 +00002150 case Iop_CmpUN32F0x4:
sewardj170ee212004-12-10 18:57:51 +00002151 case Iop_Add32F0x4:
2152 return binary32F0x4(mce, vatom1, vatom2);
2153
sewardj20d38f22005-02-07 23:50:18 +00002154 /* V128-bit data-steering */
2155 case Iop_SetV128lo32:
2156 case Iop_SetV128lo64:
2157 case Iop_64HLtoV128:
sewardja1d93302004-12-12 16:45:06 +00002158 case Iop_InterleaveLO64x2:
2159 case Iop_InterleaveLO32x4:
2160 case Iop_InterleaveLO16x8:
2161 case Iop_InterleaveLO8x16:
2162 case Iop_InterleaveHI64x2:
2163 case Iop_InterleaveHI32x4:
2164 case Iop_InterleaveHI16x8:
2165 case Iop_InterleaveHI8x16:
sewardj170ee212004-12-10 18:57:51 +00002166 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
sewardj620eb5b2005-10-22 12:50:43 +00002167
2168 /* Perm8x16: rearrange values in left arg using steering values
2169 from right arg. So rearrange the vbits in the same way but
2170 pessimise wrt steering values. */
2171 case Iop_Perm8x16:
2172 return mkUifUV128(
2173 mce,
2174 assignNew(mce, Ity_V128, binop(op, vatom1, atom2)),
2175 mkPCast8x16(mce, vatom2)
2176 );
sewardj170ee212004-12-10 18:57:51 +00002177
sewardj43d60752005-11-10 18:13:01 +00002178 /* These two take the lower half of each 16-bit lane, sign/zero
2179 extend it to 32, and multiply together, producing a 32x4
2180 result (and implicitly ignoring half the operand bits). So
2181 treat it as a bunch of independent 16x8 operations, but then
2182 do 32-bit shifts left-right to copy the lower half results
2183 (which are all 0s or all 1s due to PCasting in binary16Ix8)
2184 into the upper half of each result lane. */
2185 case Iop_MullEven16Ux8:
2186 case Iop_MullEven16Sx8: {
2187 IRAtom* at;
2188 at = binary16Ix8(mce,vatom1,vatom2);
2189 at = assignNew(mce, Ity_V128, binop(Iop_ShlN32x4, at, mkU8(16)));
2190 at = assignNew(mce, Ity_V128, binop(Iop_SarN32x4, at, mkU8(16)));
2191 return at;
2192 }
2193
2194 /* Same deal as Iop_MullEven16{S,U}x8 */
2195 case Iop_MullEven8Ux16:
2196 case Iop_MullEven8Sx16: {
2197 IRAtom* at;
2198 at = binary8Ix16(mce,vatom1,vatom2);
2199 at = assignNew(mce, Ity_V128, binop(Iop_ShlN16x8, at, mkU8(8)));
2200 at = assignNew(mce, Ity_V128, binop(Iop_SarN16x8, at, mkU8(8)));
2201 return at;
2202 }
2203
2204 /* narrow 2xV128 into 1xV128, hi half from left arg, in a 2 x
2205 32x4 -> 16x8 laneage, discarding the upper half of each lane.
2206 Simply apply same op to the V bits, since this really no more
2207 than a data steering operation. */
sewardjcbf8be72005-11-10 18:34:41 +00002208 case Iop_Narrow32x4:
2209 case Iop_Narrow16x8:
sewardj43d60752005-11-10 18:13:01 +00002210 return assignNew(mce, Ity_V128,
2211 binop(op, vatom1, vatom2));
2212
2213 case Iop_ShrV128:
2214 case Iop_ShlV128:
2215 /* Same scheme as with all other shifts. Note: 10 Nov 05:
2216 this is wrong now, scalar shifts are done properly lazily.
2217 Vector shifts should be fixed too. */
2218 complainIfUndefined(mce, atom2);
2219 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
2220
2221
sewardj69a13322005-04-23 01:14:51 +00002222 /* I128-bit data-steering */
2223 case Iop_64HLto128:
2224 return assignNew(mce, Ity_I128, binop(op, vatom1, vatom2));
2225
sewardj3245c912004-12-10 14:58:26 +00002226 /* Scalar floating point */
2227
sewardjed69fdb2006-02-03 16:12:27 +00002228 case Iop_RoundF64toInt:
2229 case Iop_RoundF64toF32:
sewardj95448072004-11-22 20:19:51 +00002230 case Iop_F64toI64:
sewardje9e16d32004-12-10 13:17:55 +00002231 case Iop_I64toF64:
sewardj22ac5f42006-02-03 22:55:04 +00002232 case Iop_SinF64:
2233 case Iop_CosF64:
2234 case Iop_TanF64:
2235 case Iop_2xm1F64:
2236 case Iop_SqrtF64:
2237 /* I32(rm) x I64/F64 -> I64/F64 */
sewardj95448072004-11-22 20:19:51 +00002238 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
2239
sewardj95448072004-11-22 20:19:51 +00002240 case Iop_F64toI32:
sewardje9e16d32004-12-10 13:17:55 +00002241 case Iop_F64toF32:
sewardj95448072004-11-22 20:19:51 +00002242 /* First arg is I32 (rounding mode), second is F64 (data). */
2243 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
2244
2245 case Iop_F64toI16:
2246 /* First arg is I32 (rounding mode), second is F64 (data). */
2247 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
2248
sewardj95448072004-11-22 20:19:51 +00002249 case Iop_CmpF64:
2250 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
2251
2252 /* non-FP after here */
2253
2254 case Iop_DivModU64to32:
2255 case Iop_DivModS64to32:
2256 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
2257
sewardj69a13322005-04-23 01:14:51 +00002258 case Iop_DivModU128to64:
2259 case Iop_DivModS128to64:
2260 return mkLazy2(mce, Ity_I128, vatom1, vatom2);
2261
sewardj95448072004-11-22 20:19:51 +00002262 case Iop_16HLto32:
sewardj170ee212004-12-10 18:57:51 +00002263 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardj95448072004-11-22 20:19:51 +00002264 case Iop_32HLto64:
sewardj170ee212004-12-10 18:57:51 +00002265 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardj95448072004-11-22 20:19:51 +00002266
sewardj6cf40ff2005-04-20 22:31:26 +00002267 case Iop_MullS64:
2268 case Iop_MullU64: {
2269 IRAtom* vLo64 = mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
2270 IRAtom* vHi64 = mkPCastTo(mce, Ity_I64, vLo64);
2271 return assignNew(mce, Ity_I128, binop(Iop_64HLto128, vHi64, vLo64));
2272 }
2273
sewardj95448072004-11-22 20:19:51 +00002274 case Iop_MullS32:
2275 case Iop_MullU32: {
2276 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
2277 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
2278 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
2279 }
2280
2281 case Iop_MullS16:
2282 case Iop_MullU16: {
2283 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
2284 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
2285 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
2286 }
2287
2288 case Iop_MullS8:
2289 case Iop_MullU8: {
2290 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
2291 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
2292 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
2293 }
2294
cerion9e591082005-06-23 15:28:34 +00002295 case Iop_DivS32:
2296 case Iop_DivU32:
2297 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
2298
sewardjb00944a2005-12-23 12:47:16 +00002299 case Iop_DivS64:
2300 case Iop_DivU64:
2301 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
2302
sewardj95448072004-11-22 20:19:51 +00002303 case Iop_Add32:
sewardjd5204dc2004-12-31 01:16:11 +00002304 if (mce->bogusLiterals)
2305 return expensiveAddSub(mce,True,Ity_I32,
2306 vatom1,vatom2, atom1,atom2);
2307 else
2308 goto cheap_AddSub32;
sewardj95448072004-11-22 20:19:51 +00002309 case Iop_Sub32:
sewardjd5204dc2004-12-31 01:16:11 +00002310 if (mce->bogusLiterals)
2311 return expensiveAddSub(mce,False,Ity_I32,
2312 vatom1,vatom2, atom1,atom2);
2313 else
2314 goto cheap_AddSub32;
2315
2316 cheap_AddSub32:
sewardj95448072004-11-22 20:19:51 +00002317 case Iop_Mul32:
sewardj992dff92005-10-07 11:08:55 +00002318 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
2319
sewardj463b3d92005-07-18 11:41:15 +00002320 case Iop_CmpORD32S:
2321 case Iop_CmpORD32U:
sewardj1bc82102005-12-23 00:16:24 +00002322 case Iop_CmpORD64S:
2323 case Iop_CmpORD64U:
2324 return doCmpORD(mce, op, vatom1,vatom2, atom1,atom2);
sewardj95448072004-11-22 20:19:51 +00002325
sewardj681be302005-01-15 20:43:58 +00002326 case Iop_Add64:
tomd9774d72005-06-27 08:11:01 +00002327 if (mce->bogusLiterals)
2328 return expensiveAddSub(mce,True,Ity_I64,
2329 vatom1,vatom2, atom1,atom2);
2330 else
2331 goto cheap_AddSub64;
sewardj681be302005-01-15 20:43:58 +00002332 case Iop_Sub64:
tomd9774d72005-06-27 08:11:01 +00002333 if (mce->bogusLiterals)
2334 return expensiveAddSub(mce,False,Ity_I64,
2335 vatom1,vatom2, atom1,atom2);
2336 else
2337 goto cheap_AddSub64;
2338
2339 cheap_AddSub64:
2340 case Iop_Mul64:
sewardj681be302005-01-15 20:43:58 +00002341 return mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
2342
sewardj95448072004-11-22 20:19:51 +00002343 case Iop_Mul16:
2344 case Iop_Add16:
2345 case Iop_Sub16:
2346 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
2347
2348 case Iop_Sub8:
2349 case Iop_Add8:
2350 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
2351
sewardj69a13322005-04-23 01:14:51 +00002352 case Iop_CmpEQ64:
sewardje6f8af42005-07-06 18:48:59 +00002353 case Iop_CmpNE64:
sewardj69a13322005-04-23 01:14:51 +00002354 if (mce->bogusLiterals)
2355 return expensiveCmpEQorNE(mce,Ity_I64, vatom1,vatom2, atom1,atom2 );
2356 else
2357 goto cheap_cmp64;
2358 cheap_cmp64:
tomcd986332005-04-26 07:44:48 +00002359 case Iop_CmpLE64S: case Iop_CmpLE64U:
2360 case Iop_CmpLT64U: case Iop_CmpLT64S:
sewardj69a13322005-04-23 01:14:51 +00002361 return mkPCastTo(mce, Ity_I1, mkUifU64(mce, vatom1,vatom2));
2362
sewardjd5204dc2004-12-31 01:16:11 +00002363 case Iop_CmpEQ32:
sewardje6f8af42005-07-06 18:48:59 +00002364 case Iop_CmpNE32:
sewardjd5204dc2004-12-31 01:16:11 +00002365 if (mce->bogusLiterals)
2366 return expensiveCmpEQorNE(mce,Ity_I32, vatom1,vatom2, atom1,atom2 );
2367 else
2368 goto cheap_cmp32;
sewardjd5204dc2004-12-31 01:16:11 +00002369 cheap_cmp32:
sewardj95448072004-11-22 20:19:51 +00002370 case Iop_CmpLE32S: case Iop_CmpLE32U:
2371 case Iop_CmpLT32U: case Iop_CmpLT32S:
sewardj95448072004-11-22 20:19:51 +00002372 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
2373
2374 case Iop_CmpEQ16: case Iop_CmpNE16:
2375 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
2376
2377 case Iop_CmpEQ8: case Iop_CmpNE8:
2378 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
2379
sewardjaaddbc22005-10-07 09:49:53 +00002380 case Iop_Shl64: case Iop_Shr64: case Iop_Sar64:
2381 return scalarShift( mce, Ity_I64, op, vatom1,vatom2, atom1,atom2 );
2382
sewardj95448072004-11-22 20:19:51 +00002383 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
sewardjaaddbc22005-10-07 09:49:53 +00002384 return scalarShift( mce, Ity_I32, op, vatom1,vatom2, atom1,atom2 );
sewardj95448072004-11-22 20:19:51 +00002385
sewardjdb67f5f2004-12-14 01:15:31 +00002386 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjaaddbc22005-10-07 09:49:53 +00002387 return scalarShift( mce, Ity_I16, op, vatom1,vatom2, atom1,atom2 );
sewardj95448072004-11-22 20:19:51 +00002388
2389 case Iop_Shl8: case Iop_Shr8:
sewardjaaddbc22005-10-07 09:49:53 +00002390 return scalarShift( mce, Ity_I8, op, vatom1,vatom2, atom1,atom2 );
sewardj95448072004-11-22 20:19:51 +00002391
sewardj20d38f22005-02-07 23:50:18 +00002392 case Iop_AndV128:
2393 uifu = mkUifUV128; difd = mkDifDV128;
2394 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj7010f6e2004-12-10 13:35:22 +00002395 case Iop_And64:
2396 uifu = mkUifU64; difd = mkDifD64;
2397 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardj95448072004-11-22 20:19:51 +00002398 case Iop_And32:
2399 uifu = mkUifU32; difd = mkDifD32;
2400 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
2401 case Iop_And16:
2402 uifu = mkUifU16; difd = mkDifD16;
2403 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
2404 case Iop_And8:
2405 uifu = mkUifU8; difd = mkDifD8;
2406 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
2407
sewardj20d38f22005-02-07 23:50:18 +00002408 case Iop_OrV128:
2409 uifu = mkUifUV128; difd = mkDifDV128;
2410 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj7010f6e2004-12-10 13:35:22 +00002411 case Iop_Or64:
2412 uifu = mkUifU64; difd = mkDifD64;
2413 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardj95448072004-11-22 20:19:51 +00002414 case Iop_Or32:
2415 uifu = mkUifU32; difd = mkDifD32;
2416 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
2417 case Iop_Or16:
2418 uifu = mkUifU16; difd = mkDifD16;
2419 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
2420 case Iop_Or8:
2421 uifu = mkUifU8; difd = mkDifD8;
2422 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
2423
2424 do_And_Or:
2425 return
2426 assignNew(
2427 mce,
2428 and_or_ty,
2429 difd(mce, uifu(mce, vatom1, vatom2),
2430 difd(mce, improve(mce, atom1, vatom1),
2431 improve(mce, atom2, vatom2) ) ) );
2432
2433 case Iop_Xor8:
2434 return mkUifU8(mce, vatom1, vatom2);
2435 case Iop_Xor16:
2436 return mkUifU16(mce, vatom1, vatom2);
2437 case Iop_Xor32:
2438 return mkUifU32(mce, vatom1, vatom2);
sewardj7010f6e2004-12-10 13:35:22 +00002439 case Iop_Xor64:
2440 return mkUifU64(mce, vatom1, vatom2);
sewardj20d38f22005-02-07 23:50:18 +00002441 case Iop_XorV128:
2442 return mkUifUV128(mce, vatom1, vatom2);
njn25e49d8e72002-09-23 09:36:25 +00002443
2444 default:
sewardj95448072004-11-22 20:19:51 +00002445 ppIROp(op);
2446 VG_(tool_panic)("memcheck:expr2vbits_Binop");
njn25e49d8e72002-09-23 09:36:25 +00002447 }
njn25e49d8e72002-09-23 09:36:25 +00002448}
2449
njn25e49d8e72002-09-23 09:36:25 +00002450
sewardj95448072004-11-22 20:19:51 +00002451static
2452IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
2453{
2454 IRAtom* vatom = expr2vbits( mce, atom );
2455 tl_assert(isOriginalAtom(mce,atom));
2456 switch (op) {
2457
sewardj0b070592004-12-10 21:44:22 +00002458 case Iop_Sqrt64Fx2:
2459 return unary64Fx2(mce, vatom);
2460
2461 case Iop_Sqrt64F0x2:
2462 return unary64F0x2(mce, vatom);
2463
sewardj170ee212004-12-10 18:57:51 +00002464 case Iop_Sqrt32Fx4:
2465 case Iop_RSqrt32Fx4:
2466 case Iop_Recip32Fx4:
cerion176cb4c2005-11-16 17:21:49 +00002467 case Iop_I32UtoFx4:
2468 case Iop_I32StoFx4:
2469 case Iop_QFtoI32Ux4_RZ:
2470 case Iop_QFtoI32Sx4_RZ:
2471 case Iop_RoundF32x4_RM:
2472 case Iop_RoundF32x4_RP:
2473 case Iop_RoundF32x4_RN:
2474 case Iop_RoundF32x4_RZ:
sewardj170ee212004-12-10 18:57:51 +00002475 return unary32Fx4(mce, vatom);
2476
2477 case Iop_Sqrt32F0x4:
2478 case Iop_RSqrt32F0x4:
2479 case Iop_Recip32F0x4:
2480 return unary32F0x4(mce, vatom);
2481
sewardj20d38f22005-02-07 23:50:18 +00002482 case Iop_32UtoV128:
2483 case Iop_64UtoV128:
sewardj620eb5b2005-10-22 12:50:43 +00002484 case Iop_Dup8x16:
2485 case Iop_Dup16x8:
2486 case Iop_Dup32x4:
sewardj170ee212004-12-10 18:57:51 +00002487 return assignNew(mce, Ity_V128, unop(op, vatom));
2488
sewardj95448072004-11-22 20:19:51 +00002489 case Iop_F32toF64:
2490 case Iop_I32toF64:
sewardj95448072004-11-22 20:19:51 +00002491 case Iop_NegF64:
sewardj95448072004-11-22 20:19:51 +00002492 case Iop_AbsF64:
sewardj4f3e0f22006-01-27 15:11:31 +00002493 case Iop_Est5FRSqrt:
sewardj39cc7352005-06-09 21:31:55 +00002494 case Iop_Clz64:
2495 case Iop_Ctz64:
sewardj95448072004-11-22 20:19:51 +00002496 return mkPCastTo(mce, Ity_I64, vatom);
2497
sewardj95448072004-11-22 20:19:51 +00002498 case Iop_Clz32:
2499 case Iop_Ctz32:
sewardjed69fdb2006-02-03 16:12:27 +00002500 case Iop_TruncF64asF32:
sewardj95448072004-11-22 20:19:51 +00002501 return mkPCastTo(mce, Ity_I32, vatom);
2502
sewardjd9dbc192005-04-27 11:40:27 +00002503 case Iop_1Uto64:
2504 case Iop_8Uto64:
2505 case Iop_8Sto64:
2506 case Iop_16Uto64:
2507 case Iop_16Sto64:
sewardj95448072004-11-22 20:19:51 +00002508 case Iop_32Sto64:
2509 case Iop_32Uto64:
sewardj20d38f22005-02-07 23:50:18 +00002510 case Iop_V128to64:
2511 case Iop_V128HIto64:
sewardj6cf40ff2005-04-20 22:31:26 +00002512 case Iop_128HIto64:
2513 case Iop_128to64:
sewardj95448072004-11-22 20:19:51 +00002514 return assignNew(mce, Ity_I64, unop(op, vatom));
2515
2516 case Iop_64to32:
2517 case Iop_64HIto32:
2518 case Iop_1Uto32:
sewardj463b3d92005-07-18 11:41:15 +00002519 case Iop_1Sto32:
sewardj95448072004-11-22 20:19:51 +00002520 case Iop_8Uto32:
2521 case Iop_16Uto32:
2522 case Iop_16Sto32:
2523 case Iop_8Sto32:
cerionfafaa0d2005-09-12 22:29:38 +00002524 case Iop_V128to32:
sewardj95448072004-11-22 20:19:51 +00002525 return assignNew(mce, Ity_I32, unop(op, vatom));
2526
2527 case Iop_8Sto16:
2528 case Iop_8Uto16:
2529 case Iop_32to16:
2530 case Iop_32HIto16:
sewardjd9dbc192005-04-27 11:40:27 +00002531 case Iop_64to16:
sewardj95448072004-11-22 20:19:51 +00002532 return assignNew(mce, Ity_I16, unop(op, vatom));
2533
2534 case Iop_1Uto8:
2535 case Iop_16to8:
sewardj9a807e02006-12-17 14:20:31 +00002536 case Iop_16HIto8:
sewardj95448072004-11-22 20:19:51 +00002537 case Iop_32to8:
sewardjd9dbc192005-04-27 11:40:27 +00002538 case Iop_64to8:
sewardj95448072004-11-22 20:19:51 +00002539 return assignNew(mce, Ity_I8, unop(op, vatom));
2540
2541 case Iop_32to1:
2542 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
2543
sewardjd9dbc192005-04-27 11:40:27 +00002544 case Iop_64to1:
2545 return assignNew(mce, Ity_I1, unop(Iop_64to1, vatom));
2546
sewardj95448072004-11-22 20:19:51 +00002547 case Iop_ReinterpF64asI64:
2548 case Iop_ReinterpI64asF64:
sewardj0b070592004-12-10 21:44:22 +00002549 case Iop_ReinterpI32asF32:
sewardj20d38f22005-02-07 23:50:18 +00002550 case Iop_NotV128:
sewardj7010f6e2004-12-10 13:35:22 +00002551 case Iop_Not64:
sewardj95448072004-11-22 20:19:51 +00002552 case Iop_Not32:
2553 case Iop_Not16:
2554 case Iop_Not8:
2555 case Iop_Not1:
2556 return vatom;
sewardj7010f6e2004-12-10 13:35:22 +00002557
sewardj95448072004-11-22 20:19:51 +00002558 default:
2559 ppIROp(op);
2560 VG_(tool_panic)("memcheck:expr2vbits_Unop");
2561 }
2562}
2563
2564
sewardj170ee212004-12-10 18:57:51 +00002565/* Worker function; do not call directly. */
sewardj95448072004-11-22 20:19:51 +00002566static
sewardj2e595852005-06-30 23:33:37 +00002567IRAtom* expr2vbits_Load_WRK ( MCEnv* mce,
2568 IREndness end, IRType ty,
2569 IRAtom* addr, UInt bias )
sewardj95448072004-11-22 20:19:51 +00002570{
2571 void* helper;
2572 Char* hname;
2573 IRDirty* di;
2574 IRTemp datavbits;
2575 IRAtom* addrAct;
2576
2577 tl_assert(isOriginalAtom(mce,addr));
sewardj2e595852005-06-30 23:33:37 +00002578 tl_assert(end == Iend_LE || end == Iend_BE);
sewardj95448072004-11-22 20:19:51 +00002579
2580 /* First, emit a definedness test for the address. This also sets
2581 the address (shadow) to 'defined' following the test. */
2582 complainIfUndefined( mce, addr );
2583
2584 /* Now cook up a call to the relevant helper function, to read the
2585 data V bits from shadow memory. */
2586 ty = shadowType(ty);
sewardj2e595852005-06-30 23:33:37 +00002587
2588 if (end == Iend_LE) {
2589 switch (ty) {
njn1d0825f2006-03-27 11:37:07 +00002590 case Ity_I64: helper = &MC_(helperc_LOADV64le);
2591 hname = "MC_(helperc_LOADV64le)";
sewardj2e595852005-06-30 23:33:37 +00002592 break;
njn1d0825f2006-03-27 11:37:07 +00002593 case Ity_I32: helper = &MC_(helperc_LOADV32le);
2594 hname = "MC_(helperc_LOADV32le)";
sewardj2e595852005-06-30 23:33:37 +00002595 break;
njn1d0825f2006-03-27 11:37:07 +00002596 case Ity_I16: helper = &MC_(helperc_LOADV16le);
2597 hname = "MC_(helperc_LOADV16le)";
sewardj2e595852005-06-30 23:33:37 +00002598 break;
njn1d0825f2006-03-27 11:37:07 +00002599 case Ity_I8: helper = &MC_(helperc_LOADV8);
2600 hname = "MC_(helperc_LOADV8)";
sewardj2e595852005-06-30 23:33:37 +00002601 break;
2602 default: ppIRType(ty);
2603 VG_(tool_panic)("memcheck:do_shadow_Load(LE)");
2604 }
2605 } else {
sewardj8cf88b72005-07-08 01:29:33 +00002606 switch (ty) {
njn1d0825f2006-03-27 11:37:07 +00002607 case Ity_I64: helper = &MC_(helperc_LOADV64be);
2608 hname = "MC_(helperc_LOADV64be)";
sewardj8cf88b72005-07-08 01:29:33 +00002609 break;
njn1d0825f2006-03-27 11:37:07 +00002610 case Ity_I32: helper = &MC_(helperc_LOADV32be);
2611 hname = "MC_(helperc_LOADV32be)";
sewardj8cf88b72005-07-08 01:29:33 +00002612 break;
njn1d0825f2006-03-27 11:37:07 +00002613 case Ity_I16: helper = &MC_(helperc_LOADV16be);
2614 hname = "MC_(helperc_LOADV16be)";
sewardj8cf88b72005-07-08 01:29:33 +00002615 break;
njn1d0825f2006-03-27 11:37:07 +00002616 case Ity_I8: helper = &MC_(helperc_LOADV8);
2617 hname = "MC_(helperc_LOADV8)";
sewardj8cf88b72005-07-08 01:29:33 +00002618 break;
2619 default: ppIRType(ty);
2620 VG_(tool_panic)("memcheck:do_shadow_Load(BE)");
2621 }
sewardj95448072004-11-22 20:19:51 +00002622 }
2623
2624 /* Generate the actual address into addrAct. */
2625 if (bias == 0) {
2626 addrAct = addr;
2627 } else {
sewardj7cf97ee2004-11-28 14:25:01 +00002628 IROp mkAdd;
2629 IRAtom* eBias;
sewardj95448072004-11-22 20:19:51 +00002630 IRType tyAddr = mce->hWordTy;
2631 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj7cf97ee2004-11-28 14:25:01 +00002632 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2633 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj95448072004-11-22 20:19:51 +00002634 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2635 }
2636
2637 /* We need to have a place to park the V bits we're just about to
2638 read. */
2639 datavbits = newIRTemp(mce->bb->tyenv, ty);
2640 di = unsafeIRDirty_1_N( datavbits,
sewardj53ee1fc2005-12-23 02:29:58 +00002641 1/*regparms*/,
2642 hname, VG_(fnptr_to_fnentry)( helper ),
sewardj95448072004-11-22 20:19:51 +00002643 mkIRExprVec_1( addrAct ));
2644 setHelperAnns( mce, di );
2645 stmt( mce->bb, IRStmt_Dirty(di) );
2646
2647 return mkexpr(datavbits);
2648}
2649
2650
2651static
sewardj2e595852005-06-30 23:33:37 +00002652IRAtom* expr2vbits_Load ( MCEnv* mce,
2653 IREndness end, IRType ty,
2654 IRAtom* addr, UInt bias )
sewardj170ee212004-12-10 18:57:51 +00002655{
2656 IRAtom *v64hi, *v64lo;
sewardj2e595852005-06-30 23:33:37 +00002657 tl_assert(end == Iend_LE || end == Iend_BE);
sewardj170ee212004-12-10 18:57:51 +00002658 switch (shadowType(ty)) {
2659 case Ity_I8:
2660 case Ity_I16:
2661 case Ity_I32:
2662 case Ity_I64:
sewardj2e595852005-06-30 23:33:37 +00002663 return expr2vbits_Load_WRK(mce, end, ty, addr, bias);
sewardj170ee212004-12-10 18:57:51 +00002664 case Ity_V128:
sewardj2e595852005-06-30 23:33:37 +00002665 if (end == Iend_LE) {
2666 v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
2667 v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
2668 } else {
sewardj2e595852005-06-30 23:33:37 +00002669 v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
2670 v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
2671 }
sewardj170ee212004-12-10 18:57:51 +00002672 return assignNew( mce,
2673 Ity_V128,
sewardj20d38f22005-02-07 23:50:18 +00002674 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj170ee212004-12-10 18:57:51 +00002675 default:
sewardj2e595852005-06-30 23:33:37 +00002676 VG_(tool_panic)("expr2vbits_Load");
sewardj170ee212004-12-10 18:57:51 +00002677 }
2678}
2679
2680
2681static
sewardj95448072004-11-22 20:19:51 +00002682IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
2683 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
2684{
2685 IRAtom *vbitsC, *vbits0, *vbitsX;
2686 IRType ty;
2687 /* Given Mux0X(cond,expr0,exprX), generate
2688 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2689 That is, steer the V bits like the originals, but trash the
2690 result if the steering value is undefined. This gives
2691 lazy propagation. */
2692 tl_assert(isOriginalAtom(mce, cond));
2693 tl_assert(isOriginalAtom(mce, expr0));
2694 tl_assert(isOriginalAtom(mce, exprX));
2695
2696 vbitsC = expr2vbits(mce, cond);
2697 vbits0 = expr2vbits(mce, expr0);
2698 vbitsX = expr2vbits(mce, exprX);
2699 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2700
2701 return
2702 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2703 mkPCastTo(mce, ty, vbitsC) );
2704}
2705
2706/* --------- This is the main expression-handling function. --------- */
2707
2708static
2709IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2710{
2711 switch (e->tag) {
2712
2713 case Iex_Get:
2714 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2715
2716 case Iex_GetI:
2717 return shadow_GETI( mce, e->Iex.GetI.descr,
2718 e->Iex.GetI.ix, e->Iex.GetI.bias );
2719
sewardj0b9d74a2006-12-24 02:24:11 +00002720 case Iex_RdTmp:
2721 return IRExpr_RdTmp( findShadowTmp(mce, e->Iex.RdTmp.tmp) );
sewardj95448072004-11-22 20:19:51 +00002722
2723 case Iex_Const:
2724 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2725
sewardje91cea72006-02-08 19:32:02 +00002726 case Iex_Qop:
2727 return expr2vbits_Qop(
2728 mce,
2729 e->Iex.Qop.op,
2730 e->Iex.Qop.arg1, e->Iex.Qop.arg2,
2731 e->Iex.Qop.arg3, e->Iex.Qop.arg4
2732 );
2733
sewardjed69fdb2006-02-03 16:12:27 +00002734 case Iex_Triop:
2735 return expr2vbits_Triop(
2736 mce,
2737 e->Iex.Triop.op,
2738 e->Iex.Triop.arg1, e->Iex.Triop.arg2, e->Iex.Triop.arg3
2739 );
2740
sewardj95448072004-11-22 20:19:51 +00002741 case Iex_Binop:
2742 return expr2vbits_Binop(
2743 mce,
2744 e->Iex.Binop.op,
2745 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2746 );
2747
2748 case Iex_Unop:
2749 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2750
sewardj2e595852005-06-30 23:33:37 +00002751 case Iex_Load:
2752 return expr2vbits_Load( mce, e->Iex.Load.end,
2753 e->Iex.Load.ty,
2754 e->Iex.Load.addr, 0/*addr bias*/ );
sewardj95448072004-11-22 20:19:51 +00002755
2756 case Iex_CCall:
2757 return mkLazyN( mce, e->Iex.CCall.args,
2758 e->Iex.CCall.retty,
2759 e->Iex.CCall.cee );
2760
2761 case Iex_Mux0X:
2762 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2763 e->Iex.Mux0X.exprX);
njn25e49d8e72002-09-23 09:36:25 +00002764
2765 default:
sewardj95448072004-11-22 20:19:51 +00002766 VG_(printf)("\n");
2767 ppIRExpr(e);
2768 VG_(printf)("\n");
2769 VG_(tool_panic)("memcheck: expr2vbits");
njn25e49d8e72002-09-23 09:36:25 +00002770 }
njn25e49d8e72002-09-23 09:36:25 +00002771}
2772
2773/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00002774/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
njn25e49d8e72002-09-23 09:36:25 +00002775/*------------------------------------------------------------*/
2776
sewardj95448072004-11-22 20:19:51 +00002777/* Widen a value to the host word size. */
njn25e49d8e72002-09-23 09:36:25 +00002778
2779static
sewardj95448072004-11-22 20:19:51 +00002780IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
njn25e49d8e72002-09-23 09:36:25 +00002781{
sewardj7cf97ee2004-11-28 14:25:01 +00002782 IRType ty, tyH;
2783
sewardj95448072004-11-22 20:19:51 +00002784 /* vatom is vbits-value and as such can only have a shadow type. */
2785 tl_assert(isShadowAtom(mce,vatom));
njn25e49d8e72002-09-23 09:36:25 +00002786
sewardj7cf97ee2004-11-28 14:25:01 +00002787 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2788 tyH = mce->hWordTy;
njn25e49d8e72002-09-23 09:36:25 +00002789
sewardj95448072004-11-22 20:19:51 +00002790 if (tyH == Ity_I32) {
2791 switch (ty) {
2792 case Ity_I32: return vatom;
2793 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2794 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2795 default: goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00002796 }
sewardj6cf40ff2005-04-20 22:31:26 +00002797 } else
2798 if (tyH == Ity_I64) {
2799 switch (ty) {
2800 case Ity_I32: return assignNew(mce, tyH, unop(Iop_32Uto64, vatom));
sewardj69a13322005-04-23 01:14:51 +00002801 case Ity_I16: return assignNew(mce, tyH, unop(Iop_32Uto64,
2802 assignNew(mce, Ity_I32, unop(Iop_16Uto32, vatom))));
2803 case Ity_I8: return assignNew(mce, tyH, unop(Iop_32Uto64,
2804 assignNew(mce, Ity_I32, unop(Iop_8Uto32, vatom))));
sewardj6cf40ff2005-04-20 22:31:26 +00002805 default: goto unhandled;
2806 }
sewardj95448072004-11-22 20:19:51 +00002807 } else {
2808 goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00002809 }
sewardj95448072004-11-22 20:19:51 +00002810 unhandled:
2811 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
2812 VG_(tool_panic)("zwidenToHostWord");
njn25e49d8e72002-09-23 09:36:25 +00002813}
2814
njn25e49d8e72002-09-23 09:36:25 +00002815
sewardj95448072004-11-22 20:19:51 +00002816/* Generate a shadow store. addr is always the original address atom.
2817 You can pass in either originals or V-bits for the data atom, but
2818 obviously not both. */
njn25e49d8e72002-09-23 09:36:25 +00002819
sewardj95448072004-11-22 20:19:51 +00002820static
sewardj2e595852005-06-30 23:33:37 +00002821void do_shadow_Store ( MCEnv* mce,
2822 IREndness end,
2823 IRAtom* addr, UInt bias,
2824 IRAtom* data, IRAtom* vdata )
njn25e49d8e72002-09-23 09:36:25 +00002825{
sewardj170ee212004-12-10 18:57:51 +00002826 IROp mkAdd;
2827 IRType ty, tyAddr;
2828 IRDirty *di, *diLo64, *diHi64;
2829 IRAtom *addrAct, *addrLo64, *addrHi64;
2830 IRAtom *vdataLo64, *vdataHi64;
sewardj2e595852005-06-30 23:33:37 +00002831 IRAtom *eBias, *eBiasLo64, *eBiasHi64;
sewardj95448072004-11-22 20:19:51 +00002832 void* helper = NULL;
2833 Char* hname = NULL;
njn1d0825f2006-03-27 11:37:07 +00002834 IRConst* c;
sewardj170ee212004-12-10 18:57:51 +00002835
2836 tyAddr = mce->hWordTy;
2837 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2838 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj2e595852005-06-30 23:33:37 +00002839 tl_assert( end == Iend_LE || end == Iend_BE );
sewardj170ee212004-12-10 18:57:51 +00002840
2841 di = diLo64 = diHi64 = NULL;
sewardj2e595852005-06-30 23:33:37 +00002842 eBias = eBiasLo64 = eBiasHi64 = NULL;
sewardj170ee212004-12-10 18:57:51 +00002843 addrAct = addrLo64 = addrHi64 = NULL;
2844 vdataLo64 = vdataHi64 = NULL;
njn25e49d8e72002-09-23 09:36:25 +00002845
sewardj95448072004-11-22 20:19:51 +00002846 if (data) {
2847 tl_assert(!vdata);
2848 tl_assert(isOriginalAtom(mce, data));
2849 tl_assert(bias == 0);
2850 vdata = expr2vbits( mce, data );
2851 } else {
2852 tl_assert(vdata);
2853 }
njn25e49d8e72002-09-23 09:36:25 +00002854
sewardj95448072004-11-22 20:19:51 +00002855 tl_assert(isOriginalAtom(mce,addr));
2856 tl_assert(isShadowAtom(mce,vdata));
njn25e49d8e72002-09-23 09:36:25 +00002857
sewardj95448072004-11-22 20:19:51 +00002858 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
njn25e49d8e72002-09-23 09:36:25 +00002859
njn1d0825f2006-03-27 11:37:07 +00002860 // If we're not doing undefined value checking, pretend that this value
2861 // is "all valid". That lets Vex's optimiser remove some of the V bit
2862 // shadow computation ops that precede it.
2863 if (!MC_(clo_undef_value_errors)) {
2864 switch (ty) {
2865 case Ity_V128: c = IRConst_V128(V_BITS16_DEFINED); break; // V128 weirdness
2866 case Ity_I64: c = IRConst_U64 (V_BITS64_DEFINED); break;
2867 case Ity_I32: c = IRConst_U32 (V_BITS32_DEFINED); break;
2868 case Ity_I16: c = IRConst_U16 (V_BITS16_DEFINED); break;
2869 case Ity_I8: c = IRConst_U8 (V_BITS8_DEFINED); break;
2870 default: VG_(tool_panic)("memcheck:do_shadow_Store(LE)");
2871 }
2872 vdata = IRExpr_Const( c );
2873 }
2874
sewardj95448072004-11-22 20:19:51 +00002875 /* First, emit a definedness test for the address. This also sets
2876 the address (shadow) to 'defined' following the test. */
2877 complainIfUndefined( mce, addr );
njn25e49d8e72002-09-23 09:36:25 +00002878
sewardj170ee212004-12-10 18:57:51 +00002879 /* Now decide which helper function to call to write the data V
2880 bits into shadow memory. */
sewardj2e595852005-06-30 23:33:37 +00002881 if (end == Iend_LE) {
2882 switch (ty) {
2883 case Ity_V128: /* we'll use the helper twice */
njn1d0825f2006-03-27 11:37:07 +00002884 case Ity_I64: helper = &MC_(helperc_STOREV64le);
2885 hname = "MC_(helperc_STOREV64le)";
sewardj2e595852005-06-30 23:33:37 +00002886 break;
njn1d0825f2006-03-27 11:37:07 +00002887 case Ity_I32: helper = &MC_(helperc_STOREV32le);
2888 hname = "MC_(helperc_STOREV32le)";
sewardj2e595852005-06-30 23:33:37 +00002889 break;
njn1d0825f2006-03-27 11:37:07 +00002890 case Ity_I16: helper = &MC_(helperc_STOREV16le);
2891 hname = "MC_(helperc_STOREV16le)";
sewardj2e595852005-06-30 23:33:37 +00002892 break;
njn1d0825f2006-03-27 11:37:07 +00002893 case Ity_I8: helper = &MC_(helperc_STOREV8);
2894 hname = "MC_(helperc_STOREV8)";
sewardj2e595852005-06-30 23:33:37 +00002895 break;
2896 default: VG_(tool_panic)("memcheck:do_shadow_Store(LE)");
2897 }
2898 } else {
sewardj8cf88b72005-07-08 01:29:33 +00002899 switch (ty) {
2900 case Ity_V128: /* we'll use the helper twice */
njn1d0825f2006-03-27 11:37:07 +00002901 case Ity_I64: helper = &MC_(helperc_STOREV64be);
2902 hname = "MC_(helperc_STOREV64be)";
sewardj8cf88b72005-07-08 01:29:33 +00002903 break;
njn1d0825f2006-03-27 11:37:07 +00002904 case Ity_I32: helper = &MC_(helperc_STOREV32be);
2905 hname = "MC_(helperc_STOREV32be)";
sewardj8cf88b72005-07-08 01:29:33 +00002906 break;
njn1d0825f2006-03-27 11:37:07 +00002907 case Ity_I16: helper = &MC_(helperc_STOREV16be);
2908 hname = "MC_(helperc_STOREV16be)";
sewardj8cf88b72005-07-08 01:29:33 +00002909 break;
njn1d0825f2006-03-27 11:37:07 +00002910 case Ity_I8: helper = &MC_(helperc_STOREV8);
2911 hname = "MC_(helperc_STOREV8)";
sewardj8cf88b72005-07-08 01:29:33 +00002912 break;
2913 default: VG_(tool_panic)("memcheck:do_shadow_Store(BE)");
2914 }
sewardj95448072004-11-22 20:19:51 +00002915 }
njn25e49d8e72002-09-23 09:36:25 +00002916
sewardj170ee212004-12-10 18:57:51 +00002917 if (ty == Ity_V128) {
2918
sewardj20d38f22005-02-07 23:50:18 +00002919 /* V128-bit case */
sewardj170ee212004-12-10 18:57:51 +00002920 /* See comment in next clause re 64-bit regparms */
sewardj2e595852005-06-30 23:33:37 +00002921 /* also, need to be careful about endianness */
2922
2923 Int offLo64, offHi64;
2924 if (end == Iend_LE) {
2925 offLo64 = 0;
2926 offHi64 = 8;
2927 } else {
sewardj2e595852005-06-30 23:33:37 +00002928 offLo64 = 8;
2929 offHi64 = 0;
2930 }
2931
2932 eBiasLo64 = tyAddr==Ity_I32 ? mkU32(bias+offLo64) : mkU64(bias+offLo64);
2933 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBiasLo64) );
sewardj20d38f22005-02-07 23:50:18 +00002934 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj170ee212004-12-10 18:57:51 +00002935 diLo64 = unsafeIRDirty_0_N(
sewardj53ee1fc2005-12-23 02:29:58 +00002936 1/*regparms*/,
2937 hname, VG_(fnptr_to_fnentry)( helper ),
2938 mkIRExprVec_2( addrLo64, vdataLo64 )
2939 );
sewardj2e595852005-06-30 23:33:37 +00002940 eBiasHi64 = tyAddr==Ity_I32 ? mkU32(bias+offHi64) : mkU64(bias+offHi64);
2941 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBiasHi64) );
sewardj20d38f22005-02-07 23:50:18 +00002942 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj170ee212004-12-10 18:57:51 +00002943 diHi64 = unsafeIRDirty_0_N(
sewardj53ee1fc2005-12-23 02:29:58 +00002944 1/*regparms*/,
2945 hname, VG_(fnptr_to_fnentry)( helper ),
2946 mkIRExprVec_2( addrHi64, vdataHi64 )
2947 );
sewardj170ee212004-12-10 18:57:51 +00002948 setHelperAnns( mce, diLo64 );
2949 setHelperAnns( mce, diHi64 );
2950 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2951 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2952
sewardj95448072004-11-22 20:19:51 +00002953 } else {
sewardj170ee212004-12-10 18:57:51 +00002954
2955 /* 8/16/32/64-bit cases */
2956 /* Generate the actual address into addrAct. */
2957 if (bias == 0) {
2958 addrAct = addr;
2959 } else {
2960 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2961 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2962 }
2963
2964 if (ty == Ity_I64) {
2965 /* We can't do this with regparm 2 on 32-bit platforms, since
2966 the back ends aren't clever enough to handle 64-bit
2967 regparm args. Therefore be different. */
2968 di = unsafeIRDirty_0_N(
sewardj53ee1fc2005-12-23 02:29:58 +00002969 1/*regparms*/,
2970 hname, VG_(fnptr_to_fnentry)( helper ),
2971 mkIRExprVec_2( addrAct, vdata )
2972 );
sewardj170ee212004-12-10 18:57:51 +00002973 } else {
2974 di = unsafeIRDirty_0_N(
sewardj53ee1fc2005-12-23 02:29:58 +00002975 2/*regparms*/,
2976 hname, VG_(fnptr_to_fnentry)( helper ),
sewardj170ee212004-12-10 18:57:51 +00002977 mkIRExprVec_2( addrAct,
sewardj53ee1fc2005-12-23 02:29:58 +00002978 zwidenToHostWord( mce, vdata ))
2979 );
sewardj170ee212004-12-10 18:57:51 +00002980 }
2981 setHelperAnns( mce, di );
2982 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj95448072004-11-22 20:19:51 +00002983 }
njn25e49d8e72002-09-23 09:36:25 +00002984
sewardj95448072004-11-22 20:19:51 +00002985}
njn25e49d8e72002-09-23 09:36:25 +00002986
njn25e49d8e72002-09-23 09:36:25 +00002987
sewardj95448072004-11-22 20:19:51 +00002988/* Do lazy pessimistic propagation through a dirty helper call, by
2989 looking at the annotations on it. This is the most complex part of
2990 Memcheck. */
njn25e49d8e72002-09-23 09:36:25 +00002991
sewardj95448072004-11-22 20:19:51 +00002992static IRType szToITy ( Int n )
2993{
2994 switch (n) {
2995 case 1: return Ity_I8;
2996 case 2: return Ity_I16;
2997 case 4: return Ity_I32;
2998 case 8: return Ity_I64;
2999 default: VG_(tool_panic)("szToITy(memcheck)");
3000 }
3001}
njn25e49d8e72002-09-23 09:36:25 +00003002
sewardj95448072004-11-22 20:19:51 +00003003static
3004void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
3005{
sewardj2e595852005-06-30 23:33:37 +00003006 Int i, n, offset, toDo, gSz, gOff;
3007 IRAtom *src, *here, *curr;
3008 IRType tyAddr, tySrc, tyDst;
3009 IRTemp dst;
3010 IREndness end;
3011
3012 /* What's the native endianness? We need to know this. */
sewardj6e340c72005-07-10 00:53:42 +00003013# if defined(VG_BIGENDIAN)
sewardj2e595852005-06-30 23:33:37 +00003014 end = Iend_BE;
sewardj6e340c72005-07-10 00:53:42 +00003015# elif defined(VG_LITTLEENDIAN)
sewardj2e595852005-06-30 23:33:37 +00003016 end = Iend_LE;
3017# else
3018# error "Unknown endianness"
3019# endif
njn25e49d8e72002-09-23 09:36:25 +00003020
sewardj95448072004-11-22 20:19:51 +00003021 /* First check the guard. */
3022 complainIfUndefined(mce, d->guard);
3023
3024 /* Now round up all inputs and PCast over them. */
sewardj7cf97ee2004-11-28 14:25:01 +00003025 curr = definedOfType(Ity_I32);
sewardj95448072004-11-22 20:19:51 +00003026
3027 /* Inputs: unmasked args */
3028 for (i = 0; d->args[i]; i++) {
3029 if (d->cee->mcx_mask & (1<<i)) {
3030 /* ignore this arg */
njn25e49d8e72002-09-23 09:36:25 +00003031 } else {
sewardj95448072004-11-22 20:19:51 +00003032 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
3033 curr = mkUifU32(mce, here, curr);
njn25e49d8e72002-09-23 09:36:25 +00003034 }
3035 }
sewardj95448072004-11-22 20:19:51 +00003036
3037 /* Inputs: guest state that we read. */
3038 for (i = 0; i < d->nFxState; i++) {
3039 tl_assert(d->fxState[i].fx != Ifx_None);
3040 if (d->fxState[i].fx == Ifx_Write)
3041 continue;
sewardja7203252004-11-26 19:17:47 +00003042
3043 /* Ignore any sections marked as 'always defined'. */
3044 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
sewardje9e16d32004-12-10 13:17:55 +00003045 if (0)
sewardja7203252004-11-26 19:17:47 +00003046 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
3047 d->fxState[i].offset, d->fxState[i].size );
3048 continue;
3049 }
3050
sewardj95448072004-11-22 20:19:51 +00003051 /* This state element is read or modified. So we need to
sewardje9e16d32004-12-10 13:17:55 +00003052 consider it. If larger than 8 bytes, deal with it in 8-byte
3053 chunks. */
3054 gSz = d->fxState[i].size;
3055 gOff = d->fxState[i].offset;
3056 tl_assert(gSz > 0);
3057 while (True) {
3058 if (gSz == 0) break;
3059 n = gSz <= 8 ? gSz : 8;
3060 /* update 'curr' with UifU of the state slice
3061 gOff .. gOff+n-1 */
3062 tySrc = szToITy( n );
3063 src = assignNew( mce, tySrc,
3064 shadow_GET(mce, gOff, tySrc ) );
3065 here = mkPCastTo( mce, Ity_I32, src );
3066 curr = mkUifU32(mce, here, curr);
3067 gSz -= n;
3068 gOff += n;
3069 }
3070
sewardj95448072004-11-22 20:19:51 +00003071 }
3072
3073 /* Inputs: memory. First set up some info needed regardless of
3074 whether we're doing reads or writes. */
3075 tyAddr = Ity_INVALID;
3076
3077 if (d->mFx != Ifx_None) {
3078 /* Because we may do multiple shadow loads/stores from the same
3079 base address, it's best to do a single test of its
3080 definedness right now. Post-instrumentation optimisation
3081 should remove all but this test. */
3082 tl_assert(d->mAddr);
3083 complainIfUndefined(mce, d->mAddr);
3084
3085 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
3086 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
3087 tl_assert(tyAddr == mce->hWordTy); /* not really right */
3088 }
3089
3090 /* Deal with memory inputs (reads or modifies) */
3091 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
3092 offset = 0;
3093 toDo = d->mSize;
sewardj2e595852005-06-30 23:33:37 +00003094 /* chew off 32-bit chunks. We don't care about the endianness
3095 since it's all going to be condensed down to a single bit,
3096 but nevertheless choose an endianness which is hopefully
3097 native to the platform. */
sewardj95448072004-11-22 20:19:51 +00003098 while (toDo >= 4) {
3099 here = mkPCastTo(
3100 mce, Ity_I32,
sewardj2e595852005-06-30 23:33:37 +00003101 expr2vbits_Load ( mce, end, Ity_I32,
sewardj95448072004-11-22 20:19:51 +00003102 d->mAddr, d->mSize - toDo )
3103 );
3104 curr = mkUifU32(mce, here, curr);
3105 toDo -= 4;
3106 }
3107 /* chew off 16-bit chunks */
3108 while (toDo >= 2) {
3109 here = mkPCastTo(
3110 mce, Ity_I32,
sewardj2e595852005-06-30 23:33:37 +00003111 expr2vbits_Load ( mce, end, Ity_I16,
sewardj95448072004-11-22 20:19:51 +00003112 d->mAddr, d->mSize - toDo )
3113 );
3114 curr = mkUifU32(mce, here, curr);
3115 toDo -= 2;
3116 }
3117 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
3118 }
3119
3120 /* Whew! So curr is a 32-bit V-value summarising pessimistically
3121 all the inputs to the helper. Now we need to re-distribute the
3122 results to all destinations. */
3123
3124 /* Outputs: the destination temporary, if there is one. */
3125 if (d->tmp != IRTemp_INVALID) {
3126 dst = findShadowTmp(mce, d->tmp);
3127 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
3128 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
3129 }
3130
3131 /* Outputs: guest state that we write or modify. */
3132 for (i = 0; i < d->nFxState; i++) {
3133 tl_assert(d->fxState[i].fx != Ifx_None);
3134 if (d->fxState[i].fx == Ifx_Read)
3135 continue;
sewardja7203252004-11-26 19:17:47 +00003136 /* Ignore any sections marked as 'always defined'. */
3137 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
3138 continue;
sewardje9e16d32004-12-10 13:17:55 +00003139 /* This state element is written or modified. So we need to
3140 consider it. If larger than 8 bytes, deal with it in 8-byte
3141 chunks. */
3142 gSz = d->fxState[i].size;
3143 gOff = d->fxState[i].offset;
3144 tl_assert(gSz > 0);
3145 while (True) {
3146 if (gSz == 0) break;
3147 n = gSz <= 8 ? gSz : 8;
3148 /* Write suitably-casted 'curr' to the state slice
3149 gOff .. gOff+n-1 */
3150 tyDst = szToITy( n );
3151 do_shadow_PUT( mce, gOff,
3152 NULL, /* original atom */
3153 mkPCastTo( mce, tyDst, curr ) );
3154 gSz -= n;
3155 gOff += n;
3156 }
sewardj95448072004-11-22 20:19:51 +00003157 }
3158
sewardj2e595852005-06-30 23:33:37 +00003159 /* Outputs: memory that we write or modify. Same comments about
3160 endianness as above apply. */
sewardj95448072004-11-22 20:19:51 +00003161 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
3162 offset = 0;
3163 toDo = d->mSize;
3164 /* chew off 32-bit chunks */
3165 while (toDo >= 4) {
sewardj2e595852005-06-30 23:33:37 +00003166 do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
3167 NULL, /* original data */
3168 mkPCastTo( mce, Ity_I32, curr ) );
sewardj95448072004-11-22 20:19:51 +00003169 toDo -= 4;
3170 }
3171 /* chew off 16-bit chunks */
3172 while (toDo >= 2) {
sewardj2e595852005-06-30 23:33:37 +00003173 do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
3174 NULL, /* original data */
3175 mkPCastTo( mce, Ity_I16, curr ) );
sewardj95448072004-11-22 20:19:51 +00003176 toDo -= 2;
3177 }
3178 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
3179 }
3180
njn25e49d8e72002-09-23 09:36:25 +00003181}
3182
sewardj826ec492005-05-12 18:05:00 +00003183/* We have an ABI hint telling us that [base .. base+len-1] is to
3184 become undefined ("writable"). Generate code to call a helper to
3185 notify the A/V bit machinery of this fact.
3186
3187 We call
3188 void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len );
3189*/
3190static
3191void do_AbiHint ( MCEnv* mce, IRExpr* base, Int len )
3192{
3193 IRDirty* di;
3194 di = unsafeIRDirty_0_N(
3195 0/*regparms*/,
3196 "MC_(helperc_MAKE_STACK_UNINIT)",
sewardj53ee1fc2005-12-23 02:29:58 +00003197 VG_(fnptr_to_fnentry)( &MC_(helperc_MAKE_STACK_UNINIT) ),
sewardj826ec492005-05-12 18:05:00 +00003198 mkIRExprVec_2( base, mkIRExpr_HWord( (UInt)len) )
3199 );
3200 stmt( mce->bb, IRStmt_Dirty(di) );
3201}
3202
njn25e49d8e72002-09-23 09:36:25 +00003203
sewardj95448072004-11-22 20:19:51 +00003204/*------------------------------------------------------------*/
3205/*--- Memcheck main ---*/
3206/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00003207
sewardj95448072004-11-22 20:19:51 +00003208static Bool isBogusAtom ( IRAtom* at )
njn25e49d8e72002-09-23 09:36:25 +00003209{
sewardj95448072004-11-22 20:19:51 +00003210 ULong n = 0;
3211 IRConst* con;
sewardj710d6c22005-03-20 18:55:15 +00003212 tl_assert(isIRAtom(at));
sewardj0b9d74a2006-12-24 02:24:11 +00003213 if (at->tag == Iex_RdTmp)
sewardj95448072004-11-22 20:19:51 +00003214 return False;
3215 tl_assert(at->tag == Iex_Const);
3216 con = at->Iex.Const.con;
3217 switch (con->tag) {
sewardjd5204dc2004-12-31 01:16:11 +00003218 case Ico_U1: return False;
3219 case Ico_U8: n = (ULong)con->Ico.U8; break;
3220 case Ico_U16: n = (ULong)con->Ico.U16; break;
3221 case Ico_U32: n = (ULong)con->Ico.U32; break;
3222 case Ico_U64: n = (ULong)con->Ico.U64; break;
3223 case Ico_F64: return False;
3224 case Ico_F64i: return False;
3225 case Ico_V128: return False;
sewardj95448072004-11-22 20:19:51 +00003226 default: ppIRExpr(at); tl_assert(0);
3227 }
3228 /* VG_(printf)("%llx\n", n); */
sewardj96a922e2005-04-23 23:26:29 +00003229 return (/*32*/ n == 0xFEFEFEFFULL
3230 /*32*/ || n == 0x80808080ULL
tomd9774d72005-06-27 08:11:01 +00003231 /*64*/ || n == 0xFFFFFFFFFEFEFEFFULL
sewardj96a922e2005-04-23 23:26:29 +00003232 /*64*/ || n == 0xFEFEFEFEFEFEFEFFULL
tomd9774d72005-06-27 08:11:01 +00003233 /*64*/ || n == 0x0000000000008080ULL
sewardj96a922e2005-04-23 23:26:29 +00003234 /*64*/ || n == 0x8080808080808080ULL
3235 /*64*/ || n == 0x0101010101010101ULL
3236 );
sewardj95448072004-11-22 20:19:51 +00003237}
njn25e49d8e72002-09-23 09:36:25 +00003238
sewardj95448072004-11-22 20:19:51 +00003239static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
3240{
sewardjd5204dc2004-12-31 01:16:11 +00003241 Int i;
3242 IRExpr* e;
3243 IRDirty* d;
sewardj95448072004-11-22 20:19:51 +00003244 switch (st->tag) {
sewardj0b9d74a2006-12-24 02:24:11 +00003245 case Ist_WrTmp:
3246 e = st->Ist.WrTmp.data;
sewardj95448072004-11-22 20:19:51 +00003247 switch (e->tag) {
3248 case Iex_Get:
sewardj0b9d74a2006-12-24 02:24:11 +00003249 case Iex_RdTmp:
sewardj95448072004-11-22 20:19:51 +00003250 return False;
sewardjd5204dc2004-12-31 01:16:11 +00003251 case Iex_Const:
3252 return isBogusAtom(e);
sewardj95448072004-11-22 20:19:51 +00003253 case Iex_Unop:
3254 return isBogusAtom(e->Iex.Unop.arg);
sewardjd5204dc2004-12-31 01:16:11 +00003255 case Iex_GetI:
3256 return isBogusAtom(e->Iex.GetI.ix);
sewardj95448072004-11-22 20:19:51 +00003257 case Iex_Binop:
3258 return isBogusAtom(e->Iex.Binop.arg1)
3259 || isBogusAtom(e->Iex.Binop.arg2);
sewardjed69fdb2006-02-03 16:12:27 +00003260 case Iex_Triop:
3261 return isBogusAtom(e->Iex.Triop.arg1)
3262 || isBogusAtom(e->Iex.Triop.arg2)
3263 || isBogusAtom(e->Iex.Triop.arg3);
sewardje91cea72006-02-08 19:32:02 +00003264 case Iex_Qop:
3265 return isBogusAtom(e->Iex.Qop.arg1)
3266 || isBogusAtom(e->Iex.Qop.arg2)
3267 || isBogusAtom(e->Iex.Qop.arg3)
3268 || isBogusAtom(e->Iex.Qop.arg4);
sewardj95448072004-11-22 20:19:51 +00003269 case Iex_Mux0X:
3270 return isBogusAtom(e->Iex.Mux0X.cond)
3271 || isBogusAtom(e->Iex.Mux0X.expr0)
3272 || isBogusAtom(e->Iex.Mux0X.exprX);
sewardj2e595852005-06-30 23:33:37 +00003273 case Iex_Load:
3274 return isBogusAtom(e->Iex.Load.addr);
sewardj95448072004-11-22 20:19:51 +00003275 case Iex_CCall:
3276 for (i = 0; e->Iex.CCall.args[i]; i++)
3277 if (isBogusAtom(e->Iex.CCall.args[i]))
3278 return True;
3279 return False;
3280 default:
3281 goto unhandled;
3282 }
sewardjd5204dc2004-12-31 01:16:11 +00003283 case Ist_Dirty:
3284 d = st->Ist.Dirty.details;
3285 for (i = 0; d->args[i]; i++)
3286 if (isBogusAtom(d->args[i]))
3287 return True;
3288 if (d->guard && isBogusAtom(d->guard))
3289 return True;
3290 if (d->mAddr && isBogusAtom(d->mAddr))
3291 return True;
3292 return False;
sewardj95448072004-11-22 20:19:51 +00003293 case Ist_Put:
3294 return isBogusAtom(st->Ist.Put.data);
sewardjd5204dc2004-12-31 01:16:11 +00003295 case Ist_PutI:
3296 return isBogusAtom(st->Ist.PutI.ix)
3297 || isBogusAtom(st->Ist.PutI.data);
sewardj2e595852005-06-30 23:33:37 +00003298 case Ist_Store:
3299 return isBogusAtom(st->Ist.Store.addr)
3300 || isBogusAtom(st->Ist.Store.data);
sewardj95448072004-11-22 20:19:51 +00003301 case Ist_Exit:
sewardjd5204dc2004-12-31 01:16:11 +00003302 return isBogusAtom(st->Ist.Exit.guard);
sewardj826ec492005-05-12 18:05:00 +00003303 case Ist_AbiHint:
3304 return isBogusAtom(st->Ist.AbiHint.base);
sewardj21dc3452005-03-21 00:27:41 +00003305 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00003306 case Ist_IMark:
sewardj72d75132007-11-09 23:06:35 +00003307 case Ist_MBE:
sewardjbd598e12005-01-07 12:10:21 +00003308 return False;
sewardj95448072004-11-22 20:19:51 +00003309 default:
3310 unhandled:
3311 ppIRStmt(st);
3312 VG_(tool_panic)("hasBogusLiterals");
3313 }
3314}
njn25e49d8e72002-09-23 09:36:25 +00003315
njn25e49d8e72002-09-23 09:36:25 +00003316
sewardj0b9d74a2006-12-24 02:24:11 +00003317IRSB* MC_(instrument) ( VgCallbackClosure* closure,
3318 IRSB* bb_in,
sewardj461df9c2006-01-17 02:06:39 +00003319 VexGuestLayout* layout,
3320 VexGuestExtents* vge,
sewardjd54babf2005-03-21 00:55:49 +00003321 IRType gWordTy, IRType hWordTy )
sewardj95448072004-11-22 20:19:51 +00003322{
sewardj151b90d2005-07-06 19:42:23 +00003323 Bool verboze = False; //True;
3324 Bool bogus;
sewardjd5204dc2004-12-31 01:16:11 +00003325 Int i, j, first_stmt;
sewardj95448072004-11-22 20:19:51 +00003326 IRStmt* st;
sewardjd5204dc2004-12-31 01:16:11 +00003327 MCEnv mce;
sewardj0b9d74a2006-12-24 02:24:11 +00003328 IRSB* bb;
sewardjd54babf2005-03-21 00:55:49 +00003329
3330 if (gWordTy != hWordTy) {
3331 /* We don't currently support this case. */
3332 VG_(tool_panic)("host/guest word size mismatch");
3333 }
njn25e49d8e72002-09-23 09:36:25 +00003334
sewardj6cf40ff2005-04-20 22:31:26 +00003335 /* Check we're not completely nuts */
3336 tl_assert(sizeof(UWord) == sizeof(void*));
3337 tl_assert(sizeof(Word) == sizeof(void*));
3338 tl_assert(sizeof(ULong) == 8);
3339 tl_assert(sizeof(Long) == 8);
3340 tl_assert(sizeof(UInt) == 4);
3341 tl_assert(sizeof(Int) == 4);
3342
sewardj0b9d74a2006-12-24 02:24:11 +00003343 /* Set up SB */
3344 bb = deepCopyIRSBExceptStmts(bb_in);
njn25e49d8e72002-09-23 09:36:25 +00003345
sewardj95448072004-11-22 20:19:51 +00003346 /* Set up the running environment. Only .bb is modified as we go
3347 along. */
3348 mce.bb = bb;
3349 mce.layout = layout;
3350 mce.n_originalTmps = bb->tyenv->types_used;
3351 mce.hWordTy = hWordTy;
sewardjd5204dc2004-12-31 01:16:11 +00003352 mce.bogusLiterals = False;
sewardj95448072004-11-22 20:19:51 +00003353 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
3354 for (i = 0; i < mce.n_originalTmps; i++)
3355 mce.tmpMap[i] = IRTemp_INVALID;
3356
sewardj151b90d2005-07-06 19:42:23 +00003357 /* Make a preliminary inspection of the statements, to see if there
3358 are any dodgy-looking literals. If there are, we generate
3359 extra-detailed (hence extra-expensive) instrumentation in
3360 places. Scan the whole bb even if dodgyness is found earlier,
3361 so that the flatness assertion is applied to all stmts. */
3362
3363 bogus = False;
sewardj95448072004-11-22 20:19:51 +00003364
sewardjf1962d32006-10-19 13:22:16 +00003365 for (i = 0; i < bb_in->stmts_used; i++) {
sewardj151b90d2005-07-06 19:42:23 +00003366
sewardj95448072004-11-22 20:19:51 +00003367 st = bb_in->stmts[i];
sewardj21dc3452005-03-21 00:27:41 +00003368 tl_assert(st);
sewardj95448072004-11-22 20:19:51 +00003369 tl_assert(isFlatIRStmt(st));
3370
sewardj151b90d2005-07-06 19:42:23 +00003371 if (!bogus) {
3372 bogus = checkForBogusLiterals(st);
3373 if (0 && bogus) {
sewardj95448072004-11-22 20:19:51 +00003374 VG_(printf)("bogus: ");
3375 ppIRStmt(st);
3376 VG_(printf)("\n");
3377 }
3378 }
sewardjd5204dc2004-12-31 01:16:11 +00003379
sewardj151b90d2005-07-06 19:42:23 +00003380 }
3381
3382 mce.bogusLiterals = bogus;
3383
sewardja0871482006-10-18 12:41:55 +00003384 /* Copy verbatim any IR preamble preceding the first IMark */
sewardj151b90d2005-07-06 19:42:23 +00003385
sewardjf1962d32006-10-19 13:22:16 +00003386 tl_assert(mce.bb == bb);
3387
sewardja0871482006-10-18 12:41:55 +00003388 i = 0;
3389 while (i < bb_in->stmts_used && bb_in->stmts[i]->tag != Ist_IMark) {
3390
3391 st = bb_in->stmts[i];
3392 tl_assert(st);
3393 tl_assert(isFlatIRStmt(st));
3394
sewardj0b9d74a2006-12-24 02:24:11 +00003395 addStmtToIRSB( bb, bb_in->stmts[i] );
sewardja0871482006-10-18 12:41:55 +00003396 i++;
3397 }
3398
sewardjf1962d32006-10-19 13:22:16 +00003399 /* Nasty problem. IR optimisation of the pre-instrumented IR may
3400 cause the IR following the preamble to contain references to IR
3401 temporaries defined in the preamble. Because the preamble isn't
3402 instrumented, these temporaries don't have any shadows.
3403 Nevertheless uses of them following the preamble will cause
3404 memcheck to generate references to their shadows. End effect is
3405 to cause IR sanity check failures, due to references to
3406 non-existent shadows. This is only evident for the complex
3407 preambles used for function wrapping on TOC-afflicted platforms
3408 (ppc64-linux, ppc32-aix5, ppc64-aix5).
3409
3410 The following loop therefore scans the preamble looking for
3411 assignments to temporaries. For each one found it creates an
3412 assignment to the corresponding shadow temp, marking it as
3413 'defined'. This is the same resulting IR as if the main
3414 instrumentation loop before had been applied to the statement
3415 'tmp = CONSTANT'.
3416 */
3417 for (j = 0; j < i; j++) {
sewardj0b9d74a2006-12-24 02:24:11 +00003418 if (bb_in->stmts[j]->tag == Ist_WrTmp) {
sewardjf1962d32006-10-19 13:22:16 +00003419 /* findShadowTmp checks its arg is an original tmp;
3420 no need to assert that here. */
sewardj0b9d74a2006-12-24 02:24:11 +00003421 IRTemp tmp_o = bb_in->stmts[j]->Ist.WrTmp.tmp;
sewardjf1962d32006-10-19 13:22:16 +00003422 IRTemp tmp_s = findShadowTmp(&mce, tmp_o);
3423 IRType ty_s = typeOfIRTemp(bb->tyenv, tmp_s);
3424 assign( bb, tmp_s, definedOfType( ty_s ) );
3425 if (0) {
3426 VG_(printf)("create shadow tmp for preamble tmp [%d] ty ", j);
3427 ppIRType( ty_s );
3428 VG_(printf)("\n");
3429 }
3430 }
3431 }
3432
sewardja0871482006-10-18 12:41:55 +00003433 /* Iterate over the remaining stmts to generate instrumentation. */
3434
3435 tl_assert(bb_in->stmts_used > 0);
3436 tl_assert(i >= 0);
3437 tl_assert(i < bb_in->stmts_used);
3438 tl_assert(bb_in->stmts[i]->tag == Ist_IMark);
3439
3440 for (/* use current i*/; i < bb_in->stmts_used; i++) {
sewardj151b90d2005-07-06 19:42:23 +00003441
3442 st = bb_in->stmts[i];
sewardj95448072004-11-22 20:19:51 +00003443 first_stmt = bb->stmts_used;
3444
3445 if (verboze) {
3446 ppIRStmt(st);
3447 VG_(printf)("\n\n");
3448 }
3449
sewardj29faa502005-03-16 18:20:21 +00003450 /* Generate instrumentation code for each stmt ... */
3451
sewardj95448072004-11-22 20:19:51 +00003452 switch (st->tag) {
3453
sewardj0b9d74a2006-12-24 02:24:11 +00003454 case Ist_WrTmp:
3455 assign( bb, findShadowTmp(&mce, st->Ist.WrTmp.tmp),
3456 expr2vbits( &mce, st->Ist.WrTmp.data) );
njn25e49d8e72002-09-23 09:36:25 +00003457 break;
3458
sewardj95448072004-11-22 20:19:51 +00003459 case Ist_Put:
3460 do_shadow_PUT( &mce,
3461 st->Ist.Put.offset,
3462 st->Ist.Put.data,
3463 NULL /* shadow atom */ );
njn25e49d8e72002-09-23 09:36:25 +00003464 break;
3465
sewardj95448072004-11-22 20:19:51 +00003466 case Ist_PutI:
3467 do_shadow_PUTI( &mce,
3468 st->Ist.PutI.descr,
3469 st->Ist.PutI.ix,
3470 st->Ist.PutI.bias,
3471 st->Ist.PutI.data );
njn25e49d8e72002-09-23 09:36:25 +00003472 break;
3473
sewardj2e595852005-06-30 23:33:37 +00003474 case Ist_Store:
3475 do_shadow_Store( &mce, st->Ist.Store.end,
3476 st->Ist.Store.addr, 0/* addr bias */,
3477 st->Ist.Store.data,
3478 NULL /* shadow data */ );
njn25e49d8e72002-09-23 09:36:25 +00003479 break;
3480
sewardj95448072004-11-22 20:19:51 +00003481 case Ist_Exit:
sewardjd5204dc2004-12-31 01:16:11 +00003482 complainIfUndefined( &mce, st->Ist.Exit.guard );
njn25e49d8e72002-09-23 09:36:25 +00003483 break;
3484
sewardj21dc3452005-03-21 00:27:41 +00003485 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00003486 case Ist_IMark:
sewardj72d75132007-11-09 23:06:35 +00003487 case Ist_MBE:
sewardjbd598e12005-01-07 12:10:21 +00003488 break;
3489
sewardj95448072004-11-22 20:19:51 +00003490 case Ist_Dirty:
3491 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
njn25e49d8e72002-09-23 09:36:25 +00003492 break;
3493
sewardj826ec492005-05-12 18:05:00 +00003494 case Ist_AbiHint:
3495 do_AbiHint( &mce, st->Ist.AbiHint.base, st->Ist.AbiHint.len );
3496 break;
3497
njn25e49d8e72002-09-23 09:36:25 +00003498 default:
sewardj95448072004-11-22 20:19:51 +00003499 VG_(printf)("\n");
3500 ppIRStmt(st);
3501 VG_(printf)("\n");
3502 VG_(tool_panic)("memcheck: unhandled IRStmt");
3503
3504 } /* switch (st->tag) */
3505
3506 if (verboze) {
3507 for (j = first_stmt; j < bb->stmts_used; j++) {
3508 VG_(printf)(" ");
3509 ppIRStmt(bb->stmts[j]);
3510 VG_(printf)("\n");
3511 }
3512 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00003513 }
sewardj95448072004-11-22 20:19:51 +00003514
sewardj29faa502005-03-16 18:20:21 +00003515 /* ... and finally copy the stmt itself to the output. */
sewardj0b9d74a2006-12-24 02:24:11 +00003516 addStmtToIRSB(bb, st);
sewardj95448072004-11-22 20:19:51 +00003517
njn25e49d8e72002-09-23 09:36:25 +00003518 }
njn25e49d8e72002-09-23 09:36:25 +00003519
sewardj95448072004-11-22 20:19:51 +00003520 /* Now we need to complain if the jump target is undefined. */
3521 first_stmt = bb->stmts_used;
njn25e49d8e72002-09-23 09:36:25 +00003522
sewardj95448072004-11-22 20:19:51 +00003523 if (verboze) {
3524 VG_(printf)("bb->next = ");
3525 ppIRExpr(bb->next);
3526 VG_(printf)("\n\n");
3527 }
njn25e49d8e72002-09-23 09:36:25 +00003528
sewardj95448072004-11-22 20:19:51 +00003529 complainIfUndefined( &mce, bb->next );
njn25e49d8e72002-09-23 09:36:25 +00003530
sewardj95448072004-11-22 20:19:51 +00003531 if (verboze) {
3532 for (j = first_stmt; j < bb->stmts_used; j++) {
3533 VG_(printf)(" ");
3534 ppIRStmt(bb->stmts[j]);
3535 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00003536 }
sewardj95448072004-11-22 20:19:51 +00003537 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00003538 }
njn25e49d8e72002-09-23 09:36:25 +00003539
sewardj95448072004-11-22 20:19:51 +00003540 return bb;
3541}
njn25e49d8e72002-09-23 09:36:25 +00003542
sewardj81651dc2007-08-28 06:05:20 +00003543/*------------------------------------------------------------*/
3544/*--- Post-tree-build final tidying ---*/
3545/*------------------------------------------------------------*/
3546
3547/* This exploits the observation that Memcheck often produces
3548 repeated conditional calls of the form
3549
3550 Dirty G MC_(helperc_value_check0/1/4/8_fail)()
3551
3552 with the same guard expression G guarding the same helper call.
3553 The second and subsequent calls are redundant. This usually
3554 results from instrumentation of guest code containing multiple
3555 memory references at different constant offsets from the same base
3556 register. After optimisation of the instrumentation, you get a
3557 test for the definedness of the base register for each memory
3558 reference, which is kinda pointless. MC_(final_tidy) therefore
3559 looks for such repeated calls and removes all but the first. */
3560
3561/* A struct for recording which (helper, guard) pairs we have already
3562 seen. */
3563typedef
3564 struct { void* entry; IRExpr* guard; }
3565 Pair;
3566
3567/* Return True if e1 and e2 definitely denote the same value (used to
3568 compare guards). Return False if unknown; False is the safe
3569 answer. Since guest registers and guest memory do not have the
3570 SSA property we must return False if any Gets or Loads appear in
3571 the expression. */
3572
3573static Bool sameIRValue ( IRExpr* e1, IRExpr* e2 )
3574{
3575 if (e1->tag != e2->tag)
3576 return False;
3577 switch (e1->tag) {
3578 case Iex_Const:
3579 return eqIRConst( e1->Iex.Const.con, e2->Iex.Const.con );
3580 case Iex_Binop:
3581 return e1->Iex.Binop.op == e2->Iex.Binop.op
3582 && sameIRValue(e1->Iex.Binop.arg1, e2->Iex.Binop.arg1)
3583 && sameIRValue(e1->Iex.Binop.arg2, e2->Iex.Binop.arg2);
3584 case Iex_Unop:
3585 return e1->Iex.Unop.op == e2->Iex.Unop.op
3586 && sameIRValue(e1->Iex.Unop.arg, e2->Iex.Unop.arg);
3587 case Iex_RdTmp:
3588 return e1->Iex.RdTmp.tmp == e2->Iex.RdTmp.tmp;
3589 case Iex_Mux0X:
3590 return sameIRValue( e1->Iex.Mux0X.cond, e2->Iex.Mux0X.cond )
3591 && sameIRValue( e1->Iex.Mux0X.expr0, e2->Iex.Mux0X.expr0 )
3592 && sameIRValue( e1->Iex.Mux0X.exprX, e2->Iex.Mux0X.exprX );
3593 case Iex_Qop:
3594 case Iex_Triop:
3595 case Iex_CCall:
3596 /* be lazy. Could define equality for these, but they never
3597 appear to be used. */
3598 return False;
3599 case Iex_Get:
3600 case Iex_GetI:
3601 case Iex_Load:
3602 /* be conservative - these may not give the same value each
3603 time */
3604 return False;
3605 case Iex_Binder:
3606 /* should never see this */
3607 /* fallthrough */
3608 default:
3609 VG_(printf)("mc_translate.c: sameIRValue: unhandled: ");
3610 ppIRExpr(e1);
3611 VG_(tool_panic)("memcheck:sameIRValue");
3612 return False;
3613 }
3614}
3615
3616/* See if 'pairs' already has an entry for (entry, guard). Return
3617 True if so. If not, add an entry. */
3618
3619static
3620Bool check_or_add ( XArray* /*of Pair*/ pairs, IRExpr* guard, void* entry )
3621{
3622 Pair p;
3623 Pair* pp;
3624 Int i, n = VG_(sizeXA)( pairs );
3625 for (i = 0; i < n; i++) {
3626 pp = VG_(indexXA)( pairs, i );
3627 if (pp->entry == entry && sameIRValue(pp->guard, guard))
3628 return True;
3629 }
3630 p.guard = guard;
3631 p.entry = entry;
3632 VG_(addToXA)( pairs, &p );
3633 return False;
3634}
3635
3636static Bool is_helperc_value_checkN_fail ( HChar* name )
3637{
3638 return
3639 0==VG_(strcmp)(name, "MC_(helperc_value_check0_fail)")
3640 || 0==VG_(strcmp)(name, "MC_(helperc_value_check1_fail)")
3641 || 0==VG_(strcmp)(name, "MC_(helperc_value_check4_fail)")
3642 || 0==VG_(strcmp)(name, "MC_(helperc_value_check8_fail)");
3643}
3644
3645IRSB* MC_(final_tidy) ( IRSB* sb_in )
3646{
3647 Int i;
3648 IRStmt* st;
3649 IRDirty* di;
3650 IRExpr* guard;
3651 IRCallee* cee;
3652 Bool alreadyPresent;
3653 XArray* pairs = VG_(newXA)( VG_(malloc), VG_(free), sizeof(Pair) );
3654 /* Scan forwards through the statements. Each time a call to one
3655 of the relevant helpers is seen, check if we have made a
3656 previous call to the same helper using the same guard
3657 expression, and if so, delete the call. */
3658 for (i = 0; i < sb_in->stmts_used; i++) {
3659 st = sb_in->stmts[i];
3660 tl_assert(st);
3661 if (st->tag != Ist_Dirty)
3662 continue;
3663 di = st->Ist.Dirty.details;
3664 guard = di->guard;
3665 if (!guard)
3666 continue;
3667 if (0) { ppIRExpr(guard); VG_(printf)("\n"); }
3668 cee = di->cee;
3669 if (!is_helperc_value_checkN_fail( cee->name ))
3670 continue;
3671 /* Ok, we have a call to helperc_value_check0/1/4/8_fail with
3672 guard 'guard'. Check if we have already seen a call to this
3673 function with the same guard. If so, delete it. If not,
3674 add it to the set of calls we do know about. */
3675 alreadyPresent = check_or_add( pairs, guard, cee->addr );
3676 if (alreadyPresent) {
3677 sb_in->stmts[i] = IRStmt_NoOp();
3678 if (0) VG_(printf)("XX\n");
3679 }
3680 }
3681 VG_(deleteXA)( pairs );
3682 return sb_in;
3683}
3684
3685
njn25e49d8e72002-09-23 09:36:25 +00003686/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00003687/*--- end mc_translate.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00003688/*--------------------------------------------------------------------*/