blob: b95caf97094e722fd4f87fba986183250d7b1bfe [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
njn9f207462009-03-10 22:02:09 +000011 Copyright (C) 2000-2009 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)
sewardj81651dc2007-08-28 06:05:20 +000038#include "pub_tool_xarray.h"
39#include "pub_tool_mallocfree.h"
40#include "pub_tool_libcbase.h"
njn25e49d8e72002-09-23 09:36:25 +000041
sewardj7cf4e6b2008-05-01 20:24:26 +000042#include "mc_include.h"
43
44
sewardj992dff92005-10-07 11:08:55 +000045/* This file implements the Memcheck instrumentation, and in
46 particular contains the core of its undefined value detection
47 machinery. For a comprehensive background of the terminology,
48 algorithms and rationale used herein, read:
49
50 Using Valgrind to detect undefined value errors with
51 bit-precision
52
53 Julian Seward and Nicholas Nethercote
54
55 2005 USENIX Annual Technical Conference (General Track),
56 Anaheim, CA, USA, April 10-15, 2005.
njn6665ea22007-05-24 23:14:41 +000057
58 ----
59
60 Here is as good a place as any to record exactly when V bits are and
61 should be checked, why, and what function is responsible.
62
63
64 Memcheck complains when an undefined value is used:
65
66 1. In the condition of a conditional branch. Because it could cause
67 incorrect control flow, and thus cause incorrect externally-visible
68 behaviour. [mc_translate.c:complainIfUndefined]
69
70 2. As an argument to a system call, or as the value that specifies
71 the system call number. Because it could cause an incorrect
72 externally-visible side effect. [mc_translate.c:mc_pre_reg_read]
73
74 3. As the address in a load or store. Because it could cause an
75 incorrect value to be used later, which could cause externally-visible
76 behaviour (eg. via incorrect control flow or an incorrect system call
77 argument) [complainIfUndefined]
78
79 4. As the target address of a branch. Because it could cause incorrect
80 control flow. [complainIfUndefined]
81
82 5. As an argument to setenv, unsetenv, or putenv. Because it could put
83 an incorrect value into the external environment.
84 [mc_replace_strmem.c:VG_WRAP_FUNCTION_ZU(*, *env)]
85
86 6. As the index in a GETI or PUTI operation. I'm not sure why... (njn).
87 [complainIfUndefined]
88
89 7. As an argument to the VALGRIND_CHECK_MEM_IS_DEFINED and
90 VALGRIND_CHECK_VALUE_IS_DEFINED client requests. Because the user
91 requested it. [in memcheck.h]
92
93
94 Memcheck also complains, but should not, when an undefined value is used:
95
96 8. As the shift value in certain SIMD shift operations (but not in the
97 standard integer shift operations). This inconsistency is due to
98 historical reasons.) [complainIfUndefined]
99
100
101 Memcheck does not complain, but should, when an undefined value is used:
102
103 9. As an input to a client request. Because the client request may
104 affect the visible behaviour -- see bug #144362 for an example
105 involving the malloc replacements in vg_replace_malloc.c and
106 VALGRIND_NON_SIMD_CALL* requests, where an uninitialised argument
107 isn't identified. That bug report also has some info on how to solve
108 the problem. [valgrind.h:VALGRIND_DO_CLIENT_REQUEST]
109
110
111 In practice, 1 and 2 account for the vast majority of cases.
sewardj992dff92005-10-07 11:08:55 +0000112*/
113
sewardj95448072004-11-22 20:19:51 +0000114/*------------------------------------------------------------*/
115/*--- Forward decls ---*/
116/*------------------------------------------------------------*/
117
118struct _MCEnv;
119
sewardj7cf4e6b2008-05-01 20:24:26 +0000120static IRType shadowTypeV ( IRType ty );
sewardj95448072004-11-22 20:19:51 +0000121static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
sewardjafa617b2008-07-22 09:59:48 +0000122static IRTemp findShadowTmpB ( struct _MCEnv* mce, IRTemp orig );
sewardj95448072004-11-22 20:19:51 +0000123
124
125/*------------------------------------------------------------*/
126/*--- Memcheck running state, and tmp management. ---*/
127/*------------------------------------------------------------*/
128
129/* Carries around state during memcheck instrumentation. */
130typedef
131 struct _MCEnv {
sewardj0b9d74a2006-12-24 02:24:11 +0000132 /* MODIFIED: the superblock being constructed. IRStmts are
133 added. */
134 IRSB* bb;
sewardj7cf4e6b2008-05-01 20:24:26 +0000135 Bool trace;
sewardj95448072004-11-22 20:19:51 +0000136
137 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
138 original temps to their current their current shadow temp.
139 Initially all entries are IRTemp_INVALID. Entries are added
140 lazily since many original temps are not used due to
141 optimisation prior to instrumentation. Note that floating
142 point original tmps are shadowed by integer tmps of the same
143 size, and Bit-typed original tmps are shadowed by the type
144 Ity_I8. See comment below. */
sewardj7cf4e6b2008-05-01 20:24:26 +0000145 IRTemp* tmpMapV; /* V-bit tmp shadows */
146 IRTemp* tmpMapB; /* origin tracking tmp shadows */
sewardj95448072004-11-22 20:19:51 +0000147 Int n_originalTmps; /* for range checking */
148
sewardjd5204dc2004-12-31 01:16:11 +0000149 /* MODIFIED: indicates whether "bogus" literals have so far been
150 found. Starts off False, and may change to True. */
151 Bool bogusLiterals;
152
sewardj95448072004-11-22 20:19:51 +0000153 /* READONLY: the guest layout. This indicates which parts of
154 the guest state should be regarded as 'always defined'. */
155 VexGuestLayout* layout;
sewardj634ba772006-10-15 12:47:37 +0000156
sewardj95448072004-11-22 20:19:51 +0000157 /* READONLY: the host word type. Needed for constructing
158 arguments of type 'HWord' to be passed to helper functions.
159 Ity_I32 or Ity_I64 only. */
160 IRType hWordTy;
161 }
162 MCEnv;
163
164/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
165 demand), as they are encountered. This is for two reasons.
166
167 (1) (less important reason): Many original tmps are unused due to
168 initial IR optimisation, and we do not want to spaces in tables
169 tracking them.
170
171 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
172 table indexed [0 .. n_types-1], which gives the current shadow for
173 each original tmp, or INVALID_IRTEMP if none is so far assigned.
174 It is necessary to support making multiple assignments to a shadow
175 -- specifically, after testing a shadow for definedness, it needs
176 to be made defined. But IR's SSA property disallows this.
177
178 (2) (more important reason): Therefore, when a shadow needs to get
179 a new value, a new temporary is created, the value is assigned to
180 that, and the tmpMap is updated to reflect the new binding.
181
182 A corollary is that if the tmpMap maps a given tmp to
sewardjf1962d32006-10-19 13:22:16 +0000183 IRTemp_INVALID and we are hoping to read that shadow tmp, it means
sewardj95448072004-11-22 20:19:51 +0000184 there's a read-before-write error in the original tmps. The IR
185 sanity checker should catch all such anomalies, however.
njn25e49d8e72002-09-23 09:36:25 +0000186*/
sewardj95448072004-11-22 20:19:51 +0000187
188/* Find the tmp currently shadowing the given original tmp. If none
189 so far exists, allocate one. */
sewardj7cf4e6b2008-05-01 20:24:26 +0000190static IRTemp findShadowTmpV ( MCEnv* mce, IRTemp orig )
njn25e49d8e72002-09-23 09:36:25 +0000191{
sewardj95448072004-11-22 20:19:51 +0000192 tl_assert(orig < mce->n_originalTmps);
sewardj7cf4e6b2008-05-01 20:24:26 +0000193 if (mce->tmpMapV[orig] == IRTemp_INVALID) {
194 mce->tmpMapV[orig]
sewardj95448072004-11-22 20:19:51 +0000195 = newIRTemp(mce->bb->tyenv,
sewardj7cf4e6b2008-05-01 20:24:26 +0000196 shadowTypeV(mce->bb->tyenv->types[orig]));
njn25e49d8e72002-09-23 09:36:25 +0000197 }
sewardj7cf4e6b2008-05-01 20:24:26 +0000198 return mce->tmpMapV[orig];
njn25e49d8e72002-09-23 09:36:25 +0000199}
200
sewardj95448072004-11-22 20:19:51 +0000201/* Allocate a new shadow for the given original tmp. This means any
202 previous shadow is abandoned. This is needed because it is
203 necessary to give a new value to a shadow once it has been tested
204 for undefinedness, but unfortunately IR's SSA property disallows
205 this. Instead we must abandon the old shadow, allocate a new one
206 and use that instead. */
sewardj7cf4e6b2008-05-01 20:24:26 +0000207static void newShadowTmpV ( MCEnv* mce, IRTemp orig )
njn25e49d8e72002-09-23 09:36:25 +0000208{
sewardj95448072004-11-22 20:19:51 +0000209 tl_assert(orig < mce->n_originalTmps);
sewardj7cf4e6b2008-05-01 20:24:26 +0000210 mce->tmpMapV[orig]
sewardj95448072004-11-22 20:19:51 +0000211 = newIRTemp(mce->bb->tyenv,
sewardj7cf4e6b2008-05-01 20:24:26 +0000212 shadowTypeV(mce->bb->tyenv->types[orig]));
sewardj95448072004-11-22 20:19:51 +0000213}
214
215
216/*------------------------------------------------------------*/
217/*--- IRAtoms -- a subset of IRExprs ---*/
218/*------------------------------------------------------------*/
219
220/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj710d6c22005-03-20 18:55:15 +0000221 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardj95448072004-11-22 20:19:51 +0000222 input, most of this code deals in atoms. Usefully, a value atom
223 always has a V-value which is also an atom: constants are shadowed
224 by constants, and temps are shadowed by the corresponding shadow
225 temporary. */
226
227typedef IRExpr IRAtom;
228
229/* (used for sanity checks only): is this an atom which looks
230 like it's from original code? */
231static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
232{
233 if (a1->tag == Iex_Const)
234 return True;
sewardj0b9d74a2006-12-24 02:24:11 +0000235 if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < mce->n_originalTmps)
sewardj95448072004-11-22 20:19:51 +0000236 return True;
237 return False;
238}
239
240/* (used for sanity checks only): is this an atom which looks
241 like it's from shadow code? */
242static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
243{
244 if (a1->tag == Iex_Const)
245 return True;
sewardj0b9d74a2006-12-24 02:24:11 +0000246 if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= mce->n_originalTmps)
sewardj95448072004-11-22 20:19:51 +0000247 return True;
248 return False;
249}
250
251/* (used for sanity checks only): check that both args are atoms and
252 are identically-kinded. */
253static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
254{
sewardj0b9d74a2006-12-24 02:24:11 +0000255 if (a1->tag == Iex_RdTmp && a2->tag == Iex_RdTmp)
sewardj95448072004-11-22 20:19:51 +0000256 return True;
sewardjbef552a2005-08-30 12:54:36 +0000257 if (a1->tag == Iex_Const && a2->tag == Iex_Const)
sewardj95448072004-11-22 20:19:51 +0000258 return True;
259 return False;
260}
261
262
263/*------------------------------------------------------------*/
264/*--- Type management ---*/
265/*------------------------------------------------------------*/
266
267/* Shadow state is always accessed using integer types. This returns
268 an integer type with the same size (as per sizeofIRType) as the
269 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj3245c912004-12-10 14:58:26 +0000270 I64, V128. */
sewardj95448072004-11-22 20:19:51 +0000271
sewardj7cf4e6b2008-05-01 20:24:26 +0000272static IRType shadowTypeV ( IRType ty )
sewardj95448072004-11-22 20:19:51 +0000273{
274 switch (ty) {
275 case Ity_I1:
276 case Ity_I8:
277 case Ity_I16:
278 case Ity_I32:
sewardj6cf40ff2005-04-20 22:31:26 +0000279 case Ity_I64:
280 case Ity_I128: return ty;
sewardj3245c912004-12-10 14:58:26 +0000281 case Ity_F32: return Ity_I32;
282 case Ity_F64: return Ity_I64;
283 case Ity_V128: return Ity_V128;
sewardj95448072004-11-22 20:19:51 +0000284 default: ppIRType(ty);
sewardj7cf4e6b2008-05-01 20:24:26 +0000285 VG_(tool_panic)("memcheck:shadowTypeV");
sewardj95448072004-11-22 20:19:51 +0000286 }
287}
288
289/* Produce a 'defined' value of the given shadow type. Should only be
290 supplied shadow types (Bit/I8/I16/I32/UI64). */
291static IRExpr* definedOfType ( IRType ty ) {
292 switch (ty) {
sewardj170ee212004-12-10 18:57:51 +0000293 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
294 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
295 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
296 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
297 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
298 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
sewardjf1962d32006-10-19 13:22:16 +0000299 default: VG_(tool_panic)("memcheck:definedOfType");
njn25e49d8e72002-09-23 09:36:25 +0000300 }
301}
302
303
sewardj95448072004-11-22 20:19:51 +0000304/*------------------------------------------------------------*/
305/*--- Constructing IR fragments ---*/
306/*------------------------------------------------------------*/
307
sewardj95448072004-11-22 20:19:51 +0000308/* add stmt to a bb */
sewardj7cf4e6b2008-05-01 20:24:26 +0000309static inline void stmt ( HChar cat, MCEnv* mce, IRStmt* st ) {
310 if (mce->trace) {
311 VG_(printf)(" %c: ", cat);
312 ppIRStmt(st);
313 VG_(printf)("\n");
314 }
315 addStmtToIRSB(mce->bb, st);
316}
317
318/* assign value to tmp */
319static inline
320void assign ( HChar cat, MCEnv* mce, IRTemp tmp, IRExpr* expr ) {
321 stmt(cat, mce, IRStmt_WrTmp(tmp,expr));
322}
sewardj95448072004-11-22 20:19:51 +0000323
324/* build various kinds of expressions */
325#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
326#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
327#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
328#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
329#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
330#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj170ee212004-12-10 18:57:51 +0000331#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardj0b9d74a2006-12-24 02:24:11 +0000332#define mkexpr(_tmp) IRExpr_RdTmp((_tmp))
sewardj95448072004-11-22 20:19:51 +0000333
sewardj7cf4e6b2008-05-01 20:24:26 +0000334/* Bind the given expression to a new temporary, and return the
sewardj95448072004-11-22 20:19:51 +0000335 temporary. This effectively converts an arbitrary expression into
sewardj7cf4e6b2008-05-01 20:24:26 +0000336 an atom.
337
338 'ty' is the type of 'e' and hence the type that the new temporary
339 needs to be. But passing it is redundant, since we can deduce the
340 type merely by inspecting 'e'. So at least that fact to assert
341 that the two types agree. */
342static IRAtom* assignNew ( HChar cat, MCEnv* mce, IRType ty, IRExpr* e ) {
343 IRTemp t;
344 IRType tyE = typeOfIRExpr(mce->bb->tyenv, e);
345 tl_assert(tyE == ty); /* so 'ty' is redundant (!) */
346 t = newIRTemp(mce->bb->tyenv, ty);
347 assign(cat, mce, t, e);
sewardj95448072004-11-22 20:19:51 +0000348 return mkexpr(t);
349}
350
351
352/*------------------------------------------------------------*/
353/*--- Constructing definedness primitive ops ---*/
354/*------------------------------------------------------------*/
355
356/* --------- Defined-if-either-defined --------- */
357
358static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
359 tl_assert(isShadowAtom(mce,a1));
360 tl_assert(isShadowAtom(mce,a2));
sewardj7cf4e6b2008-05-01 20:24:26 +0000361 return assignNew('V', mce, Ity_I8, binop(Iop_And8, a1, a2));
sewardj95448072004-11-22 20:19:51 +0000362}
363
364static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
365 tl_assert(isShadowAtom(mce,a1));
366 tl_assert(isShadowAtom(mce,a2));
sewardj7cf4e6b2008-05-01 20:24:26 +0000367 return assignNew('V', mce, Ity_I16, binop(Iop_And16, a1, a2));
sewardj95448072004-11-22 20:19:51 +0000368}
369
370static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
371 tl_assert(isShadowAtom(mce,a1));
372 tl_assert(isShadowAtom(mce,a2));
sewardj7cf4e6b2008-05-01 20:24:26 +0000373 return assignNew('V', mce, Ity_I32, binop(Iop_And32, a1, a2));
sewardj95448072004-11-22 20:19:51 +0000374}
375
sewardj7010f6e2004-12-10 13:35:22 +0000376static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
377 tl_assert(isShadowAtom(mce,a1));
378 tl_assert(isShadowAtom(mce,a2));
sewardj7cf4e6b2008-05-01 20:24:26 +0000379 return assignNew('V', mce, Ity_I64, binop(Iop_And64, a1, a2));
sewardj7010f6e2004-12-10 13:35:22 +0000380}
381
sewardj20d38f22005-02-07 23:50:18 +0000382static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj170ee212004-12-10 18:57:51 +0000383 tl_assert(isShadowAtom(mce,a1));
384 tl_assert(isShadowAtom(mce,a2));
sewardj7cf4e6b2008-05-01 20:24:26 +0000385 return assignNew('V', mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj170ee212004-12-10 18:57:51 +0000386}
387
sewardj95448072004-11-22 20:19:51 +0000388/* --------- Undefined-if-either-undefined --------- */
389
390static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
391 tl_assert(isShadowAtom(mce,a1));
392 tl_assert(isShadowAtom(mce,a2));
sewardj7cf4e6b2008-05-01 20:24:26 +0000393 return assignNew('V', mce, Ity_I8, binop(Iop_Or8, a1, a2));
sewardj95448072004-11-22 20:19:51 +0000394}
395
396static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
397 tl_assert(isShadowAtom(mce,a1));
398 tl_assert(isShadowAtom(mce,a2));
sewardj7cf4e6b2008-05-01 20:24:26 +0000399 return assignNew('V', mce, Ity_I16, binop(Iop_Or16, a1, a2));
sewardj95448072004-11-22 20:19:51 +0000400}
401
402static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
403 tl_assert(isShadowAtom(mce,a1));
404 tl_assert(isShadowAtom(mce,a2));
sewardj7cf4e6b2008-05-01 20:24:26 +0000405 return assignNew('V', mce, Ity_I32, binop(Iop_Or32, a1, a2));
sewardj95448072004-11-22 20:19:51 +0000406}
407
408static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
409 tl_assert(isShadowAtom(mce,a1));
410 tl_assert(isShadowAtom(mce,a2));
sewardj7cf4e6b2008-05-01 20:24:26 +0000411 return assignNew('V', mce, Ity_I64, binop(Iop_Or64, a1, a2));
sewardj95448072004-11-22 20:19:51 +0000412}
413
sewardj20d38f22005-02-07 23:50:18 +0000414static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj3245c912004-12-10 14:58:26 +0000415 tl_assert(isShadowAtom(mce,a1));
416 tl_assert(isShadowAtom(mce,a2));
sewardj7cf4e6b2008-05-01 20:24:26 +0000417 return assignNew('V', mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj3245c912004-12-10 14:58:26 +0000418}
419
sewardje50a1b12004-12-17 01:24:54 +0000420static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardj95448072004-11-22 20:19:51 +0000421 switch (vty) {
sewardje50a1b12004-12-17 01:24:54 +0000422 case Ity_I8: return mkUifU8(mce, a1, a2);
sewardja1d93302004-12-12 16:45:06 +0000423 case Ity_I16: return mkUifU16(mce, a1, a2);
424 case Ity_I32: return mkUifU32(mce, a1, a2);
425 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardj20d38f22005-02-07 23:50:18 +0000426 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardj95448072004-11-22 20:19:51 +0000427 default:
428 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
429 VG_(tool_panic)("memcheck:mkUifU");
njn25e49d8e72002-09-23 09:36:25 +0000430 }
431}
432
sewardj95448072004-11-22 20:19:51 +0000433/* --------- The Left-family of operations. --------- */
njn25e49d8e72002-09-23 09:36:25 +0000434
sewardj95448072004-11-22 20:19:51 +0000435static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
436 tl_assert(isShadowAtom(mce,a1));
sewardj7cf4e6b2008-05-01 20:24:26 +0000437 return assignNew('V', mce, Ity_I8, unop(Iop_Left8, a1));
sewardj95448072004-11-22 20:19:51 +0000438}
439
440static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
441 tl_assert(isShadowAtom(mce,a1));
sewardj7cf4e6b2008-05-01 20:24:26 +0000442 return assignNew('V', mce, Ity_I16, unop(Iop_Left16, a1));
sewardj95448072004-11-22 20:19:51 +0000443}
444
445static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
446 tl_assert(isShadowAtom(mce,a1));
sewardj7cf4e6b2008-05-01 20:24:26 +0000447 return assignNew('V', mce, Ity_I32, unop(Iop_Left32, a1));
sewardj95448072004-11-22 20:19:51 +0000448}
449
sewardj681be302005-01-15 20:43:58 +0000450static IRAtom* mkLeft64 ( MCEnv* mce, IRAtom* a1 ) {
451 tl_assert(isShadowAtom(mce,a1));
sewardj7cf4e6b2008-05-01 20:24:26 +0000452 return assignNew('V', mce, Ity_I64, unop(Iop_Left64, a1));
sewardj681be302005-01-15 20:43:58 +0000453}
454
sewardj95448072004-11-22 20:19:51 +0000455/* --------- 'Improvement' functions for AND/OR. --------- */
456
457/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
458 defined (0); all other -> undefined (1).
459*/
460static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
njn25e49d8e72002-09-23 09:36:25 +0000461{
sewardj95448072004-11-22 20:19:51 +0000462 tl_assert(isOriginalAtom(mce, data));
463 tl_assert(isShadowAtom(mce, vbits));
464 tl_assert(sameKindedAtoms(data, vbits));
sewardj7cf4e6b2008-05-01 20:24:26 +0000465 return assignNew('V', mce, Ity_I8, binop(Iop_Or8, data, vbits));
sewardj95448072004-11-22 20:19:51 +0000466}
njn25e49d8e72002-09-23 09:36:25 +0000467
sewardj95448072004-11-22 20:19:51 +0000468static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
469{
470 tl_assert(isOriginalAtom(mce, data));
471 tl_assert(isShadowAtom(mce, vbits));
472 tl_assert(sameKindedAtoms(data, vbits));
sewardj7cf4e6b2008-05-01 20:24:26 +0000473 return assignNew('V', mce, Ity_I16, binop(Iop_Or16, data, vbits));
sewardj95448072004-11-22 20:19:51 +0000474}
njn25e49d8e72002-09-23 09:36:25 +0000475
sewardj95448072004-11-22 20:19:51 +0000476static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
477{
478 tl_assert(isOriginalAtom(mce, data));
479 tl_assert(isShadowAtom(mce, vbits));
480 tl_assert(sameKindedAtoms(data, vbits));
sewardj7cf4e6b2008-05-01 20:24:26 +0000481 return assignNew('V', mce, Ity_I32, binop(Iop_Or32, data, vbits));
sewardj95448072004-11-22 20:19:51 +0000482}
njn25e49d8e72002-09-23 09:36:25 +0000483
sewardj7010f6e2004-12-10 13:35:22 +0000484static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
485{
486 tl_assert(isOriginalAtom(mce, data));
487 tl_assert(isShadowAtom(mce, vbits));
488 tl_assert(sameKindedAtoms(data, vbits));
sewardj7cf4e6b2008-05-01 20:24:26 +0000489 return assignNew('V', mce, Ity_I64, binop(Iop_Or64, data, vbits));
sewardj7010f6e2004-12-10 13:35:22 +0000490}
491
sewardj20d38f22005-02-07 23:50:18 +0000492static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj170ee212004-12-10 18:57:51 +0000493{
494 tl_assert(isOriginalAtom(mce, data));
495 tl_assert(isShadowAtom(mce, vbits));
496 tl_assert(sameKindedAtoms(data, vbits));
sewardj7cf4e6b2008-05-01 20:24:26 +0000497 return assignNew('V', mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj170ee212004-12-10 18:57:51 +0000498}
499
sewardj95448072004-11-22 20:19:51 +0000500/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
501 defined (0); all other -> undefined (1).
502*/
503static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
504{
505 tl_assert(isOriginalAtom(mce, data));
506 tl_assert(isShadowAtom(mce, vbits));
507 tl_assert(sameKindedAtoms(data, vbits));
508 return assignNew(
sewardj7cf4e6b2008-05-01 20:24:26 +0000509 'V', mce, Ity_I8,
sewardj95448072004-11-22 20:19:51 +0000510 binop(Iop_Or8,
sewardj7cf4e6b2008-05-01 20:24:26 +0000511 assignNew('V', mce, Ity_I8, unop(Iop_Not8, data)),
sewardj95448072004-11-22 20:19:51 +0000512 vbits) );
513}
njn25e49d8e72002-09-23 09:36:25 +0000514
sewardj95448072004-11-22 20:19:51 +0000515static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
516{
517 tl_assert(isOriginalAtom(mce, data));
518 tl_assert(isShadowAtom(mce, vbits));
519 tl_assert(sameKindedAtoms(data, vbits));
520 return assignNew(
sewardj7cf4e6b2008-05-01 20:24:26 +0000521 'V', mce, Ity_I16,
sewardj95448072004-11-22 20:19:51 +0000522 binop(Iop_Or16,
sewardj7cf4e6b2008-05-01 20:24:26 +0000523 assignNew('V', mce, Ity_I16, unop(Iop_Not16, data)),
sewardj95448072004-11-22 20:19:51 +0000524 vbits) );
525}
njn25e49d8e72002-09-23 09:36:25 +0000526
sewardj95448072004-11-22 20:19:51 +0000527static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
528{
529 tl_assert(isOriginalAtom(mce, data));
530 tl_assert(isShadowAtom(mce, vbits));
531 tl_assert(sameKindedAtoms(data, vbits));
532 return assignNew(
sewardj7cf4e6b2008-05-01 20:24:26 +0000533 'V', mce, Ity_I32,
sewardj95448072004-11-22 20:19:51 +0000534 binop(Iop_Or32,
sewardj7cf4e6b2008-05-01 20:24:26 +0000535 assignNew('V', mce, Ity_I32, unop(Iop_Not32, data)),
sewardj95448072004-11-22 20:19:51 +0000536 vbits) );
537}
538
sewardj7010f6e2004-12-10 13:35:22 +0000539static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
540{
541 tl_assert(isOriginalAtom(mce, data));
542 tl_assert(isShadowAtom(mce, vbits));
543 tl_assert(sameKindedAtoms(data, vbits));
544 return assignNew(
sewardj7cf4e6b2008-05-01 20:24:26 +0000545 'V', mce, Ity_I64,
sewardj7010f6e2004-12-10 13:35:22 +0000546 binop(Iop_Or64,
sewardj7cf4e6b2008-05-01 20:24:26 +0000547 assignNew('V', mce, Ity_I64, unop(Iop_Not64, data)),
sewardj7010f6e2004-12-10 13:35:22 +0000548 vbits) );
549}
550
sewardj20d38f22005-02-07 23:50:18 +0000551static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj170ee212004-12-10 18:57:51 +0000552{
553 tl_assert(isOriginalAtom(mce, data));
554 tl_assert(isShadowAtom(mce, vbits));
555 tl_assert(sameKindedAtoms(data, vbits));
556 return assignNew(
sewardj7cf4e6b2008-05-01 20:24:26 +0000557 'V', mce, Ity_V128,
sewardj20d38f22005-02-07 23:50:18 +0000558 binop(Iop_OrV128,
sewardj7cf4e6b2008-05-01 20:24:26 +0000559 assignNew('V', mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj170ee212004-12-10 18:57:51 +0000560 vbits) );
561}
562
sewardj95448072004-11-22 20:19:51 +0000563/* --------- Pessimising casts. --------- */
564
565static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
566{
sewardj4cc684b2007-08-25 23:09:36 +0000567 IRType src_ty;
sewardj7cf97ee2004-11-28 14:25:01 +0000568 IRAtom* tmp1;
sewardj95448072004-11-22 20:19:51 +0000569 /* Note, dst_ty is a shadow type, not an original type. */
570 /* First of all, collapse vbits down to a single bit. */
571 tl_assert(isShadowAtom(mce,vbits));
sewardj4cc684b2007-08-25 23:09:36 +0000572 src_ty = typeOfIRExpr(mce->bb->tyenv, vbits);
573
574 /* Fast-track some common cases */
575 if (src_ty == Ity_I32 && dst_ty == Ity_I32)
sewardj7cf4e6b2008-05-01 20:24:26 +0000576 return assignNew('V', mce, Ity_I32, unop(Iop_CmpwNEZ32, vbits));
sewardj4cc684b2007-08-25 23:09:36 +0000577
578 if (src_ty == Ity_I64 && dst_ty == Ity_I64)
sewardj7cf4e6b2008-05-01 20:24:26 +0000579 return assignNew('V', mce, Ity_I64, unop(Iop_CmpwNEZ64, vbits));
sewardj4cc684b2007-08-25 23:09:36 +0000580
581 if (src_ty == Ity_I32 && dst_ty == Ity_I64) {
sewardj7cf4e6b2008-05-01 20:24:26 +0000582 IRAtom* tmp = assignNew('V', mce, Ity_I32, unop(Iop_CmpwNEZ32, vbits));
583 return assignNew('V', mce, Ity_I64, binop(Iop_32HLto64, tmp, tmp));
sewardj4cc684b2007-08-25 23:09:36 +0000584 }
585
586 /* Else do it the slow way .. */
587 tmp1 = NULL;
588 switch (src_ty) {
sewardj95448072004-11-22 20:19:51 +0000589 case Ity_I1:
590 tmp1 = vbits;
njn25e49d8e72002-09-23 09:36:25 +0000591 break;
sewardj95448072004-11-22 20:19:51 +0000592 case Ity_I8:
sewardj7cf4e6b2008-05-01 20:24:26 +0000593 tmp1 = assignNew('V', mce, Ity_I1, unop(Iop_CmpNEZ8, vbits));
sewardj95448072004-11-22 20:19:51 +0000594 break;
595 case Ity_I16:
sewardj7cf4e6b2008-05-01 20:24:26 +0000596 tmp1 = assignNew('V', mce, Ity_I1, unop(Iop_CmpNEZ16, vbits));
sewardj95448072004-11-22 20:19:51 +0000597 break;
598 case Ity_I32:
sewardj7cf4e6b2008-05-01 20:24:26 +0000599 tmp1 = assignNew('V', mce, Ity_I1, unop(Iop_CmpNEZ32, vbits));
sewardj95448072004-11-22 20:19:51 +0000600 break;
601 case Ity_I64:
sewardj7cf4e6b2008-05-01 20:24:26 +0000602 tmp1 = assignNew('V', mce, Ity_I1, unop(Iop_CmpNEZ64, vbits));
sewardj95448072004-11-22 20:19:51 +0000603 break;
sewardj69a13322005-04-23 01:14:51 +0000604 case Ity_I128: {
605 /* Gah. Chop it in half, OR the halves together, and compare
606 that with zero. */
sewardj7cf4e6b2008-05-01 20:24:26 +0000607 IRAtom* tmp2 = assignNew('V', mce, Ity_I64, unop(Iop_128HIto64, vbits));
608 IRAtom* tmp3 = assignNew('V', mce, Ity_I64, unop(Iop_128to64, vbits));
609 IRAtom* tmp4 = assignNew('V', mce, Ity_I64, binop(Iop_Or64, tmp2, tmp3));
610 tmp1 = assignNew('V', mce, Ity_I1,
sewardj37c31cc2005-04-26 23:49:24 +0000611 unop(Iop_CmpNEZ64, tmp4));
sewardj69a13322005-04-23 01:14:51 +0000612 break;
613 }
sewardj95448072004-11-22 20:19:51 +0000614 default:
sewardj4cc684b2007-08-25 23:09:36 +0000615 ppIRType(src_ty);
sewardj95448072004-11-22 20:19:51 +0000616 VG_(tool_panic)("mkPCastTo(1)");
617 }
618 tl_assert(tmp1);
619 /* Now widen up to the dst type. */
620 switch (dst_ty) {
621 case Ity_I1:
622 return tmp1;
623 case Ity_I8:
sewardj7cf4e6b2008-05-01 20:24:26 +0000624 return assignNew('V', mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardj95448072004-11-22 20:19:51 +0000625 case Ity_I16:
sewardj7cf4e6b2008-05-01 20:24:26 +0000626 return assignNew('V', mce, Ity_I16, unop(Iop_1Sto16, tmp1));
sewardj95448072004-11-22 20:19:51 +0000627 case Ity_I32:
sewardj7cf4e6b2008-05-01 20:24:26 +0000628 return assignNew('V', mce, Ity_I32, unop(Iop_1Sto32, tmp1));
sewardj95448072004-11-22 20:19:51 +0000629 case Ity_I64:
sewardj7cf4e6b2008-05-01 20:24:26 +0000630 return assignNew('V', mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardja1d93302004-12-12 16:45:06 +0000631 case Ity_V128:
sewardj7cf4e6b2008-05-01 20:24:26 +0000632 tmp1 = assignNew('V', mce, Ity_I64, unop(Iop_1Sto64, tmp1));
633 tmp1 = assignNew('V', mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardja1d93302004-12-12 16:45:06 +0000634 return tmp1;
sewardj69a13322005-04-23 01:14:51 +0000635 case Ity_I128:
sewardj7cf4e6b2008-05-01 20:24:26 +0000636 tmp1 = assignNew('V', mce, Ity_I64, unop(Iop_1Sto64, tmp1));
637 tmp1 = assignNew('V', mce, Ity_I128, binop(Iop_64HLto128, tmp1, tmp1));
sewardj69a13322005-04-23 01:14:51 +0000638 return tmp1;
sewardj95448072004-11-22 20:19:51 +0000639 default:
640 ppIRType(dst_ty);
641 VG_(tool_panic)("mkPCastTo(2)");
642 }
643}
644
sewardjd5204dc2004-12-31 01:16:11 +0000645/* --------- Accurate interpretation of CmpEQ/CmpNE. --------- */
646/*
647 Normally, we can do CmpEQ/CmpNE by doing UifU on the arguments, and
648 PCasting to Ity_U1. However, sometimes it is necessary to be more
649 accurate. The insight is that the result is defined if two
650 corresponding bits can be found, one from each argument, so that
651 both bits are defined but are different -- that makes EQ say "No"
652 and NE say "Yes". Hence, we compute an improvement term and DifD
653 it onto the "normal" (UifU) result.
654
655 The result is:
656
657 PCastTo<1> (
sewardje6f8af42005-07-06 18:48:59 +0000658 -- naive version
659 PCastTo<sz>( UifU<sz>(vxx, vyy) )
660
sewardjd5204dc2004-12-31 01:16:11 +0000661 `DifD<sz>`
sewardje6f8af42005-07-06 18:48:59 +0000662
663 -- improvement term
664 PCastTo<sz>( PCast<sz>( CmpEQ<sz> ( vec, 1...1 ) ) )
sewardjd5204dc2004-12-31 01:16:11 +0000665 )
sewardje6f8af42005-07-06 18:48:59 +0000666
sewardjd5204dc2004-12-31 01:16:11 +0000667 where
668 vec contains 0 (defined) bits where the corresponding arg bits
sewardje6f8af42005-07-06 18:48:59 +0000669 are defined but different, and 1 bits otherwise.
sewardjd5204dc2004-12-31 01:16:11 +0000670
sewardje6f8af42005-07-06 18:48:59 +0000671 vec = Or<sz>( vxx, // 0 iff bit defined
672 vyy, // 0 iff bit defined
673 Not<sz>(Xor<sz>( xx, yy )) // 0 iff bits different
674 )
675
676 If any bit of vec is 0, the result is defined and so the
677 improvement term should produce 0...0, else it should produce
678 1...1.
679
680 Hence require for the improvement term:
681
682 if vec == 1...1 then 1...1 else 0...0
683 ->
684 PCast<sz>( CmpEQ<sz> ( vec, 1...1 ) )
685
686 This was extensively re-analysed and checked on 6 July 05.
sewardjd5204dc2004-12-31 01:16:11 +0000687*/
688static IRAtom* expensiveCmpEQorNE ( MCEnv* mce,
689 IRType ty,
690 IRAtom* vxx, IRAtom* vyy,
691 IRAtom* xx, IRAtom* yy )
692{
sewardje6f8af42005-07-06 18:48:59 +0000693 IRAtom *naive, *vec, *improvement_term;
694 IRAtom *improved, *final_cast, *top;
695 IROp opDIFD, opUIFU, opXOR, opNOT, opCMP, opOR;
sewardjd5204dc2004-12-31 01:16:11 +0000696
697 tl_assert(isShadowAtom(mce,vxx));
698 tl_assert(isShadowAtom(mce,vyy));
699 tl_assert(isOriginalAtom(mce,xx));
700 tl_assert(isOriginalAtom(mce,yy));
701 tl_assert(sameKindedAtoms(vxx,xx));
702 tl_assert(sameKindedAtoms(vyy,yy));
703
704 switch (ty) {
705 case Ity_I32:
sewardje6f8af42005-07-06 18:48:59 +0000706 opOR = Iop_Or32;
sewardjd5204dc2004-12-31 01:16:11 +0000707 opDIFD = Iop_And32;
708 opUIFU = Iop_Or32;
709 opNOT = Iop_Not32;
710 opXOR = Iop_Xor32;
711 opCMP = Iop_CmpEQ32;
712 top = mkU32(0xFFFFFFFF);
713 break;
tomcd986332005-04-26 07:44:48 +0000714 case Ity_I64:
sewardje6f8af42005-07-06 18:48:59 +0000715 opOR = Iop_Or64;
tomcd986332005-04-26 07:44:48 +0000716 opDIFD = Iop_And64;
717 opUIFU = Iop_Or64;
718 opNOT = Iop_Not64;
719 opXOR = Iop_Xor64;
720 opCMP = Iop_CmpEQ64;
sewardj37c31cc2005-04-26 23:49:24 +0000721 top = mkU64(0xFFFFFFFFFFFFFFFFULL);
tomcd986332005-04-26 07:44:48 +0000722 break;
sewardjd5204dc2004-12-31 01:16:11 +0000723 default:
724 VG_(tool_panic)("expensiveCmpEQorNE");
725 }
726
727 naive
sewardj7cf4e6b2008-05-01 20:24:26 +0000728 = mkPCastTo(mce,ty,
729 assignNew('V', mce, ty, binop(opUIFU, vxx, vyy)));
sewardjd5204dc2004-12-31 01:16:11 +0000730
731 vec
732 = assignNew(
sewardj7cf4e6b2008-05-01 20:24:26 +0000733 'V', mce,ty,
sewardje6f8af42005-07-06 18:48:59 +0000734 binop( opOR,
sewardj7cf4e6b2008-05-01 20:24:26 +0000735 assignNew('V', mce,ty, binop(opOR, vxx, vyy)),
sewardjd5204dc2004-12-31 01:16:11 +0000736 assignNew(
sewardj7cf4e6b2008-05-01 20:24:26 +0000737 'V', mce,ty,
sewardjd5204dc2004-12-31 01:16:11 +0000738 unop( opNOT,
sewardj7cf4e6b2008-05-01 20:24:26 +0000739 assignNew('V', mce,ty, binop(opXOR, xx, yy))))));
sewardjd5204dc2004-12-31 01:16:11 +0000740
sewardje6f8af42005-07-06 18:48:59 +0000741 improvement_term
sewardj7cf4e6b2008-05-01 20:24:26 +0000742 = mkPCastTo( mce,ty,
743 assignNew('V', mce,Ity_I1, binop(opCMP, vec, top)));
sewardjd5204dc2004-12-31 01:16:11 +0000744
745 improved
sewardj7cf4e6b2008-05-01 20:24:26 +0000746 = assignNew( 'V', mce,ty, binop(opDIFD, naive, improvement_term) );
sewardjd5204dc2004-12-31 01:16:11 +0000747
748 final_cast
749 = mkPCastTo( mce, Ity_I1, improved );
750
751 return final_cast;
752}
753
sewardj95448072004-11-22 20:19:51 +0000754
sewardj992dff92005-10-07 11:08:55 +0000755/* --------- Semi-accurate interpretation of CmpORD. --------- */
756
757/* CmpORD32{S,U} does PowerPC-style 3-way comparisons:
758
759 CmpORD32S(x,y) = 1<<3 if x <s y
760 = 1<<2 if x >s y
761 = 1<<1 if x == y
762
763 and similarly the unsigned variant. The default interpretation is:
764
765 CmpORD32{S,U}#(x,y,x#,y#) = PCast(x# `UifU` y#)
sewardj1bc82102005-12-23 00:16:24 +0000766 & (7<<1)
sewardj992dff92005-10-07 11:08:55 +0000767
768 The "& (7<<1)" reflects the fact that all result bits except 3,2,1
769 are zero and therefore defined (viz, zero).
sewardja9e62a92005-10-07 12:13:21 +0000770
771 Also deal with a special case better:
772
773 CmpORD32S(x,0)
774
775 Here, bit 3 (LT) of the result is a copy of the top bit of x and
776 will be defined even if the rest of x isn't. In which case we do:
777
778 CmpORD32S#(x,x#,0,{impliedly 0}#)
sewardj1bc82102005-12-23 00:16:24 +0000779 = PCast(x#) & (3<<1) -- standard interp for GT#,EQ#
780 | (x# >>u 31) << 3 -- LT# = x#[31]
sewardja9e62a92005-10-07 12:13:21 +0000781
sewardj1bc82102005-12-23 00:16:24 +0000782 Analogous handling for CmpORD64{S,U}.
sewardj992dff92005-10-07 11:08:55 +0000783*/
sewardja9e62a92005-10-07 12:13:21 +0000784static Bool isZeroU32 ( IRAtom* e )
785{
786 return
787 toBool( e->tag == Iex_Const
788 && e->Iex.Const.con->tag == Ico_U32
789 && e->Iex.Const.con->Ico.U32 == 0 );
790}
791
sewardj1bc82102005-12-23 00:16:24 +0000792static Bool isZeroU64 ( IRAtom* e )
sewardj992dff92005-10-07 11:08:55 +0000793{
sewardj1bc82102005-12-23 00:16:24 +0000794 return
795 toBool( e->tag == Iex_Const
796 && e->Iex.Const.con->tag == Ico_U64
797 && e->Iex.Const.con->Ico.U64 == 0 );
798}
799
800static IRAtom* doCmpORD ( MCEnv* mce,
801 IROp cmp_op,
802 IRAtom* xxhash, IRAtom* yyhash,
803 IRAtom* xx, IRAtom* yy )
804{
805 Bool m64 = cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD64U;
806 Bool syned = cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD32S;
807 IROp opOR = m64 ? Iop_Or64 : Iop_Or32;
808 IROp opAND = m64 ? Iop_And64 : Iop_And32;
809 IROp opSHL = m64 ? Iop_Shl64 : Iop_Shl32;
810 IROp opSHR = m64 ? Iop_Shr64 : Iop_Shr32;
811 IRType ty = m64 ? Ity_I64 : Ity_I32;
812 Int width = m64 ? 64 : 32;
813
814 Bool (*isZero)(IRAtom*) = m64 ? isZeroU64 : isZeroU32;
815
816 IRAtom* threeLeft1 = NULL;
817 IRAtom* sevenLeft1 = NULL;
818
sewardj992dff92005-10-07 11:08:55 +0000819 tl_assert(isShadowAtom(mce,xxhash));
820 tl_assert(isShadowAtom(mce,yyhash));
821 tl_assert(isOriginalAtom(mce,xx));
822 tl_assert(isOriginalAtom(mce,yy));
823 tl_assert(sameKindedAtoms(xxhash,xx));
824 tl_assert(sameKindedAtoms(yyhash,yy));
sewardj1bc82102005-12-23 00:16:24 +0000825 tl_assert(cmp_op == Iop_CmpORD32S || cmp_op == Iop_CmpORD32U
826 || cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD64U);
sewardj992dff92005-10-07 11:08:55 +0000827
sewardja9e62a92005-10-07 12:13:21 +0000828 if (0) {
829 ppIROp(cmp_op); VG_(printf)(" ");
830 ppIRExpr(xx); VG_(printf)(" "); ppIRExpr( yy ); VG_(printf)("\n");
831 }
832
sewardj1bc82102005-12-23 00:16:24 +0000833 if (syned && isZero(yy)) {
sewardja9e62a92005-10-07 12:13:21 +0000834 /* fancy interpretation */
835 /* if yy is zero, then it must be fully defined (zero#). */
sewardj1bc82102005-12-23 00:16:24 +0000836 tl_assert(isZero(yyhash));
837 threeLeft1 = m64 ? mkU64(3<<1) : mkU32(3<<1);
sewardja9e62a92005-10-07 12:13:21 +0000838 return
839 binop(
sewardj1bc82102005-12-23 00:16:24 +0000840 opOR,
sewardja9e62a92005-10-07 12:13:21 +0000841 assignNew(
sewardj7cf4e6b2008-05-01 20:24:26 +0000842 'V', mce,ty,
sewardja9e62a92005-10-07 12:13:21 +0000843 binop(
sewardj1bc82102005-12-23 00:16:24 +0000844 opAND,
845 mkPCastTo(mce,ty, xxhash),
846 threeLeft1
sewardja9e62a92005-10-07 12:13:21 +0000847 )),
848 assignNew(
sewardj7cf4e6b2008-05-01 20:24:26 +0000849 'V', mce,ty,
sewardja9e62a92005-10-07 12:13:21 +0000850 binop(
sewardj1bc82102005-12-23 00:16:24 +0000851 opSHL,
sewardja9e62a92005-10-07 12:13:21 +0000852 assignNew(
sewardj7cf4e6b2008-05-01 20:24:26 +0000853 'V', mce,ty,
sewardj1bc82102005-12-23 00:16:24 +0000854 binop(opSHR, xxhash, mkU8(width-1))),
sewardja9e62a92005-10-07 12:13:21 +0000855 mkU8(3)
856 ))
857 );
858 } else {
859 /* standard interpretation */
sewardj1bc82102005-12-23 00:16:24 +0000860 sevenLeft1 = m64 ? mkU64(7<<1) : mkU32(7<<1);
sewardja9e62a92005-10-07 12:13:21 +0000861 return
862 binop(
sewardj1bc82102005-12-23 00:16:24 +0000863 opAND,
864 mkPCastTo( mce,ty,
865 mkUifU(mce,ty, xxhash,yyhash)),
866 sevenLeft1
sewardja9e62a92005-10-07 12:13:21 +0000867 );
868 }
sewardj992dff92005-10-07 11:08:55 +0000869}
870
871
sewardj95448072004-11-22 20:19:51 +0000872/*------------------------------------------------------------*/
873/*--- Emit a test and complaint if something is undefined. ---*/
874/*------------------------------------------------------------*/
875
sewardj7cf4e6b2008-05-01 20:24:26 +0000876static IRAtom* schemeE ( MCEnv* mce, IRExpr* e ); /* fwds */
877
878
sewardj95448072004-11-22 20:19:51 +0000879/* Set the annotations on a dirty helper to indicate that the stack
880 pointer and instruction pointers might be read. This is the
881 behaviour of all 'emit-a-complaint' style functions we might
882 call. */
883
884static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
885 di->nFxState = 2;
886 di->fxState[0].fx = Ifx_Read;
887 di->fxState[0].offset = mce->layout->offset_SP;
888 di->fxState[0].size = mce->layout->sizeof_SP;
889 di->fxState[1].fx = Ifx_Read;
890 di->fxState[1].offset = mce->layout->offset_IP;
891 di->fxState[1].size = mce->layout->sizeof_IP;
892}
893
894
895/* Check the supplied **original** atom for undefinedness, and emit a
896 complaint if so. Once that happens, mark it as defined. This is
897 possible because the atom is either a tmp or literal. If it's a
898 tmp, it will be shadowed by a tmp, and so we can set the shadow to
899 be defined. In fact as mentioned above, we will have to allocate a
900 new tmp to carry the new 'defined' shadow value, and update the
901 original->tmp mapping accordingly; we cannot simply assign a new
902 value to an existing shadow tmp as this breaks SSAness -- resulting
903 in the post-instrumentation sanity checker spluttering in disapproval.
904*/
905static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
906{
sewardj7cf97ee2004-11-28 14:25:01 +0000907 IRAtom* vatom;
908 IRType ty;
909 Int sz;
910 IRDirty* di;
911 IRAtom* cond;
sewardj7cf4e6b2008-05-01 20:24:26 +0000912 IRAtom* origin;
913 void* fn;
914 HChar* nm;
915 IRExpr** args;
916 Int nargs;
sewardj7cf97ee2004-11-28 14:25:01 +0000917
njn1d0825f2006-03-27 11:37:07 +0000918 // Don't do V bit tests if we're not reporting undefined value errors.
sewardj7cf4e6b2008-05-01 20:24:26 +0000919 if (MC_(clo_mc_level) == 1)
njn1d0825f2006-03-27 11:37:07 +0000920 return;
921
sewardj95448072004-11-22 20:19:51 +0000922 /* Since the original expression is atomic, there's no duplicated
923 work generated by making multiple V-expressions for it. So we
924 don't really care about the possibility that someone else may
925 also create a V-interpretion for it. */
926 tl_assert(isOriginalAtom(mce, atom));
sewardj7cf97ee2004-11-28 14:25:01 +0000927 vatom = expr2vbits( mce, atom );
sewardj95448072004-11-22 20:19:51 +0000928 tl_assert(isShadowAtom(mce, vatom));
929 tl_assert(sameKindedAtoms(atom, vatom));
930
sewardj7cf97ee2004-11-28 14:25:01 +0000931 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj95448072004-11-22 20:19:51 +0000932
933 /* sz is only used for constructing the error message */
sewardj7cf97ee2004-11-28 14:25:01 +0000934 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardj95448072004-11-22 20:19:51 +0000935
sewardj7cf97ee2004-11-28 14:25:01 +0000936 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardj95448072004-11-22 20:19:51 +0000937 /* cond will be 0 if all defined, and 1 if any not defined. */
938
sewardj7cf4e6b2008-05-01 20:24:26 +0000939 /* Get the origin info for the value we are about to check. At
940 least, if we are doing origin tracking. If not, use a dummy
941 zero origin. */
942 if (MC_(clo_mc_level) == 3) {
943 origin = schemeE( mce, atom );
944 if (mce->hWordTy == Ity_I64) {
945 origin = assignNew( 'B', mce, Ity_I64, unop(Iop_32Uto64, origin) );
946 }
947 } else {
948 origin = NULL;
949 }
950
951 fn = NULL;
952 nm = NULL;
953 args = NULL;
954 nargs = -1;
955
sewardj95448072004-11-22 20:19:51 +0000956 switch (sz) {
957 case 0:
sewardj7cf4e6b2008-05-01 20:24:26 +0000958 if (origin) {
959 fn = &MC_(helperc_value_check0_fail_w_o);
960 nm = "MC_(helperc_value_check0_fail_w_o)";
961 args = mkIRExprVec_1(origin);
962 nargs = 1;
963 } else {
964 fn = &MC_(helperc_value_check0_fail_no_o);
965 nm = "MC_(helperc_value_check0_fail_no_o)";
966 args = mkIRExprVec_0();
967 nargs = 0;
968 }
sewardj95448072004-11-22 20:19:51 +0000969 break;
970 case 1:
sewardj7cf4e6b2008-05-01 20:24:26 +0000971 if (origin) {
972 fn = &MC_(helperc_value_check1_fail_w_o);
973 nm = "MC_(helperc_value_check1_fail_w_o)";
974 args = mkIRExprVec_1(origin);
975 nargs = 1;
976 } else {
977 fn = &MC_(helperc_value_check1_fail_no_o);
978 nm = "MC_(helperc_value_check1_fail_no_o)";
979 args = mkIRExprVec_0();
980 nargs = 0;
981 }
sewardj95448072004-11-22 20:19:51 +0000982 break;
983 case 4:
sewardj7cf4e6b2008-05-01 20:24:26 +0000984 if (origin) {
985 fn = &MC_(helperc_value_check4_fail_w_o);
986 nm = "MC_(helperc_value_check4_fail_w_o)";
987 args = mkIRExprVec_1(origin);
988 nargs = 1;
989 } else {
990 fn = &MC_(helperc_value_check4_fail_no_o);
991 nm = "MC_(helperc_value_check4_fail_no_o)";
992 args = mkIRExprVec_0();
993 nargs = 0;
994 }
sewardj95448072004-11-22 20:19:51 +0000995 break;
sewardj11bcc4e2005-04-23 22:38:38 +0000996 case 8:
sewardj7cf4e6b2008-05-01 20:24:26 +0000997 if (origin) {
998 fn = &MC_(helperc_value_check8_fail_w_o);
999 nm = "MC_(helperc_value_check8_fail_w_o)";
1000 args = mkIRExprVec_1(origin);
1001 nargs = 1;
1002 } else {
1003 fn = &MC_(helperc_value_check8_fail_no_o);
1004 nm = "MC_(helperc_value_check8_fail_no_o)";
1005 args = mkIRExprVec_0();
1006 nargs = 0;
1007 }
sewardj11bcc4e2005-04-23 22:38:38 +00001008 break;
sewardj95448072004-11-22 20:19:51 +00001009 default:
sewardj7cf4e6b2008-05-01 20:24:26 +00001010 if (origin) {
1011 fn = &MC_(helperc_value_checkN_fail_w_o);
1012 nm = "MC_(helperc_value_checkN_fail_w_o)";
1013 args = mkIRExprVec_2( mkIRExpr_HWord( sz ), origin);
1014 nargs = 2;
1015 } else {
1016 fn = &MC_(helperc_value_checkN_fail_no_o);
1017 nm = "MC_(helperc_value_checkN_fail_no_o)";
1018 args = mkIRExprVec_1( mkIRExpr_HWord( sz ) );
1019 nargs = 1;
1020 }
sewardj95448072004-11-22 20:19:51 +00001021 break;
1022 }
sewardj7cf4e6b2008-05-01 20:24:26 +00001023
1024 tl_assert(fn);
1025 tl_assert(nm);
1026 tl_assert(args);
1027 tl_assert(nargs >= 0 && nargs <= 2);
1028 tl_assert( (MC_(clo_mc_level) == 3 && origin != NULL)
1029 || (MC_(clo_mc_level) == 2 && origin == NULL) );
1030
1031 di = unsafeIRDirty_0_N( nargs/*regparms*/, nm,
1032 VG_(fnptr_to_fnentry)( fn ), args );
sewardj95448072004-11-22 20:19:51 +00001033 di->guard = cond;
1034 setHelperAnns( mce, di );
sewardj7cf4e6b2008-05-01 20:24:26 +00001035 stmt( 'V', mce, IRStmt_Dirty(di));
sewardj95448072004-11-22 20:19:51 +00001036
1037 /* Set the shadow tmp to be defined. First, update the
1038 orig->shadow tmp mapping to reflect the fact that this shadow is
1039 getting a new value. */
sewardj710d6c22005-03-20 18:55:15 +00001040 tl_assert(isIRAtom(vatom));
sewardj95448072004-11-22 20:19:51 +00001041 /* sameKindedAtoms ... */
sewardj0b9d74a2006-12-24 02:24:11 +00001042 if (vatom->tag == Iex_RdTmp) {
1043 tl_assert(atom->tag == Iex_RdTmp);
sewardj7cf4e6b2008-05-01 20:24:26 +00001044 newShadowTmpV(mce, atom->Iex.RdTmp.tmp);
1045 assign('V', mce, findShadowTmpV(mce, atom->Iex.RdTmp.tmp),
1046 definedOfType(ty));
sewardj95448072004-11-22 20:19:51 +00001047 }
1048}
1049
1050
1051/*------------------------------------------------------------*/
1052/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
1053/*------------------------------------------------------------*/
1054
1055/* Examine the always-defined sections declared in layout to see if
1056 the (offset,size) section is within one. Note, is is an error to
1057 partially fall into such a region: (offset,size) should either be
1058 completely in such a region or completely not-in such a region.
1059*/
1060static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1061{
1062 Int minoffD, maxoffD, i;
1063 Int minoff = offset;
1064 Int maxoff = minoff + size - 1;
1065 tl_assert((minoff & ~0xFFFF) == 0);
1066 tl_assert((maxoff & ~0xFFFF) == 0);
1067
1068 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1069 minoffD = mce->layout->alwaysDefd[i].offset;
1070 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
1071 tl_assert((minoffD & ~0xFFFF) == 0);
1072 tl_assert((maxoffD & ~0xFFFF) == 0);
1073
1074 if (maxoff < minoffD || maxoffD < minoff)
1075 continue; /* no overlap */
1076 if (minoff >= minoffD && maxoff <= maxoffD)
1077 return True; /* completely contained in an always-defd section */
1078
1079 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
1080 }
1081 return False; /* could not find any containing section */
1082}
1083
1084
1085/* Generate into bb suitable actions to shadow this Put. If the state
1086 slice is marked 'always defined', do nothing. Otherwise, write the
1087 supplied V bits to the shadow state. We can pass in either an
1088 original atom or a V-atom, but not both. In the former case the
1089 relevant V-bits are then generated from the original.
1090*/
1091static
1092void do_shadow_PUT ( MCEnv* mce, Int offset,
1093 IRAtom* atom, IRAtom* vatom )
1094{
sewardj7cf97ee2004-11-28 14:25:01 +00001095 IRType ty;
njn1d0825f2006-03-27 11:37:07 +00001096
1097 // Don't do shadow PUTs if we're not doing undefined value checking.
1098 // Their absence lets Vex's optimiser remove all the shadow computation
1099 // that they depend on, which includes GETs of the shadow registers.
sewardj7cf4e6b2008-05-01 20:24:26 +00001100 if (MC_(clo_mc_level) == 1)
njn1d0825f2006-03-27 11:37:07 +00001101 return;
1102
sewardj95448072004-11-22 20:19:51 +00001103 if (atom) {
1104 tl_assert(!vatom);
1105 tl_assert(isOriginalAtom(mce, atom));
1106 vatom = expr2vbits( mce, atom );
1107 } else {
1108 tl_assert(vatom);
1109 tl_assert(isShadowAtom(mce, vatom));
1110 }
1111
sewardj7cf97ee2004-11-28 14:25:01 +00001112 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj95448072004-11-22 20:19:51 +00001113 tl_assert(ty != Ity_I1);
1114 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1115 /* later: no ... */
1116 /* emit code to emit a complaint if any of the vbits are 1. */
1117 /* complainIfUndefined(mce, atom); */
1118 } else {
1119 /* Do a plain shadow Put. */
sewardj7cf4e6b2008-05-01 20:24:26 +00001120 stmt( 'V', mce, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
sewardj95448072004-11-22 20:19:51 +00001121 }
1122}
1123
1124
1125/* Return an expression which contains the V bits corresponding to the
1126 given GETI (passed in in pieces).
1127*/
1128static
1129void do_shadow_PUTI ( MCEnv* mce,
sewardj0b9d74a2006-12-24 02:24:11 +00001130 IRRegArray* descr,
1131 IRAtom* ix, Int bias, IRAtom* atom )
sewardj95448072004-11-22 20:19:51 +00001132{
sewardj7cf97ee2004-11-28 14:25:01 +00001133 IRAtom* vatom;
1134 IRType ty, tyS;
1135 Int arrSize;;
1136
njn1d0825f2006-03-27 11:37:07 +00001137 // Don't do shadow PUTIs if we're not doing undefined value checking.
1138 // Their absence lets Vex's optimiser remove all the shadow computation
1139 // that they depend on, which includes GETIs of the shadow registers.
sewardj7cf4e6b2008-05-01 20:24:26 +00001140 if (MC_(clo_mc_level) == 1)
njn1d0825f2006-03-27 11:37:07 +00001141 return;
1142
sewardj95448072004-11-22 20:19:51 +00001143 tl_assert(isOriginalAtom(mce,atom));
sewardj7cf97ee2004-11-28 14:25:01 +00001144 vatom = expr2vbits( mce, atom );
sewardj95448072004-11-22 20:19:51 +00001145 tl_assert(sameKindedAtoms(atom, vatom));
sewardj7cf97ee2004-11-28 14:25:01 +00001146 ty = descr->elemTy;
sewardj7cf4e6b2008-05-01 20:24:26 +00001147 tyS = shadowTypeV(ty);
sewardj7cf97ee2004-11-28 14:25:01 +00001148 arrSize = descr->nElems * sizeofIRType(ty);
sewardj95448072004-11-22 20:19:51 +00001149 tl_assert(ty != Ity_I1);
1150 tl_assert(isOriginalAtom(mce,ix));
1151 complainIfUndefined(mce,ix);
1152 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1153 /* later: no ... */
1154 /* emit code to emit a complaint if any of the vbits are 1. */
1155 /* complainIfUndefined(mce, atom); */
1156 } else {
1157 /* Do a cloned version of the Put that refers to the shadow
1158 area. */
sewardj0b9d74a2006-12-24 02:24:11 +00001159 IRRegArray* new_descr
1160 = mkIRRegArray( descr->base + mce->layout->total_sizeB,
1161 tyS, descr->nElems);
sewardj7cf4e6b2008-05-01 20:24:26 +00001162 stmt( 'V', mce, IRStmt_PutI( new_descr, ix, bias, vatom ));
sewardj95448072004-11-22 20:19:51 +00001163 }
1164}
1165
1166
1167/* Return an expression which contains the V bits corresponding to the
1168 given GET (passed in in pieces).
1169*/
1170static
1171IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1172{
sewardj7cf4e6b2008-05-01 20:24:26 +00001173 IRType tyS = shadowTypeV(ty);
sewardj95448072004-11-22 20:19:51 +00001174 tl_assert(ty != Ity_I1);
1175 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1176 /* Always defined, return all zeroes of the relevant type */
1177 return definedOfType(tyS);
1178 } else {
1179 /* return a cloned version of the Get that refers to the shadow
1180 area. */
sewardj7cf4e6b2008-05-01 20:24:26 +00001181 /* FIXME: this isn't an atom! */
sewardj95448072004-11-22 20:19:51 +00001182 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1183 }
1184}
1185
1186
1187/* Return an expression which contains the V bits corresponding to the
1188 given GETI (passed in in pieces).
1189*/
1190static
sewardj0b9d74a2006-12-24 02:24:11 +00001191IRExpr* shadow_GETI ( MCEnv* mce,
1192 IRRegArray* descr, IRAtom* ix, Int bias )
sewardj95448072004-11-22 20:19:51 +00001193{
1194 IRType ty = descr->elemTy;
sewardj7cf4e6b2008-05-01 20:24:26 +00001195 IRType tyS = shadowTypeV(ty);
sewardj95448072004-11-22 20:19:51 +00001196 Int arrSize = descr->nElems * sizeofIRType(ty);
1197 tl_assert(ty != Ity_I1);
1198 tl_assert(isOriginalAtom(mce,ix));
1199 complainIfUndefined(mce,ix);
1200 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1201 /* Always defined, return all zeroes of the relevant type */
1202 return definedOfType(tyS);
1203 } else {
1204 /* return a cloned version of the Get that refers to the shadow
1205 area. */
sewardj0b9d74a2006-12-24 02:24:11 +00001206 IRRegArray* new_descr
1207 = mkIRRegArray( descr->base + mce->layout->total_sizeB,
1208 tyS, descr->nElems);
sewardj95448072004-11-22 20:19:51 +00001209 return IRExpr_GetI( new_descr, ix, bias );
1210 }
1211}
1212
1213
1214/*------------------------------------------------------------*/
1215/*--- Generating approximations for unknown operations, ---*/
1216/*--- using lazy-propagate semantics ---*/
1217/*------------------------------------------------------------*/
1218
1219/* Lazy propagation of undefinedness from two values, resulting in the
1220 specified shadow type.
1221*/
1222static
1223IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1224{
sewardj95448072004-11-22 20:19:51 +00001225 IRAtom* at;
sewardj37c31cc2005-04-26 23:49:24 +00001226 IRType t1 = typeOfIRExpr(mce->bb->tyenv, va1);
1227 IRType t2 = typeOfIRExpr(mce->bb->tyenv, va2);
sewardj95448072004-11-22 20:19:51 +00001228 tl_assert(isShadowAtom(mce,va1));
1229 tl_assert(isShadowAtom(mce,va2));
sewardj37c31cc2005-04-26 23:49:24 +00001230
1231 /* The general case is inefficient because PCast is an expensive
1232 operation. Here are some special cases which use PCast only
1233 once rather than twice. */
1234
1235 /* I64 x I64 -> I64 */
1236 if (t1 == Ity_I64 && t2 == Ity_I64 && finalVty == Ity_I64) {
1237 if (0) VG_(printf)("mkLazy2: I64 x I64 -> I64\n");
1238 at = mkUifU(mce, Ity_I64, va1, va2);
1239 at = mkPCastTo(mce, Ity_I64, at);
1240 return at;
1241 }
1242
1243 /* I64 x I64 -> I32 */
1244 if (t1 == Ity_I64 && t2 == Ity_I64 && finalVty == Ity_I32) {
1245 if (0) VG_(printf)("mkLazy2: I64 x I64 -> I32\n");
1246 at = mkUifU(mce, Ity_I64, va1, va2);
1247 at = mkPCastTo(mce, Ity_I32, at);
1248 return at;
1249 }
1250
1251 if (0) {
1252 VG_(printf)("mkLazy2 ");
1253 ppIRType(t1);
1254 VG_(printf)("_");
1255 ppIRType(t2);
1256 VG_(printf)("_");
1257 ppIRType(finalVty);
1258 VG_(printf)("\n");
1259 }
1260
1261 /* General case: force everything via 32-bit intermediaries. */
sewardj95448072004-11-22 20:19:51 +00001262 at = mkPCastTo(mce, Ity_I32, va1);
1263 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1264 at = mkPCastTo(mce, finalVty, at);
1265 return at;
1266}
1267
1268
sewardjed69fdb2006-02-03 16:12:27 +00001269/* 3-arg version of the above. */
1270static
1271IRAtom* mkLazy3 ( MCEnv* mce, IRType finalVty,
1272 IRAtom* va1, IRAtom* va2, IRAtom* va3 )
1273{
1274 IRAtom* at;
1275 IRType t1 = typeOfIRExpr(mce->bb->tyenv, va1);
1276 IRType t2 = typeOfIRExpr(mce->bb->tyenv, va2);
1277 IRType t3 = typeOfIRExpr(mce->bb->tyenv, va3);
1278 tl_assert(isShadowAtom(mce,va1));
1279 tl_assert(isShadowAtom(mce,va2));
1280 tl_assert(isShadowAtom(mce,va3));
1281
1282 /* The general case is inefficient because PCast is an expensive
1283 operation. Here are some special cases which use PCast only
1284 twice rather than three times. */
1285
1286 /* I32 x I64 x I64 -> I64 */
1287 /* Standard FP idiom: rm x FParg1 x FParg2 -> FPresult */
1288 if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64
1289 && finalVty == Ity_I64) {
1290 if (0) VG_(printf)("mkLazy3: I32 x I64 x I64 -> I64\n");
1291 /* Widen 1st arg to I64. Since 1st arg is typically a rounding
1292 mode indication which is fully defined, this should get
1293 folded out later. */
1294 at = mkPCastTo(mce, Ity_I64, va1);
1295 /* Now fold in 2nd and 3rd args. */
1296 at = mkUifU(mce, Ity_I64, at, va2);
1297 at = mkUifU(mce, Ity_I64, at, va3);
1298 /* and PCast once again. */
1299 at = mkPCastTo(mce, Ity_I64, at);
1300 return at;
1301 }
1302
sewardj453e8f82006-02-09 03:25:06 +00001303 /* I32 x I64 x I64 -> I32 */
1304 if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64
1305 && finalVty == Ity_I32) {
1306 if (0) VG_(printf)("mkLazy3: I32 x I64 x I64 -> I64\n");
1307 at = mkPCastTo(mce, Ity_I64, va1);
1308 at = mkUifU(mce, Ity_I64, at, va2);
1309 at = mkUifU(mce, Ity_I64, at, va3);
1310 at = mkPCastTo(mce, Ity_I32, at);
1311 return at;
1312 }
1313
1314 if (1) {
1315 VG_(printf)("mkLazy3: ");
sewardjed69fdb2006-02-03 16:12:27 +00001316 ppIRType(t1);
sewardj453e8f82006-02-09 03:25:06 +00001317 VG_(printf)(" x ");
sewardjed69fdb2006-02-03 16:12:27 +00001318 ppIRType(t2);
sewardj453e8f82006-02-09 03:25:06 +00001319 VG_(printf)(" x ");
sewardjed69fdb2006-02-03 16:12:27 +00001320 ppIRType(t3);
sewardj453e8f82006-02-09 03:25:06 +00001321 VG_(printf)(" -> ");
sewardjed69fdb2006-02-03 16:12:27 +00001322 ppIRType(finalVty);
1323 VG_(printf)("\n");
1324 }
1325
sewardj453e8f82006-02-09 03:25:06 +00001326 tl_assert(0);
sewardjed69fdb2006-02-03 16:12:27 +00001327 /* General case: force everything via 32-bit intermediaries. */
sewardj453e8f82006-02-09 03:25:06 +00001328 /*
sewardjed69fdb2006-02-03 16:12:27 +00001329 at = mkPCastTo(mce, Ity_I32, va1);
1330 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1331 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va3));
1332 at = mkPCastTo(mce, finalVty, at);
1333 return at;
sewardj453e8f82006-02-09 03:25:06 +00001334 */
sewardjed69fdb2006-02-03 16:12:27 +00001335}
1336
1337
sewardje91cea72006-02-08 19:32:02 +00001338/* 4-arg version of the above. */
1339static
1340IRAtom* mkLazy4 ( MCEnv* mce, IRType finalVty,
1341 IRAtom* va1, IRAtom* va2, IRAtom* va3, IRAtom* va4 )
1342{
1343 IRAtom* at;
1344 IRType t1 = typeOfIRExpr(mce->bb->tyenv, va1);
1345 IRType t2 = typeOfIRExpr(mce->bb->tyenv, va2);
1346 IRType t3 = typeOfIRExpr(mce->bb->tyenv, va3);
1347 IRType t4 = typeOfIRExpr(mce->bb->tyenv, va4);
1348 tl_assert(isShadowAtom(mce,va1));
1349 tl_assert(isShadowAtom(mce,va2));
1350 tl_assert(isShadowAtom(mce,va3));
1351 tl_assert(isShadowAtom(mce,va4));
1352
1353 /* The general case is inefficient because PCast is an expensive
1354 operation. Here are some special cases which use PCast only
1355 twice rather than three times. */
1356
1357 /* I32 x I64 x I64 x I64 -> I64 */
1358 /* Standard FP idiom: rm x FParg1 x FParg2 x FParg3 -> FPresult */
1359 if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64 && t4 == Ity_I64
1360 && finalVty == Ity_I64) {
1361 if (0) VG_(printf)("mkLazy4: I32 x I64 x I64 x I64 -> I64\n");
1362 /* Widen 1st arg to I64. Since 1st arg is typically a rounding
1363 mode indication which is fully defined, this should get
1364 folded out later. */
1365 at = mkPCastTo(mce, Ity_I64, va1);
1366 /* Now fold in 2nd, 3rd, 4th args. */
1367 at = mkUifU(mce, Ity_I64, at, va2);
1368 at = mkUifU(mce, Ity_I64, at, va3);
1369 at = mkUifU(mce, Ity_I64, at, va4);
1370 /* and PCast once again. */
1371 at = mkPCastTo(mce, Ity_I64, at);
1372 return at;
1373 }
1374
1375 if (1) {
sewardj453e8f82006-02-09 03:25:06 +00001376 VG_(printf)("mkLazy4: ");
sewardje91cea72006-02-08 19:32:02 +00001377 ppIRType(t1);
1378 VG_(printf)(" x ");
1379 ppIRType(t2);
1380 VG_(printf)(" x ");
1381 ppIRType(t3);
1382 VG_(printf)(" x ");
1383 ppIRType(t4);
1384 VG_(printf)(" -> ");
1385 ppIRType(finalVty);
1386 VG_(printf)("\n");
1387 }
1388
1389 tl_assert(0);
1390}
1391
1392
sewardj95448072004-11-22 20:19:51 +00001393/* Do the lazy propagation game from a null-terminated vector of
1394 atoms. This is presumably the arguments to a helper call, so the
1395 IRCallee info is also supplied in order that we can know which
1396 arguments should be ignored (via the .mcx_mask field).
1397*/
1398static
1399IRAtom* mkLazyN ( MCEnv* mce,
1400 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1401{
sewardj4cc684b2007-08-25 23:09:36 +00001402 Int i;
sewardj95448072004-11-22 20:19:51 +00001403 IRAtom* here;
sewardj4cc684b2007-08-25 23:09:36 +00001404 IRAtom* curr;
1405 IRType mergeTy;
1406 IRType mergeTy64 = True;
1407
1408 /* Decide on the type of the merge intermediary. If all relevant
1409 args are I64, then it's I64. In all other circumstances, use
1410 I32. */
1411 for (i = 0; exprvec[i]; i++) {
1412 tl_assert(i < 32);
1413 tl_assert(isOriginalAtom(mce, exprvec[i]));
1414 if (cee->mcx_mask & (1<<i))
1415 continue;
1416 if (typeOfIRExpr(mce->bb->tyenv, exprvec[i]) != Ity_I64)
1417 mergeTy64 = False;
1418 }
1419
1420 mergeTy = mergeTy64 ? Ity_I64 : Ity_I32;
1421 curr = definedOfType(mergeTy);
1422
sewardj95448072004-11-22 20:19:51 +00001423 for (i = 0; exprvec[i]; i++) {
1424 tl_assert(i < 32);
1425 tl_assert(isOriginalAtom(mce, exprvec[i]));
1426 /* Only take notice of this arg if the callee's mc-exclusion
1427 mask does not say it is to be excluded. */
1428 if (cee->mcx_mask & (1<<i)) {
1429 /* the arg is to be excluded from definedness checking. Do
1430 nothing. */
1431 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1432 } else {
1433 /* calculate the arg's definedness, and pessimistically merge
1434 it in. */
sewardj4cc684b2007-08-25 23:09:36 +00001435 here = mkPCastTo( mce, mergeTy, expr2vbits(mce, exprvec[i]) );
1436 curr = mergeTy64
1437 ? mkUifU64(mce, here, curr)
1438 : mkUifU32(mce, here, curr);
sewardj95448072004-11-22 20:19:51 +00001439 }
1440 }
1441 return mkPCastTo(mce, finalVtype, curr );
1442}
1443
1444
1445/*------------------------------------------------------------*/
1446/*--- Generating expensive sequences for exact carry-chain ---*/
1447/*--- propagation in add/sub and related operations. ---*/
1448/*------------------------------------------------------------*/
1449
1450static
sewardjd5204dc2004-12-31 01:16:11 +00001451IRAtom* expensiveAddSub ( MCEnv* mce,
1452 Bool add,
1453 IRType ty,
1454 IRAtom* qaa, IRAtom* qbb,
1455 IRAtom* aa, IRAtom* bb )
sewardj95448072004-11-22 20:19:51 +00001456{
sewardj7cf97ee2004-11-28 14:25:01 +00001457 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardjd5204dc2004-12-31 01:16:11 +00001458 IROp opAND, opOR, opXOR, opNOT, opADD, opSUB;
sewardj7cf97ee2004-11-28 14:25:01 +00001459
sewardj95448072004-11-22 20:19:51 +00001460 tl_assert(isShadowAtom(mce,qaa));
1461 tl_assert(isShadowAtom(mce,qbb));
1462 tl_assert(isOriginalAtom(mce,aa));
1463 tl_assert(isOriginalAtom(mce,bb));
1464 tl_assert(sameKindedAtoms(qaa,aa));
1465 tl_assert(sameKindedAtoms(qbb,bb));
1466
sewardjd5204dc2004-12-31 01:16:11 +00001467 switch (ty) {
1468 case Ity_I32:
1469 opAND = Iop_And32;
1470 opOR = Iop_Or32;
1471 opXOR = Iop_Xor32;
1472 opNOT = Iop_Not32;
1473 opADD = Iop_Add32;
1474 opSUB = Iop_Sub32;
1475 break;
tomd9774d72005-06-27 08:11:01 +00001476 case Ity_I64:
1477 opAND = Iop_And64;
1478 opOR = Iop_Or64;
1479 opXOR = Iop_Xor64;
1480 opNOT = Iop_Not64;
1481 opADD = Iop_Add64;
1482 opSUB = Iop_Sub64;
1483 break;
sewardjd5204dc2004-12-31 01:16:11 +00001484 default:
1485 VG_(tool_panic)("expensiveAddSub");
1486 }
sewardj95448072004-11-22 20:19:51 +00001487
1488 // a_min = aa & ~qaa
sewardj7cf4e6b2008-05-01 20:24:26 +00001489 a_min = assignNew('V', mce,ty,
sewardj95448072004-11-22 20:19:51 +00001490 binop(opAND, aa,
sewardj7cf4e6b2008-05-01 20:24:26 +00001491 assignNew('V', mce,ty, unop(opNOT, qaa))));
sewardj95448072004-11-22 20:19:51 +00001492
1493 // b_min = bb & ~qbb
sewardj7cf4e6b2008-05-01 20:24:26 +00001494 b_min = assignNew('V', mce,ty,
sewardj95448072004-11-22 20:19:51 +00001495 binop(opAND, bb,
sewardj7cf4e6b2008-05-01 20:24:26 +00001496 assignNew('V', mce,ty, unop(opNOT, qbb))));
sewardj95448072004-11-22 20:19:51 +00001497
1498 // a_max = aa | qaa
sewardj7cf4e6b2008-05-01 20:24:26 +00001499 a_max = assignNew('V', mce,ty, binop(opOR, aa, qaa));
sewardj95448072004-11-22 20:19:51 +00001500
1501 // b_max = bb | qbb
sewardj7cf4e6b2008-05-01 20:24:26 +00001502 b_max = assignNew('V', mce,ty, binop(opOR, bb, qbb));
sewardj95448072004-11-22 20:19:51 +00001503
sewardjd5204dc2004-12-31 01:16:11 +00001504 if (add) {
1505 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1506 return
sewardj7cf4e6b2008-05-01 20:24:26 +00001507 assignNew('V', mce,ty,
sewardjd5204dc2004-12-31 01:16:11 +00001508 binop( opOR,
sewardj7cf4e6b2008-05-01 20:24:26 +00001509 assignNew('V', mce,ty, binop(opOR, qaa, qbb)),
1510 assignNew('V', mce,ty,
sewardjd5204dc2004-12-31 01:16:11 +00001511 binop( opXOR,
sewardj7cf4e6b2008-05-01 20:24:26 +00001512 assignNew('V', mce,ty, binop(opADD, a_min, b_min)),
1513 assignNew('V', mce,ty, binop(opADD, a_max, b_max))
sewardjd5204dc2004-12-31 01:16:11 +00001514 )
sewardj95448072004-11-22 20:19:51 +00001515 )
sewardjd5204dc2004-12-31 01:16:11 +00001516 )
1517 );
1518 } else {
1519 // result = (qaa | qbb) | ((a_min - b_max) ^ (a_max + b_min))
1520 return
sewardj7cf4e6b2008-05-01 20:24:26 +00001521 assignNew('V', mce,ty,
sewardjd5204dc2004-12-31 01:16:11 +00001522 binop( opOR,
sewardj7cf4e6b2008-05-01 20:24:26 +00001523 assignNew('V', mce,ty, binop(opOR, qaa, qbb)),
1524 assignNew('V', mce,ty,
sewardjd5204dc2004-12-31 01:16:11 +00001525 binop( opXOR,
sewardj7cf4e6b2008-05-01 20:24:26 +00001526 assignNew('V', mce,ty, binop(opSUB, a_min, b_max)),
1527 assignNew('V', mce,ty, binop(opSUB, a_max, b_min))
sewardjd5204dc2004-12-31 01:16:11 +00001528 )
1529 )
1530 )
1531 );
1532 }
1533
sewardj95448072004-11-22 20:19:51 +00001534}
1535
1536
1537/*------------------------------------------------------------*/
sewardjaaddbc22005-10-07 09:49:53 +00001538/*--- Scalar shifts. ---*/
1539/*------------------------------------------------------------*/
1540
1541/* Produce an interpretation for (aa << bb) (or >>s, >>u). The basic
1542 idea is to shift the definedness bits by the original shift amount.
1543 This introduces 0s ("defined") in new positions for left shifts and
1544 unsigned right shifts, and copies the top definedness bit for
1545 signed right shifts. So, conveniently, applying the original shift
1546 operator to the definedness bits for the left arg is exactly the
1547 right thing to do:
1548
1549 (qaa << bb)
1550
1551 However if the shift amount is undefined then the whole result
1552 is undefined. Hence need:
1553
1554 (qaa << bb) `UifU` PCast(qbb)
1555
1556 If the shift amount bb is a literal than qbb will say 'all defined'
1557 and the UifU and PCast will get folded out by post-instrumentation
1558 optimisation.
1559*/
1560static IRAtom* scalarShift ( MCEnv* mce,
1561 IRType ty,
1562 IROp original_op,
1563 IRAtom* qaa, IRAtom* qbb,
1564 IRAtom* aa, IRAtom* bb )
1565{
1566 tl_assert(isShadowAtom(mce,qaa));
1567 tl_assert(isShadowAtom(mce,qbb));
1568 tl_assert(isOriginalAtom(mce,aa));
1569 tl_assert(isOriginalAtom(mce,bb));
1570 tl_assert(sameKindedAtoms(qaa,aa));
1571 tl_assert(sameKindedAtoms(qbb,bb));
1572 return
1573 assignNew(
sewardj7cf4e6b2008-05-01 20:24:26 +00001574 'V', mce, ty,
sewardjaaddbc22005-10-07 09:49:53 +00001575 mkUifU( mce, ty,
sewardj7cf4e6b2008-05-01 20:24:26 +00001576 assignNew('V', mce, ty, binop(original_op, qaa, bb)),
sewardjaaddbc22005-10-07 09:49:53 +00001577 mkPCastTo(mce, ty, qbb)
1578 )
1579 );
1580}
1581
1582
1583/*------------------------------------------------------------*/
1584/*--- Helpers for dealing with vector primops. ---*/
sewardj3245c912004-12-10 14:58:26 +00001585/*------------------------------------------------------------*/
1586
sewardja1d93302004-12-12 16:45:06 +00001587/* Vector pessimisation -- pessimise within each lane individually. */
1588
1589static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1590{
sewardj7cf4e6b2008-05-01 20:24:26 +00001591 return assignNew('V', mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
sewardja1d93302004-12-12 16:45:06 +00001592}
1593
1594static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1595{
sewardj7cf4e6b2008-05-01 20:24:26 +00001596 return assignNew('V', mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
sewardja1d93302004-12-12 16:45:06 +00001597}
1598
1599static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1600{
sewardj7cf4e6b2008-05-01 20:24:26 +00001601 return assignNew('V', mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
sewardja1d93302004-12-12 16:45:06 +00001602}
1603
1604static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1605{
sewardj7cf4e6b2008-05-01 20:24:26 +00001606 return assignNew('V', mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
sewardja1d93302004-12-12 16:45:06 +00001607}
1608
sewardjacd2e912005-01-13 19:17:06 +00001609static IRAtom* mkPCast32x2 ( MCEnv* mce, IRAtom* at )
1610{
sewardj7cf4e6b2008-05-01 20:24:26 +00001611 return assignNew('V', mce, Ity_I64, unop(Iop_CmpNEZ32x2, at));
sewardjacd2e912005-01-13 19:17:06 +00001612}
1613
1614static IRAtom* mkPCast16x4 ( MCEnv* mce, IRAtom* at )
1615{
sewardj7cf4e6b2008-05-01 20:24:26 +00001616 return assignNew('V', mce, Ity_I64, unop(Iop_CmpNEZ16x4, at));
sewardjacd2e912005-01-13 19:17:06 +00001617}
1618
1619static IRAtom* mkPCast8x8 ( MCEnv* mce, IRAtom* at )
1620{
sewardj7cf4e6b2008-05-01 20:24:26 +00001621 return assignNew('V', mce, Ity_I64, unop(Iop_CmpNEZ8x8, at));
sewardjacd2e912005-01-13 19:17:06 +00001622}
1623
sewardja1d93302004-12-12 16:45:06 +00001624
sewardj3245c912004-12-10 14:58:26 +00001625/* Here's a simple scheme capable of handling ops derived from SSE1
1626 code and while only generating ops that can be efficiently
1627 implemented in SSE1. */
1628
1629/* All-lanes versions are straightforward:
1630
sewardj20d38f22005-02-07 23:50:18 +00001631 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj3245c912004-12-10 14:58:26 +00001632
1633 unary32Fx4(x,y) ==> PCast32x4(x#)
1634
1635 Lowest-lane-only versions are more complex:
1636
sewardj20d38f22005-02-07 23:50:18 +00001637 binary32F0x4(x,y) ==> SetV128lo32(
sewardj3245c912004-12-10 14:58:26 +00001638 x#,
sewardj20d38f22005-02-07 23:50:18 +00001639 PCast32(V128to32(UifUV128(x#,y#)))
sewardj3245c912004-12-10 14:58:26 +00001640 )
1641
1642 This is perhaps not so obvious. In particular, it's faster to
sewardj20d38f22005-02-07 23:50:18 +00001643 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj3245c912004-12-10 14:58:26 +00001644 obvious scheme of taking the bottom 32 bits of each operand
1645 and doing a 32-bit UifU. Basically since UifU is fast and
1646 chopping lanes off vector values is slow.
1647
1648 Finally:
1649
sewardj20d38f22005-02-07 23:50:18 +00001650 unary32F0x4(x) ==> SetV128lo32(
sewardj3245c912004-12-10 14:58:26 +00001651 x#,
sewardj20d38f22005-02-07 23:50:18 +00001652 PCast32(V128to32(x#))
sewardj3245c912004-12-10 14:58:26 +00001653 )
1654
1655 Where:
1656
1657 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1658 PCast32x4(v#) = CmpNEZ32x4(v#)
1659*/
1660
1661static
1662IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1663{
1664 IRAtom* at;
1665 tl_assert(isShadowAtom(mce, vatomX));
1666 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001667 at = mkUifUV128(mce, vatomX, vatomY);
sewardj7cf4e6b2008-05-01 20:24:26 +00001668 at = assignNew('V', mce, Ity_V128, mkPCast32x4(mce, at));
sewardj3245c912004-12-10 14:58:26 +00001669 return at;
1670}
1671
1672static
1673IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1674{
1675 IRAtom* at;
1676 tl_assert(isShadowAtom(mce, vatomX));
sewardj7cf4e6b2008-05-01 20:24:26 +00001677 at = assignNew('V', mce, Ity_V128, mkPCast32x4(mce, vatomX));
sewardj3245c912004-12-10 14:58:26 +00001678 return at;
1679}
1680
1681static
1682IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1683{
1684 IRAtom* at;
1685 tl_assert(isShadowAtom(mce, vatomX));
1686 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001687 at = mkUifUV128(mce, vatomX, vatomY);
sewardj7cf4e6b2008-05-01 20:24:26 +00001688 at = assignNew('V', mce, Ity_I32, unop(Iop_V128to32, at));
sewardj3245c912004-12-10 14:58:26 +00001689 at = mkPCastTo(mce, Ity_I32, at);
sewardj7cf4e6b2008-05-01 20:24:26 +00001690 at = assignNew('V', mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj3245c912004-12-10 14:58:26 +00001691 return at;
1692}
1693
1694static
1695IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1696{
1697 IRAtom* at;
1698 tl_assert(isShadowAtom(mce, vatomX));
sewardj7cf4e6b2008-05-01 20:24:26 +00001699 at = assignNew('V', mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj3245c912004-12-10 14:58:26 +00001700 at = mkPCastTo(mce, Ity_I32, at);
sewardj7cf4e6b2008-05-01 20:24:26 +00001701 at = assignNew('V', mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj3245c912004-12-10 14:58:26 +00001702 return at;
1703}
1704
sewardj0b070592004-12-10 21:44:22 +00001705/* --- ... and ... 64Fx2 versions of the same ... --- */
1706
1707static
1708IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1709{
1710 IRAtom* at;
1711 tl_assert(isShadowAtom(mce, vatomX));
1712 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001713 at = mkUifUV128(mce, vatomX, vatomY);
sewardj7cf4e6b2008-05-01 20:24:26 +00001714 at = assignNew('V', mce, Ity_V128, mkPCast64x2(mce, at));
sewardj0b070592004-12-10 21:44:22 +00001715 return at;
1716}
1717
1718static
1719IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1720{
1721 IRAtom* at;
1722 tl_assert(isShadowAtom(mce, vatomX));
sewardj7cf4e6b2008-05-01 20:24:26 +00001723 at = assignNew('V', mce, Ity_V128, mkPCast64x2(mce, vatomX));
sewardj0b070592004-12-10 21:44:22 +00001724 return at;
1725}
1726
1727static
1728IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1729{
1730 IRAtom* at;
1731 tl_assert(isShadowAtom(mce, vatomX));
1732 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001733 at = mkUifUV128(mce, vatomX, vatomY);
sewardj7cf4e6b2008-05-01 20:24:26 +00001734 at = assignNew('V', mce, Ity_I64, unop(Iop_V128to64, at));
sewardj0b070592004-12-10 21:44:22 +00001735 at = mkPCastTo(mce, Ity_I64, at);
sewardj7cf4e6b2008-05-01 20:24:26 +00001736 at = assignNew('V', mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj0b070592004-12-10 21:44:22 +00001737 return at;
1738}
1739
1740static
1741IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1742{
1743 IRAtom* at;
1744 tl_assert(isShadowAtom(mce, vatomX));
sewardj7cf4e6b2008-05-01 20:24:26 +00001745 at = assignNew('V', mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj0b070592004-12-10 21:44:22 +00001746 at = mkPCastTo(mce, Ity_I64, at);
sewardj7cf4e6b2008-05-01 20:24:26 +00001747 at = assignNew('V', mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj0b070592004-12-10 21:44:22 +00001748 return at;
1749}
1750
sewardja1d93302004-12-12 16:45:06 +00001751/* --- --- Vector saturated narrowing --- --- */
1752
1753/* This is quite subtle. What to do is simple:
1754
1755 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1756
1757 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1758
1759 Why this is right is not so simple. Consider a lane in the args,
1760 vatom1 or 2, doesn't matter.
1761
1762 After the PCast, that lane is all 0s (defined) or all
1763 1s(undefined).
1764
1765 Both signed and unsigned saturating narrowing of all 0s produces
1766 all 0s, which is what we want.
1767
1768 The all-1s case is more complex. Unsigned narrowing interprets an
1769 all-1s input as the largest unsigned integer, and so produces all
1770 1s as a result since that is the largest unsigned value at the
1771 smaller width.
1772
1773 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1774 to -1, so we still wind up with all 1s at the smaller width.
1775
1776 So: In short, pessimise the args, then apply the original narrowing
1777 op.
1778*/
1779static
sewardj20d38f22005-02-07 23:50:18 +00001780IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardja1d93302004-12-12 16:45:06 +00001781 IRAtom* vatom1, IRAtom* vatom2)
1782{
1783 IRAtom *at1, *at2, *at3;
1784 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1785 switch (narrow_op) {
1786 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
sewardj43d60752005-11-10 18:13:01 +00001787 case Iop_QNarrow32Ux4: pcast = mkPCast32x4; break;
sewardja1d93302004-12-12 16:45:06 +00001788 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1789 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardj20d38f22005-02-07 23:50:18 +00001790 default: VG_(tool_panic)("vectorNarrowV128");
sewardja1d93302004-12-12 16:45:06 +00001791 }
1792 tl_assert(isShadowAtom(mce,vatom1));
1793 tl_assert(isShadowAtom(mce,vatom2));
sewardj7cf4e6b2008-05-01 20:24:26 +00001794 at1 = assignNew('V', mce, Ity_V128, pcast(mce, vatom1));
1795 at2 = assignNew('V', mce, Ity_V128, pcast(mce, vatom2));
1796 at3 = assignNew('V', mce, Ity_V128, binop(narrow_op, at1, at2));
sewardja1d93302004-12-12 16:45:06 +00001797 return at3;
1798}
1799
sewardjacd2e912005-01-13 19:17:06 +00001800static
1801IRAtom* vectorNarrow64 ( MCEnv* mce, IROp narrow_op,
1802 IRAtom* vatom1, IRAtom* vatom2)
1803{
1804 IRAtom *at1, *at2, *at3;
1805 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1806 switch (narrow_op) {
1807 case Iop_QNarrow32Sx2: pcast = mkPCast32x2; break;
1808 case Iop_QNarrow16Sx4: pcast = mkPCast16x4; break;
1809 case Iop_QNarrow16Ux4: pcast = mkPCast16x4; break;
1810 default: VG_(tool_panic)("vectorNarrow64");
1811 }
1812 tl_assert(isShadowAtom(mce,vatom1));
1813 tl_assert(isShadowAtom(mce,vatom2));
sewardj7cf4e6b2008-05-01 20:24:26 +00001814 at1 = assignNew('V', mce, Ity_I64, pcast(mce, vatom1));
1815 at2 = assignNew('V', mce, Ity_I64, pcast(mce, vatom2));
1816 at3 = assignNew('V', mce, Ity_I64, binop(narrow_op, at1, at2));
sewardjacd2e912005-01-13 19:17:06 +00001817 return at3;
1818}
1819
sewardja1d93302004-12-12 16:45:06 +00001820
1821/* --- --- Vector integer arithmetic --- --- */
1822
1823/* Simple ... UifU the args and per-lane pessimise the results. */
sewardjacd2e912005-01-13 19:17:06 +00001824
sewardj20d38f22005-02-07 23:50:18 +00001825/* --- V128-bit versions --- */
sewardjacd2e912005-01-13 19:17:06 +00001826
sewardja1d93302004-12-12 16:45:06 +00001827static
1828IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1829{
1830 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001831 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001832 at = mkPCast8x16(mce, at);
1833 return at;
1834}
1835
1836static
1837IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1838{
1839 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001840 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001841 at = mkPCast16x8(mce, at);
1842 return at;
1843}
1844
1845static
1846IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1847{
1848 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001849 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001850 at = mkPCast32x4(mce, at);
1851 return at;
1852}
1853
1854static
1855IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1856{
1857 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001858 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001859 at = mkPCast64x2(mce, at);
1860 return at;
1861}
sewardj3245c912004-12-10 14:58:26 +00001862
sewardjacd2e912005-01-13 19:17:06 +00001863/* --- 64-bit versions --- */
1864
1865static
1866IRAtom* binary8Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1867{
1868 IRAtom* at;
1869 at = mkUifU64(mce, vatom1, vatom2);
1870 at = mkPCast8x8(mce, at);
1871 return at;
1872}
1873
1874static
1875IRAtom* binary16Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1876{
1877 IRAtom* at;
1878 at = mkUifU64(mce, vatom1, vatom2);
1879 at = mkPCast16x4(mce, at);
1880 return at;
1881}
1882
1883static
1884IRAtom* binary32Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1885{
1886 IRAtom* at;
1887 at = mkUifU64(mce, vatom1, vatom2);
1888 at = mkPCast32x2(mce, at);
1889 return at;
1890}
1891
sewardj3245c912004-12-10 14:58:26 +00001892
1893/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00001894/*--- Generate shadow values from all kinds of IRExprs. ---*/
1895/*------------------------------------------------------------*/
1896
1897static
sewardje91cea72006-02-08 19:32:02 +00001898IRAtom* expr2vbits_Qop ( MCEnv* mce,
1899 IROp op,
1900 IRAtom* atom1, IRAtom* atom2,
1901 IRAtom* atom3, IRAtom* atom4 )
1902{
1903 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1904 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1905 IRAtom* vatom3 = expr2vbits( mce, atom3 );
1906 IRAtom* vatom4 = expr2vbits( mce, atom4 );
1907
1908 tl_assert(isOriginalAtom(mce,atom1));
1909 tl_assert(isOriginalAtom(mce,atom2));
1910 tl_assert(isOriginalAtom(mce,atom3));
1911 tl_assert(isOriginalAtom(mce,atom4));
1912 tl_assert(isShadowAtom(mce,vatom1));
1913 tl_assert(isShadowAtom(mce,vatom2));
1914 tl_assert(isShadowAtom(mce,vatom3));
1915 tl_assert(isShadowAtom(mce,vatom4));
1916 tl_assert(sameKindedAtoms(atom1,vatom1));
1917 tl_assert(sameKindedAtoms(atom2,vatom2));
1918 tl_assert(sameKindedAtoms(atom3,vatom3));
1919 tl_assert(sameKindedAtoms(atom4,vatom4));
1920 switch (op) {
1921 case Iop_MAddF64:
1922 case Iop_MAddF64r32:
1923 case Iop_MSubF64:
1924 case Iop_MSubF64r32:
1925 /* I32(rm) x F64 x F64 x F64 -> F64 */
1926 return mkLazy4(mce, Ity_I64, vatom1, vatom2, vatom3, vatom4);
1927 default:
1928 ppIROp(op);
1929 VG_(tool_panic)("memcheck:expr2vbits_Qop");
1930 }
1931}
1932
1933
1934static
sewardjed69fdb2006-02-03 16:12:27 +00001935IRAtom* expr2vbits_Triop ( MCEnv* mce,
1936 IROp op,
1937 IRAtom* atom1, IRAtom* atom2, IRAtom* atom3 )
1938{
sewardjed69fdb2006-02-03 16:12:27 +00001939 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1940 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1941 IRAtom* vatom3 = expr2vbits( mce, atom3 );
1942
1943 tl_assert(isOriginalAtom(mce,atom1));
1944 tl_assert(isOriginalAtom(mce,atom2));
1945 tl_assert(isOriginalAtom(mce,atom3));
1946 tl_assert(isShadowAtom(mce,vatom1));
1947 tl_assert(isShadowAtom(mce,vatom2));
1948 tl_assert(isShadowAtom(mce,vatom3));
1949 tl_assert(sameKindedAtoms(atom1,vatom1));
1950 tl_assert(sameKindedAtoms(atom2,vatom2));
1951 tl_assert(sameKindedAtoms(atom3,vatom3));
1952 switch (op) {
1953 case Iop_AddF64:
1954 case Iop_AddF64r32:
1955 case Iop_SubF64:
1956 case Iop_SubF64r32:
1957 case Iop_MulF64:
1958 case Iop_MulF64r32:
1959 case Iop_DivF64:
1960 case Iop_DivF64r32:
sewardj22ac5f42006-02-03 22:55:04 +00001961 case Iop_ScaleF64:
1962 case Iop_Yl2xF64:
1963 case Iop_Yl2xp1F64:
1964 case Iop_AtanF64:
sewardjd6075eb2006-02-04 15:25:23 +00001965 case Iop_PRemF64:
1966 case Iop_PRem1F64:
sewardj22ac5f42006-02-03 22:55:04 +00001967 /* I32(rm) x F64 x F64 -> F64 */
sewardjed69fdb2006-02-03 16:12:27 +00001968 return mkLazy3(mce, Ity_I64, vatom1, vatom2, vatom3);
sewardjd6075eb2006-02-04 15:25:23 +00001969 case Iop_PRemC3210F64:
1970 case Iop_PRem1C3210F64:
1971 /* I32(rm) x F64 x F64 -> I32 */
1972 return mkLazy3(mce, Ity_I32, vatom1, vatom2, vatom3);
sewardjed69fdb2006-02-03 16:12:27 +00001973 default:
1974 ppIROp(op);
1975 VG_(tool_panic)("memcheck:expr2vbits_Triop");
1976 }
1977}
1978
1979
1980static
sewardj95448072004-11-22 20:19:51 +00001981IRAtom* expr2vbits_Binop ( MCEnv* mce,
1982 IROp op,
1983 IRAtom* atom1, IRAtom* atom2 )
1984{
1985 IRType and_or_ty;
1986 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1987 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1988 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1989
1990 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1991 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1992
1993 tl_assert(isOriginalAtom(mce,atom1));
1994 tl_assert(isOriginalAtom(mce,atom2));
1995 tl_assert(isShadowAtom(mce,vatom1));
1996 tl_assert(isShadowAtom(mce,vatom2));
1997 tl_assert(sameKindedAtoms(atom1,vatom1));
1998 tl_assert(sameKindedAtoms(atom2,vatom2));
1999 switch (op) {
2000
sewardjacd2e912005-01-13 19:17:06 +00002001 /* 64-bit SIMD */
2002
2003 case Iop_ShrN16x4:
2004 case Iop_ShrN32x2:
sewardj03809ae2006-12-27 01:16:58 +00002005 case Iop_SarN8x8:
sewardjacd2e912005-01-13 19:17:06 +00002006 case Iop_SarN16x4:
2007 case Iop_SarN32x2:
2008 case Iop_ShlN16x4:
2009 case Iop_ShlN32x2:
sewardj114a9172008-02-09 01:49:32 +00002010 case Iop_ShlN8x8:
sewardjacd2e912005-01-13 19:17:06 +00002011 /* Same scheme as with all other shifts. */
2012 complainIfUndefined(mce, atom2);
sewardj7cf4e6b2008-05-01 20:24:26 +00002013 return assignNew('V', mce, Ity_I64, binop(op, vatom1, atom2));
sewardjacd2e912005-01-13 19:17:06 +00002014
2015 case Iop_QNarrow32Sx2:
2016 case Iop_QNarrow16Sx4:
2017 case Iop_QNarrow16Ux4:
2018 return vectorNarrow64(mce, op, vatom1, vatom2);
2019
2020 case Iop_Min8Ux8:
2021 case Iop_Max8Ux8:
2022 case Iop_Avg8Ux8:
2023 case Iop_QSub8Sx8:
2024 case Iop_QSub8Ux8:
2025 case Iop_Sub8x8:
2026 case Iop_CmpGT8Sx8:
2027 case Iop_CmpEQ8x8:
2028 case Iop_QAdd8Sx8:
2029 case Iop_QAdd8Ux8:
2030 case Iop_Add8x8:
2031 return binary8Ix8(mce, vatom1, vatom2);
2032
2033 case Iop_Min16Sx4:
2034 case Iop_Max16Sx4:
2035 case Iop_Avg16Ux4:
2036 case Iop_QSub16Ux4:
2037 case Iop_QSub16Sx4:
2038 case Iop_Sub16x4:
2039 case Iop_Mul16x4:
2040 case Iop_MulHi16Sx4:
2041 case Iop_MulHi16Ux4:
2042 case Iop_CmpGT16Sx4:
2043 case Iop_CmpEQ16x4:
2044 case Iop_QAdd16Sx4:
2045 case Iop_QAdd16Ux4:
2046 case Iop_Add16x4:
2047 return binary16Ix4(mce, vatom1, vatom2);
2048
2049 case Iop_Sub32x2:
sewardj114a9172008-02-09 01:49:32 +00002050 case Iop_Mul32x2:
sewardjacd2e912005-01-13 19:17:06 +00002051 case Iop_CmpGT32Sx2:
2052 case Iop_CmpEQ32x2:
2053 case Iop_Add32x2:
2054 return binary32Ix2(mce, vatom1, vatom2);
2055
2056 /* 64-bit data-steering */
2057 case Iop_InterleaveLO32x2:
2058 case Iop_InterleaveLO16x4:
2059 case Iop_InterleaveLO8x8:
2060 case Iop_InterleaveHI32x2:
2061 case Iop_InterleaveHI16x4:
2062 case Iop_InterleaveHI8x8:
sewardj114a9172008-02-09 01:49:32 +00002063 case Iop_CatOddLanes16x4:
2064 case Iop_CatEvenLanes16x4:
sewardj7cf4e6b2008-05-01 20:24:26 +00002065 return assignNew('V', mce, Ity_I64, binop(op, vatom1, vatom2));
sewardjacd2e912005-01-13 19:17:06 +00002066
sewardj114a9172008-02-09 01:49:32 +00002067 /* Perm8x8: rearrange values in left arg using steering values
2068 from right arg. So rearrange the vbits in the same way but
2069 pessimise wrt steering values. */
2070 case Iop_Perm8x8:
2071 return mkUifU64(
2072 mce,
sewardj7cf4e6b2008-05-01 20:24:26 +00002073 assignNew('V', mce, Ity_I64, binop(op, vatom1, atom2)),
sewardj114a9172008-02-09 01:49:32 +00002074 mkPCast8x8(mce, vatom2)
2075 );
2076
sewardj20d38f22005-02-07 23:50:18 +00002077 /* V128-bit SIMD */
sewardj0b070592004-12-10 21:44:22 +00002078
sewardja1d93302004-12-12 16:45:06 +00002079 case Iop_ShrN16x8:
2080 case Iop_ShrN32x4:
2081 case Iop_ShrN64x2:
2082 case Iop_SarN16x8:
2083 case Iop_SarN32x4:
2084 case Iop_ShlN16x8:
2085 case Iop_ShlN32x4:
2086 case Iop_ShlN64x2:
sewardj620eb5b2005-10-22 12:50:43 +00002087 case Iop_ShlN8x16:
2088 case Iop_SarN8x16:
2089 /* Same scheme as with all other shifts. Note: 22 Oct 05:
2090 this is wrong now, scalar shifts are done properly lazily.
2091 Vector shifts should be fixed too. */
sewardja1d93302004-12-12 16:45:06 +00002092 complainIfUndefined(mce, atom2);
sewardj7cf4e6b2008-05-01 20:24:26 +00002093 return assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2));
sewardja1d93302004-12-12 16:45:06 +00002094
sewardjcbf8be72005-11-10 18:34:41 +00002095 /* V x V shifts/rotates are done using the standard lazy scheme. */
sewardj43d60752005-11-10 18:13:01 +00002096 case Iop_Shl8x16:
2097 case Iop_Shr8x16:
2098 case Iop_Sar8x16:
sewardjcbf8be72005-11-10 18:34:41 +00002099 case Iop_Rol8x16:
sewardj43d60752005-11-10 18:13:01 +00002100 return mkUifUV128(mce,
sewardj7cf4e6b2008-05-01 20:24:26 +00002101 assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
sewardj43d60752005-11-10 18:13:01 +00002102 mkPCast8x16(mce,vatom2)
2103 );
2104
2105 case Iop_Shl16x8:
2106 case Iop_Shr16x8:
2107 case Iop_Sar16x8:
sewardjcbf8be72005-11-10 18:34:41 +00002108 case Iop_Rol16x8:
sewardj43d60752005-11-10 18:13:01 +00002109 return mkUifUV128(mce,
sewardj7cf4e6b2008-05-01 20:24:26 +00002110 assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
sewardj43d60752005-11-10 18:13:01 +00002111 mkPCast16x8(mce,vatom2)
2112 );
2113
2114 case Iop_Shl32x4:
2115 case Iop_Shr32x4:
2116 case Iop_Sar32x4:
sewardjcbf8be72005-11-10 18:34:41 +00002117 case Iop_Rol32x4:
sewardj43d60752005-11-10 18:13:01 +00002118 return mkUifUV128(mce,
sewardj7cf4e6b2008-05-01 20:24:26 +00002119 assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
sewardj43d60752005-11-10 18:13:01 +00002120 mkPCast32x4(mce,vatom2)
2121 );
2122
sewardja1d93302004-12-12 16:45:06 +00002123 case Iop_QSub8Ux16:
2124 case Iop_QSub8Sx16:
2125 case Iop_Sub8x16:
2126 case Iop_Min8Ux16:
sewardj43d60752005-11-10 18:13:01 +00002127 case Iop_Min8Sx16:
sewardja1d93302004-12-12 16:45:06 +00002128 case Iop_Max8Ux16:
sewardj43d60752005-11-10 18:13:01 +00002129 case Iop_Max8Sx16:
sewardja1d93302004-12-12 16:45:06 +00002130 case Iop_CmpGT8Sx16:
sewardj43d60752005-11-10 18:13:01 +00002131 case Iop_CmpGT8Ux16:
sewardja1d93302004-12-12 16:45:06 +00002132 case Iop_CmpEQ8x16:
2133 case Iop_Avg8Ux16:
sewardj43d60752005-11-10 18:13:01 +00002134 case Iop_Avg8Sx16:
sewardja1d93302004-12-12 16:45:06 +00002135 case Iop_QAdd8Ux16:
2136 case Iop_QAdd8Sx16:
2137 case Iop_Add8x16:
2138 return binary8Ix16(mce, vatom1, vatom2);
2139
2140 case Iop_QSub16Ux8:
2141 case Iop_QSub16Sx8:
2142 case Iop_Sub16x8:
2143 case Iop_Mul16x8:
2144 case Iop_MulHi16Sx8:
2145 case Iop_MulHi16Ux8:
2146 case Iop_Min16Sx8:
sewardj43d60752005-11-10 18:13:01 +00002147 case Iop_Min16Ux8:
sewardja1d93302004-12-12 16:45:06 +00002148 case Iop_Max16Sx8:
sewardj43d60752005-11-10 18:13:01 +00002149 case Iop_Max16Ux8:
sewardja1d93302004-12-12 16:45:06 +00002150 case Iop_CmpGT16Sx8:
sewardj43d60752005-11-10 18:13:01 +00002151 case Iop_CmpGT16Ux8:
sewardja1d93302004-12-12 16:45:06 +00002152 case Iop_CmpEQ16x8:
2153 case Iop_Avg16Ux8:
sewardj43d60752005-11-10 18:13:01 +00002154 case Iop_Avg16Sx8:
sewardja1d93302004-12-12 16:45:06 +00002155 case Iop_QAdd16Ux8:
2156 case Iop_QAdd16Sx8:
2157 case Iop_Add16x8:
2158 return binary16Ix8(mce, vatom1, vatom2);
2159
2160 case Iop_Sub32x4:
2161 case Iop_CmpGT32Sx4:
sewardj43d60752005-11-10 18:13:01 +00002162 case Iop_CmpGT32Ux4:
sewardja1d93302004-12-12 16:45:06 +00002163 case Iop_CmpEQ32x4:
sewardj43d60752005-11-10 18:13:01 +00002164 case Iop_QAdd32Sx4:
2165 case Iop_QAdd32Ux4:
2166 case Iop_QSub32Sx4:
2167 case Iop_QSub32Ux4:
2168 case Iop_Avg32Ux4:
2169 case Iop_Avg32Sx4:
sewardja1d93302004-12-12 16:45:06 +00002170 case Iop_Add32x4:
sewardj43d60752005-11-10 18:13:01 +00002171 case Iop_Max32Ux4:
2172 case Iop_Max32Sx4:
2173 case Iop_Min32Ux4:
2174 case Iop_Min32Sx4:
sewardja1d93302004-12-12 16:45:06 +00002175 return binary32Ix4(mce, vatom1, vatom2);
2176
2177 case Iop_Sub64x2:
2178 case Iop_Add64x2:
2179 return binary64Ix2(mce, vatom1, vatom2);
2180
2181 case Iop_QNarrow32Sx4:
sewardj43d60752005-11-10 18:13:01 +00002182 case Iop_QNarrow32Ux4:
sewardja1d93302004-12-12 16:45:06 +00002183 case Iop_QNarrow16Sx8:
2184 case Iop_QNarrow16Ux8:
sewardj20d38f22005-02-07 23:50:18 +00002185 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00002186
sewardj0b070592004-12-10 21:44:22 +00002187 case Iop_Sub64Fx2:
2188 case Iop_Mul64Fx2:
2189 case Iop_Min64Fx2:
2190 case Iop_Max64Fx2:
2191 case Iop_Div64Fx2:
2192 case Iop_CmpLT64Fx2:
2193 case Iop_CmpLE64Fx2:
2194 case Iop_CmpEQ64Fx2:
sewardj545663e2005-11-05 01:55:04 +00002195 case Iop_CmpUN64Fx2:
sewardj0b070592004-12-10 21:44:22 +00002196 case Iop_Add64Fx2:
2197 return binary64Fx2(mce, vatom1, vatom2);
2198
2199 case Iop_Sub64F0x2:
2200 case Iop_Mul64F0x2:
2201 case Iop_Min64F0x2:
2202 case Iop_Max64F0x2:
2203 case Iop_Div64F0x2:
2204 case Iop_CmpLT64F0x2:
2205 case Iop_CmpLE64F0x2:
2206 case Iop_CmpEQ64F0x2:
sewardj545663e2005-11-05 01:55:04 +00002207 case Iop_CmpUN64F0x2:
sewardj0b070592004-12-10 21:44:22 +00002208 case Iop_Add64F0x2:
2209 return binary64F0x2(mce, vatom1, vatom2);
2210
sewardj170ee212004-12-10 18:57:51 +00002211 case Iop_Sub32Fx4:
2212 case Iop_Mul32Fx4:
2213 case Iop_Min32Fx4:
2214 case Iop_Max32Fx4:
2215 case Iop_Div32Fx4:
2216 case Iop_CmpLT32Fx4:
2217 case Iop_CmpLE32Fx4:
2218 case Iop_CmpEQ32Fx4:
sewardj545663e2005-11-05 01:55:04 +00002219 case Iop_CmpUN32Fx4:
cerione78ba2a2005-11-14 03:00:35 +00002220 case Iop_CmpGT32Fx4:
2221 case Iop_CmpGE32Fx4:
sewardj3245c912004-12-10 14:58:26 +00002222 case Iop_Add32Fx4:
2223 return binary32Fx4(mce, vatom1, vatom2);
2224
sewardj170ee212004-12-10 18:57:51 +00002225 case Iop_Sub32F0x4:
2226 case Iop_Mul32F0x4:
2227 case Iop_Min32F0x4:
2228 case Iop_Max32F0x4:
2229 case Iop_Div32F0x4:
2230 case Iop_CmpLT32F0x4:
2231 case Iop_CmpLE32F0x4:
2232 case Iop_CmpEQ32F0x4:
sewardj545663e2005-11-05 01:55:04 +00002233 case Iop_CmpUN32F0x4:
sewardj170ee212004-12-10 18:57:51 +00002234 case Iop_Add32F0x4:
2235 return binary32F0x4(mce, vatom1, vatom2);
2236
sewardj20d38f22005-02-07 23:50:18 +00002237 /* V128-bit data-steering */
2238 case Iop_SetV128lo32:
2239 case Iop_SetV128lo64:
2240 case Iop_64HLtoV128:
sewardja1d93302004-12-12 16:45:06 +00002241 case Iop_InterleaveLO64x2:
2242 case Iop_InterleaveLO32x4:
2243 case Iop_InterleaveLO16x8:
2244 case Iop_InterleaveLO8x16:
2245 case Iop_InterleaveHI64x2:
2246 case Iop_InterleaveHI32x4:
2247 case Iop_InterleaveHI16x8:
2248 case Iop_InterleaveHI8x16:
sewardj7cf4e6b2008-05-01 20:24:26 +00002249 return assignNew('V', mce, Ity_V128, binop(op, vatom1, vatom2));
sewardj620eb5b2005-10-22 12:50:43 +00002250
2251 /* Perm8x16: rearrange values in left arg using steering values
2252 from right arg. So rearrange the vbits in the same way but
2253 pessimise wrt steering values. */
2254 case Iop_Perm8x16:
2255 return mkUifUV128(
2256 mce,
sewardj7cf4e6b2008-05-01 20:24:26 +00002257 assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
sewardj620eb5b2005-10-22 12:50:43 +00002258 mkPCast8x16(mce, vatom2)
2259 );
sewardj170ee212004-12-10 18:57:51 +00002260
sewardj43d60752005-11-10 18:13:01 +00002261 /* These two take the lower half of each 16-bit lane, sign/zero
2262 extend it to 32, and multiply together, producing a 32x4
2263 result (and implicitly ignoring half the operand bits). So
2264 treat it as a bunch of independent 16x8 operations, but then
2265 do 32-bit shifts left-right to copy the lower half results
2266 (which are all 0s or all 1s due to PCasting in binary16Ix8)
2267 into the upper half of each result lane. */
2268 case Iop_MullEven16Ux8:
2269 case Iop_MullEven16Sx8: {
2270 IRAtom* at;
2271 at = binary16Ix8(mce,vatom1,vatom2);
sewardj7cf4e6b2008-05-01 20:24:26 +00002272 at = assignNew('V', mce, Ity_V128, binop(Iop_ShlN32x4, at, mkU8(16)));
2273 at = assignNew('V', mce, Ity_V128, binop(Iop_SarN32x4, at, mkU8(16)));
sewardj43d60752005-11-10 18:13:01 +00002274 return at;
2275 }
2276
2277 /* Same deal as Iop_MullEven16{S,U}x8 */
2278 case Iop_MullEven8Ux16:
2279 case Iop_MullEven8Sx16: {
2280 IRAtom* at;
2281 at = binary8Ix16(mce,vatom1,vatom2);
sewardj7cf4e6b2008-05-01 20:24:26 +00002282 at = assignNew('V', mce, Ity_V128, binop(Iop_ShlN16x8, at, mkU8(8)));
2283 at = assignNew('V', mce, Ity_V128, binop(Iop_SarN16x8, at, mkU8(8)));
sewardj43d60752005-11-10 18:13:01 +00002284 return at;
2285 }
2286
2287 /* narrow 2xV128 into 1xV128, hi half from left arg, in a 2 x
2288 32x4 -> 16x8 laneage, discarding the upper half of each lane.
2289 Simply apply same op to the V bits, since this really no more
2290 than a data steering operation. */
sewardjcbf8be72005-11-10 18:34:41 +00002291 case Iop_Narrow32x4:
2292 case Iop_Narrow16x8:
sewardj7cf4e6b2008-05-01 20:24:26 +00002293 return assignNew('V', mce, Ity_V128,
2294 binop(op, vatom1, vatom2));
sewardj43d60752005-11-10 18:13:01 +00002295
2296 case Iop_ShrV128:
2297 case Iop_ShlV128:
2298 /* Same scheme as with all other shifts. Note: 10 Nov 05:
2299 this is wrong now, scalar shifts are done properly lazily.
2300 Vector shifts should be fixed too. */
2301 complainIfUndefined(mce, atom2);
sewardj7cf4e6b2008-05-01 20:24:26 +00002302 return assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2));
sewardj43d60752005-11-10 18:13:01 +00002303
2304
sewardj69a13322005-04-23 01:14:51 +00002305 /* I128-bit data-steering */
2306 case Iop_64HLto128:
sewardj7cf4e6b2008-05-01 20:24:26 +00002307 return assignNew('V', mce, Ity_I128, binop(op, vatom1, vatom2));
sewardj69a13322005-04-23 01:14:51 +00002308
sewardj3245c912004-12-10 14:58:26 +00002309 /* Scalar floating point */
2310
sewardjed69fdb2006-02-03 16:12:27 +00002311 case Iop_RoundF64toInt:
2312 case Iop_RoundF64toF32:
sewardj95448072004-11-22 20:19:51 +00002313 case Iop_F64toI64:
sewardje9e16d32004-12-10 13:17:55 +00002314 case Iop_I64toF64:
sewardj22ac5f42006-02-03 22:55:04 +00002315 case Iop_SinF64:
2316 case Iop_CosF64:
2317 case Iop_TanF64:
2318 case Iop_2xm1F64:
2319 case Iop_SqrtF64:
2320 /* I32(rm) x I64/F64 -> I64/F64 */
sewardj95448072004-11-22 20:19:51 +00002321 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
2322
sewardj95448072004-11-22 20:19:51 +00002323 case Iop_F64toI32:
sewardje9e16d32004-12-10 13:17:55 +00002324 case Iop_F64toF32:
sewardj95448072004-11-22 20:19:51 +00002325 /* First arg is I32 (rounding mode), second is F64 (data). */
2326 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
2327
2328 case Iop_F64toI16:
2329 /* First arg is I32 (rounding mode), second is F64 (data). */
2330 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
2331
sewardj95448072004-11-22 20:19:51 +00002332 case Iop_CmpF64:
2333 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
2334
2335 /* non-FP after here */
2336
2337 case Iop_DivModU64to32:
2338 case Iop_DivModS64to32:
2339 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
2340
sewardj69a13322005-04-23 01:14:51 +00002341 case Iop_DivModU128to64:
2342 case Iop_DivModS128to64:
2343 return mkLazy2(mce, Ity_I128, vatom1, vatom2);
2344
sewardj95448072004-11-22 20:19:51 +00002345 case Iop_16HLto32:
sewardj7cf4e6b2008-05-01 20:24:26 +00002346 return assignNew('V', mce, Ity_I32, binop(op, vatom1, vatom2));
sewardj95448072004-11-22 20:19:51 +00002347 case Iop_32HLto64:
sewardj7cf4e6b2008-05-01 20:24:26 +00002348 return assignNew('V', mce, Ity_I64, binop(op, vatom1, vatom2));
sewardj95448072004-11-22 20:19:51 +00002349
sewardj6cf40ff2005-04-20 22:31:26 +00002350 case Iop_MullS64:
2351 case Iop_MullU64: {
2352 IRAtom* vLo64 = mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
2353 IRAtom* vHi64 = mkPCastTo(mce, Ity_I64, vLo64);
sewardj7cf4e6b2008-05-01 20:24:26 +00002354 return assignNew('V', mce, Ity_I128, binop(Iop_64HLto128, vHi64, vLo64));
sewardj6cf40ff2005-04-20 22:31:26 +00002355 }
2356
sewardj95448072004-11-22 20:19:51 +00002357 case Iop_MullS32:
2358 case Iop_MullU32: {
2359 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
2360 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
sewardj7cf4e6b2008-05-01 20:24:26 +00002361 return assignNew('V', mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
sewardj95448072004-11-22 20:19:51 +00002362 }
2363
2364 case Iop_MullS16:
2365 case Iop_MullU16: {
2366 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
2367 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
sewardj7cf4e6b2008-05-01 20:24:26 +00002368 return assignNew('V', mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
sewardj95448072004-11-22 20:19:51 +00002369 }
2370
2371 case Iop_MullS8:
2372 case Iop_MullU8: {
2373 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
2374 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
sewardj7cf4e6b2008-05-01 20:24:26 +00002375 return assignNew('V', mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
sewardj95448072004-11-22 20:19:51 +00002376 }
2377
cerion9e591082005-06-23 15:28:34 +00002378 case Iop_DivS32:
2379 case Iop_DivU32:
2380 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
2381
sewardjb00944a2005-12-23 12:47:16 +00002382 case Iop_DivS64:
2383 case Iop_DivU64:
2384 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
2385
sewardj95448072004-11-22 20:19:51 +00002386 case Iop_Add32:
sewardjd5204dc2004-12-31 01:16:11 +00002387 if (mce->bogusLiterals)
2388 return expensiveAddSub(mce,True,Ity_I32,
2389 vatom1,vatom2, atom1,atom2);
2390 else
2391 goto cheap_AddSub32;
sewardj95448072004-11-22 20:19:51 +00002392 case Iop_Sub32:
sewardjd5204dc2004-12-31 01:16:11 +00002393 if (mce->bogusLiterals)
2394 return expensiveAddSub(mce,False,Ity_I32,
2395 vatom1,vatom2, atom1,atom2);
2396 else
2397 goto cheap_AddSub32;
2398
2399 cheap_AddSub32:
sewardj95448072004-11-22 20:19:51 +00002400 case Iop_Mul32:
sewardj992dff92005-10-07 11:08:55 +00002401 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
2402
sewardj463b3d92005-07-18 11:41:15 +00002403 case Iop_CmpORD32S:
2404 case Iop_CmpORD32U:
sewardj1bc82102005-12-23 00:16:24 +00002405 case Iop_CmpORD64S:
2406 case Iop_CmpORD64U:
2407 return doCmpORD(mce, op, vatom1,vatom2, atom1,atom2);
sewardj95448072004-11-22 20:19:51 +00002408
sewardj681be302005-01-15 20:43:58 +00002409 case Iop_Add64:
tomd9774d72005-06-27 08:11:01 +00002410 if (mce->bogusLiterals)
2411 return expensiveAddSub(mce,True,Ity_I64,
2412 vatom1,vatom2, atom1,atom2);
2413 else
2414 goto cheap_AddSub64;
sewardj681be302005-01-15 20:43:58 +00002415 case Iop_Sub64:
tomd9774d72005-06-27 08:11:01 +00002416 if (mce->bogusLiterals)
2417 return expensiveAddSub(mce,False,Ity_I64,
2418 vatom1,vatom2, atom1,atom2);
2419 else
2420 goto cheap_AddSub64;
2421
2422 cheap_AddSub64:
2423 case Iop_Mul64:
sewardj681be302005-01-15 20:43:58 +00002424 return mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
2425
sewardj95448072004-11-22 20:19:51 +00002426 case Iop_Mul16:
2427 case Iop_Add16:
2428 case Iop_Sub16:
2429 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
2430
2431 case Iop_Sub8:
2432 case Iop_Add8:
2433 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
2434
sewardj69a13322005-04-23 01:14:51 +00002435 case Iop_CmpEQ64:
sewardje6f8af42005-07-06 18:48:59 +00002436 case Iop_CmpNE64:
sewardj69a13322005-04-23 01:14:51 +00002437 if (mce->bogusLiterals)
2438 return expensiveCmpEQorNE(mce,Ity_I64, vatom1,vatom2, atom1,atom2 );
2439 else
2440 goto cheap_cmp64;
2441 cheap_cmp64:
tomcd986332005-04-26 07:44:48 +00002442 case Iop_CmpLE64S: case Iop_CmpLE64U:
2443 case Iop_CmpLT64U: case Iop_CmpLT64S:
sewardj69a13322005-04-23 01:14:51 +00002444 return mkPCastTo(mce, Ity_I1, mkUifU64(mce, vatom1,vatom2));
2445
sewardjd5204dc2004-12-31 01:16:11 +00002446 case Iop_CmpEQ32:
sewardje6f8af42005-07-06 18:48:59 +00002447 case Iop_CmpNE32:
sewardjd5204dc2004-12-31 01:16:11 +00002448 if (mce->bogusLiterals)
2449 return expensiveCmpEQorNE(mce,Ity_I32, vatom1,vatom2, atom1,atom2 );
2450 else
2451 goto cheap_cmp32;
sewardjd5204dc2004-12-31 01:16:11 +00002452 cheap_cmp32:
sewardj95448072004-11-22 20:19:51 +00002453 case Iop_CmpLE32S: case Iop_CmpLE32U:
2454 case Iop_CmpLT32U: case Iop_CmpLT32S:
sewardj95448072004-11-22 20:19:51 +00002455 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
2456
2457 case Iop_CmpEQ16: case Iop_CmpNE16:
2458 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
2459
2460 case Iop_CmpEQ8: case Iop_CmpNE8:
2461 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
2462
sewardjaaddbc22005-10-07 09:49:53 +00002463 case Iop_Shl64: case Iop_Shr64: case Iop_Sar64:
2464 return scalarShift( mce, Ity_I64, op, vatom1,vatom2, atom1,atom2 );
2465
sewardj95448072004-11-22 20:19:51 +00002466 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
sewardjaaddbc22005-10-07 09:49:53 +00002467 return scalarShift( mce, Ity_I32, op, vatom1,vatom2, atom1,atom2 );
sewardj95448072004-11-22 20:19:51 +00002468
sewardjdb67f5f2004-12-14 01:15:31 +00002469 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjaaddbc22005-10-07 09:49:53 +00002470 return scalarShift( mce, Ity_I16, op, vatom1,vatom2, atom1,atom2 );
sewardj95448072004-11-22 20:19:51 +00002471
2472 case Iop_Shl8: case Iop_Shr8:
sewardjaaddbc22005-10-07 09:49:53 +00002473 return scalarShift( mce, Ity_I8, op, vatom1,vatom2, atom1,atom2 );
sewardj95448072004-11-22 20:19:51 +00002474
sewardj20d38f22005-02-07 23:50:18 +00002475 case Iop_AndV128:
2476 uifu = mkUifUV128; difd = mkDifDV128;
2477 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj7010f6e2004-12-10 13:35:22 +00002478 case Iop_And64:
2479 uifu = mkUifU64; difd = mkDifD64;
2480 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardj95448072004-11-22 20:19:51 +00002481 case Iop_And32:
2482 uifu = mkUifU32; difd = mkDifD32;
2483 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
2484 case Iop_And16:
2485 uifu = mkUifU16; difd = mkDifD16;
2486 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
2487 case Iop_And8:
2488 uifu = mkUifU8; difd = mkDifD8;
2489 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
2490
sewardj20d38f22005-02-07 23:50:18 +00002491 case Iop_OrV128:
2492 uifu = mkUifUV128; difd = mkDifDV128;
2493 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj7010f6e2004-12-10 13:35:22 +00002494 case Iop_Or64:
2495 uifu = mkUifU64; difd = mkDifD64;
2496 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardj95448072004-11-22 20:19:51 +00002497 case Iop_Or32:
2498 uifu = mkUifU32; difd = mkDifD32;
2499 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
2500 case Iop_Or16:
2501 uifu = mkUifU16; difd = mkDifD16;
2502 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
2503 case Iop_Or8:
2504 uifu = mkUifU8; difd = mkDifD8;
2505 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
2506
2507 do_And_Or:
2508 return
2509 assignNew(
sewardj7cf4e6b2008-05-01 20:24:26 +00002510 'V', mce,
sewardj95448072004-11-22 20:19:51 +00002511 and_or_ty,
2512 difd(mce, uifu(mce, vatom1, vatom2),
2513 difd(mce, improve(mce, atom1, vatom1),
2514 improve(mce, atom2, vatom2) ) ) );
2515
2516 case Iop_Xor8:
2517 return mkUifU8(mce, vatom1, vatom2);
2518 case Iop_Xor16:
2519 return mkUifU16(mce, vatom1, vatom2);
2520 case Iop_Xor32:
2521 return mkUifU32(mce, vatom1, vatom2);
sewardj7010f6e2004-12-10 13:35:22 +00002522 case Iop_Xor64:
2523 return mkUifU64(mce, vatom1, vatom2);
sewardj20d38f22005-02-07 23:50:18 +00002524 case Iop_XorV128:
2525 return mkUifUV128(mce, vatom1, vatom2);
njn25e49d8e72002-09-23 09:36:25 +00002526
2527 default:
sewardj95448072004-11-22 20:19:51 +00002528 ppIROp(op);
2529 VG_(tool_panic)("memcheck:expr2vbits_Binop");
njn25e49d8e72002-09-23 09:36:25 +00002530 }
njn25e49d8e72002-09-23 09:36:25 +00002531}
2532
njn25e49d8e72002-09-23 09:36:25 +00002533
sewardj95448072004-11-22 20:19:51 +00002534static
2535IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
2536{
2537 IRAtom* vatom = expr2vbits( mce, atom );
2538 tl_assert(isOriginalAtom(mce,atom));
2539 switch (op) {
2540
sewardj0b070592004-12-10 21:44:22 +00002541 case Iop_Sqrt64Fx2:
2542 return unary64Fx2(mce, vatom);
2543
2544 case Iop_Sqrt64F0x2:
2545 return unary64F0x2(mce, vatom);
2546
sewardj170ee212004-12-10 18:57:51 +00002547 case Iop_Sqrt32Fx4:
2548 case Iop_RSqrt32Fx4:
2549 case Iop_Recip32Fx4:
cerion176cb4c2005-11-16 17:21:49 +00002550 case Iop_I32UtoFx4:
2551 case Iop_I32StoFx4:
2552 case Iop_QFtoI32Ux4_RZ:
2553 case Iop_QFtoI32Sx4_RZ:
2554 case Iop_RoundF32x4_RM:
2555 case Iop_RoundF32x4_RP:
2556 case Iop_RoundF32x4_RN:
2557 case Iop_RoundF32x4_RZ:
sewardj170ee212004-12-10 18:57:51 +00002558 return unary32Fx4(mce, vatom);
2559
2560 case Iop_Sqrt32F0x4:
2561 case Iop_RSqrt32F0x4:
2562 case Iop_Recip32F0x4:
2563 return unary32F0x4(mce, vatom);
2564
sewardj20d38f22005-02-07 23:50:18 +00002565 case Iop_32UtoV128:
2566 case Iop_64UtoV128:
sewardj620eb5b2005-10-22 12:50:43 +00002567 case Iop_Dup8x16:
2568 case Iop_Dup16x8:
2569 case Iop_Dup32x4:
sewardj7cf4e6b2008-05-01 20:24:26 +00002570 return assignNew('V', mce, Ity_V128, unop(op, vatom));
sewardj170ee212004-12-10 18:57:51 +00002571
sewardj95448072004-11-22 20:19:51 +00002572 case Iop_F32toF64:
2573 case Iop_I32toF64:
sewardj95448072004-11-22 20:19:51 +00002574 case Iop_NegF64:
sewardj95448072004-11-22 20:19:51 +00002575 case Iop_AbsF64:
sewardj4f3e0f22006-01-27 15:11:31 +00002576 case Iop_Est5FRSqrt:
sewardjdead90a2008-08-08 08:38:23 +00002577 case Iop_RoundF64toF64_NEAREST:
2578 case Iop_RoundF64toF64_NegINF:
2579 case Iop_RoundF64toF64_PosINF:
2580 case Iop_RoundF64toF64_ZERO:
sewardj39cc7352005-06-09 21:31:55 +00002581 case Iop_Clz64:
2582 case Iop_Ctz64:
sewardj95448072004-11-22 20:19:51 +00002583 return mkPCastTo(mce, Ity_I64, vatom);
2584
sewardj95448072004-11-22 20:19:51 +00002585 case Iop_Clz32:
2586 case Iop_Ctz32:
sewardjed69fdb2006-02-03 16:12:27 +00002587 case Iop_TruncF64asF32:
sewardj95448072004-11-22 20:19:51 +00002588 return mkPCastTo(mce, Ity_I32, vatom);
2589
sewardjd9dbc192005-04-27 11:40:27 +00002590 case Iop_1Uto64:
2591 case Iop_8Uto64:
2592 case Iop_8Sto64:
2593 case Iop_16Uto64:
2594 case Iop_16Sto64:
sewardj95448072004-11-22 20:19:51 +00002595 case Iop_32Sto64:
2596 case Iop_32Uto64:
sewardj20d38f22005-02-07 23:50:18 +00002597 case Iop_V128to64:
2598 case Iop_V128HIto64:
sewardj6cf40ff2005-04-20 22:31:26 +00002599 case Iop_128HIto64:
2600 case Iop_128to64:
sewardj7cf4e6b2008-05-01 20:24:26 +00002601 return assignNew('V', mce, Ity_I64, unop(op, vatom));
sewardj95448072004-11-22 20:19:51 +00002602
2603 case Iop_64to32:
2604 case Iop_64HIto32:
2605 case Iop_1Uto32:
sewardj463b3d92005-07-18 11:41:15 +00002606 case Iop_1Sto32:
sewardj95448072004-11-22 20:19:51 +00002607 case Iop_8Uto32:
2608 case Iop_16Uto32:
2609 case Iop_16Sto32:
2610 case Iop_8Sto32:
cerionfafaa0d2005-09-12 22:29:38 +00002611 case Iop_V128to32:
sewardj7cf4e6b2008-05-01 20:24:26 +00002612 return assignNew('V', mce, Ity_I32, unop(op, vatom));
sewardj95448072004-11-22 20:19:51 +00002613
2614 case Iop_8Sto16:
2615 case Iop_8Uto16:
2616 case Iop_32to16:
2617 case Iop_32HIto16:
sewardjd9dbc192005-04-27 11:40:27 +00002618 case Iop_64to16:
sewardj7cf4e6b2008-05-01 20:24:26 +00002619 return assignNew('V', mce, Ity_I16, unop(op, vatom));
sewardj95448072004-11-22 20:19:51 +00002620
2621 case Iop_1Uto8:
2622 case Iop_16to8:
sewardj9a807e02006-12-17 14:20:31 +00002623 case Iop_16HIto8:
sewardj95448072004-11-22 20:19:51 +00002624 case Iop_32to8:
sewardjd9dbc192005-04-27 11:40:27 +00002625 case Iop_64to8:
sewardj7cf4e6b2008-05-01 20:24:26 +00002626 return assignNew('V', mce, Ity_I8, unop(op, vatom));
sewardj95448072004-11-22 20:19:51 +00002627
2628 case Iop_32to1:
sewardj7cf4e6b2008-05-01 20:24:26 +00002629 return assignNew('V', mce, Ity_I1, unop(Iop_32to1, vatom));
sewardj95448072004-11-22 20:19:51 +00002630
sewardjd9dbc192005-04-27 11:40:27 +00002631 case Iop_64to1:
sewardj7cf4e6b2008-05-01 20:24:26 +00002632 return assignNew('V', mce, Ity_I1, unop(Iop_64to1, vatom));
sewardjd9dbc192005-04-27 11:40:27 +00002633
sewardj95448072004-11-22 20:19:51 +00002634 case Iop_ReinterpF64asI64:
2635 case Iop_ReinterpI64asF64:
sewardj0b070592004-12-10 21:44:22 +00002636 case Iop_ReinterpI32asF32:
sewardj20d38f22005-02-07 23:50:18 +00002637 case Iop_NotV128:
sewardj7010f6e2004-12-10 13:35:22 +00002638 case Iop_Not64:
sewardj95448072004-11-22 20:19:51 +00002639 case Iop_Not32:
2640 case Iop_Not16:
2641 case Iop_Not8:
2642 case Iop_Not1:
2643 return vatom;
sewardj7010f6e2004-12-10 13:35:22 +00002644
sewardj95448072004-11-22 20:19:51 +00002645 default:
2646 ppIROp(op);
2647 VG_(tool_panic)("memcheck:expr2vbits_Unop");
2648 }
2649}
2650
2651
sewardj170ee212004-12-10 18:57:51 +00002652/* Worker function; do not call directly. */
sewardj95448072004-11-22 20:19:51 +00002653static
sewardj2e595852005-06-30 23:33:37 +00002654IRAtom* expr2vbits_Load_WRK ( MCEnv* mce,
2655 IREndness end, IRType ty,
2656 IRAtom* addr, UInt bias )
sewardj95448072004-11-22 20:19:51 +00002657{
2658 void* helper;
2659 Char* hname;
2660 IRDirty* di;
2661 IRTemp datavbits;
2662 IRAtom* addrAct;
2663
2664 tl_assert(isOriginalAtom(mce,addr));
sewardj2e595852005-06-30 23:33:37 +00002665 tl_assert(end == Iend_LE || end == Iend_BE);
sewardj95448072004-11-22 20:19:51 +00002666
2667 /* First, emit a definedness test for the address. This also sets
2668 the address (shadow) to 'defined' following the test. */
2669 complainIfUndefined( mce, addr );
2670
2671 /* Now cook up a call to the relevant helper function, to read the
2672 data V bits from shadow memory. */
sewardj7cf4e6b2008-05-01 20:24:26 +00002673 ty = shadowTypeV(ty);
sewardj2e595852005-06-30 23:33:37 +00002674
2675 if (end == Iend_LE) {
2676 switch (ty) {
njn1d0825f2006-03-27 11:37:07 +00002677 case Ity_I64: helper = &MC_(helperc_LOADV64le);
2678 hname = "MC_(helperc_LOADV64le)";
sewardj2e595852005-06-30 23:33:37 +00002679 break;
njn1d0825f2006-03-27 11:37:07 +00002680 case Ity_I32: helper = &MC_(helperc_LOADV32le);
2681 hname = "MC_(helperc_LOADV32le)";
sewardj2e595852005-06-30 23:33:37 +00002682 break;
njn1d0825f2006-03-27 11:37:07 +00002683 case Ity_I16: helper = &MC_(helperc_LOADV16le);
2684 hname = "MC_(helperc_LOADV16le)";
sewardj2e595852005-06-30 23:33:37 +00002685 break;
njn1d0825f2006-03-27 11:37:07 +00002686 case Ity_I8: helper = &MC_(helperc_LOADV8);
2687 hname = "MC_(helperc_LOADV8)";
sewardj2e595852005-06-30 23:33:37 +00002688 break;
2689 default: ppIRType(ty);
2690 VG_(tool_panic)("memcheck:do_shadow_Load(LE)");
2691 }
2692 } else {
sewardj8cf88b72005-07-08 01:29:33 +00002693 switch (ty) {
njn1d0825f2006-03-27 11:37:07 +00002694 case Ity_I64: helper = &MC_(helperc_LOADV64be);
2695 hname = "MC_(helperc_LOADV64be)";
sewardj8cf88b72005-07-08 01:29:33 +00002696 break;
njn1d0825f2006-03-27 11:37:07 +00002697 case Ity_I32: helper = &MC_(helperc_LOADV32be);
2698 hname = "MC_(helperc_LOADV32be)";
sewardj8cf88b72005-07-08 01:29:33 +00002699 break;
njn1d0825f2006-03-27 11:37:07 +00002700 case Ity_I16: helper = &MC_(helperc_LOADV16be);
2701 hname = "MC_(helperc_LOADV16be)";
sewardj8cf88b72005-07-08 01:29:33 +00002702 break;
njn1d0825f2006-03-27 11:37:07 +00002703 case Ity_I8: helper = &MC_(helperc_LOADV8);
2704 hname = "MC_(helperc_LOADV8)";
sewardj8cf88b72005-07-08 01:29:33 +00002705 break;
2706 default: ppIRType(ty);
2707 VG_(tool_panic)("memcheck:do_shadow_Load(BE)");
2708 }
sewardj95448072004-11-22 20:19:51 +00002709 }
2710
2711 /* Generate the actual address into addrAct. */
2712 if (bias == 0) {
2713 addrAct = addr;
2714 } else {
sewardj7cf97ee2004-11-28 14:25:01 +00002715 IROp mkAdd;
2716 IRAtom* eBias;
sewardj95448072004-11-22 20:19:51 +00002717 IRType tyAddr = mce->hWordTy;
2718 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj7cf97ee2004-11-28 14:25:01 +00002719 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2720 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj7cf4e6b2008-05-01 20:24:26 +00002721 addrAct = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBias) );
sewardj95448072004-11-22 20:19:51 +00002722 }
2723
2724 /* We need to have a place to park the V bits we're just about to
2725 read. */
2726 datavbits = newIRTemp(mce->bb->tyenv, ty);
2727 di = unsafeIRDirty_1_N( datavbits,
sewardj53ee1fc2005-12-23 02:29:58 +00002728 1/*regparms*/,
2729 hname, VG_(fnptr_to_fnentry)( helper ),
sewardj95448072004-11-22 20:19:51 +00002730 mkIRExprVec_1( addrAct ));
2731 setHelperAnns( mce, di );
sewardj7cf4e6b2008-05-01 20:24:26 +00002732 stmt( 'V', mce, IRStmt_Dirty(di) );
sewardj95448072004-11-22 20:19:51 +00002733
2734 return mkexpr(datavbits);
2735}
2736
2737
2738static
sewardj2e595852005-06-30 23:33:37 +00002739IRAtom* expr2vbits_Load ( MCEnv* mce,
2740 IREndness end, IRType ty,
2741 IRAtom* addr, UInt bias )
sewardj170ee212004-12-10 18:57:51 +00002742{
2743 IRAtom *v64hi, *v64lo;
sewardj2e595852005-06-30 23:33:37 +00002744 tl_assert(end == Iend_LE || end == Iend_BE);
sewardj7cf4e6b2008-05-01 20:24:26 +00002745 switch (shadowTypeV(ty)) {
sewardj170ee212004-12-10 18:57:51 +00002746 case Ity_I8:
2747 case Ity_I16:
2748 case Ity_I32:
2749 case Ity_I64:
sewardj2e595852005-06-30 23:33:37 +00002750 return expr2vbits_Load_WRK(mce, end, ty, addr, bias);
sewardj170ee212004-12-10 18:57:51 +00002751 case Ity_V128:
sewardj2e595852005-06-30 23:33:37 +00002752 if (end == Iend_LE) {
2753 v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
2754 v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
2755 } else {
sewardj2e595852005-06-30 23:33:37 +00002756 v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
2757 v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
2758 }
sewardj7cf4e6b2008-05-01 20:24:26 +00002759 return assignNew( 'V', mce,
sewardj170ee212004-12-10 18:57:51 +00002760 Ity_V128,
sewardj20d38f22005-02-07 23:50:18 +00002761 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj170ee212004-12-10 18:57:51 +00002762 default:
sewardj2e595852005-06-30 23:33:37 +00002763 VG_(tool_panic)("expr2vbits_Load");
sewardj170ee212004-12-10 18:57:51 +00002764 }
2765}
2766
2767
2768static
sewardj95448072004-11-22 20:19:51 +00002769IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
2770 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
2771{
2772 IRAtom *vbitsC, *vbits0, *vbitsX;
2773 IRType ty;
2774 /* Given Mux0X(cond,expr0,exprX), generate
2775 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2776 That is, steer the V bits like the originals, but trash the
2777 result if the steering value is undefined. This gives
2778 lazy propagation. */
2779 tl_assert(isOriginalAtom(mce, cond));
2780 tl_assert(isOriginalAtom(mce, expr0));
2781 tl_assert(isOriginalAtom(mce, exprX));
2782
2783 vbitsC = expr2vbits(mce, cond);
2784 vbits0 = expr2vbits(mce, expr0);
2785 vbitsX = expr2vbits(mce, exprX);
2786 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2787
2788 return
sewardj7cf4e6b2008-05-01 20:24:26 +00002789 mkUifU(mce, ty, assignNew('V', mce, ty,
2790 IRExpr_Mux0X(cond, vbits0, vbitsX)),
sewardj95448072004-11-22 20:19:51 +00002791 mkPCastTo(mce, ty, vbitsC) );
2792}
2793
2794/* --------- This is the main expression-handling function. --------- */
2795
2796static
2797IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2798{
2799 switch (e->tag) {
2800
2801 case Iex_Get:
2802 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2803
2804 case Iex_GetI:
2805 return shadow_GETI( mce, e->Iex.GetI.descr,
2806 e->Iex.GetI.ix, e->Iex.GetI.bias );
2807
sewardj0b9d74a2006-12-24 02:24:11 +00002808 case Iex_RdTmp:
sewardj7cf4e6b2008-05-01 20:24:26 +00002809 return IRExpr_RdTmp( findShadowTmpV(mce, e->Iex.RdTmp.tmp) );
sewardj95448072004-11-22 20:19:51 +00002810
2811 case Iex_Const:
sewardj7cf4e6b2008-05-01 20:24:26 +00002812 return definedOfType(shadowTypeV(typeOfIRExpr(mce->bb->tyenv, e)));
sewardj95448072004-11-22 20:19:51 +00002813
sewardje91cea72006-02-08 19:32:02 +00002814 case Iex_Qop:
2815 return expr2vbits_Qop(
2816 mce,
2817 e->Iex.Qop.op,
2818 e->Iex.Qop.arg1, e->Iex.Qop.arg2,
2819 e->Iex.Qop.arg3, e->Iex.Qop.arg4
2820 );
2821
sewardjed69fdb2006-02-03 16:12:27 +00002822 case Iex_Triop:
2823 return expr2vbits_Triop(
2824 mce,
2825 e->Iex.Triop.op,
2826 e->Iex.Triop.arg1, e->Iex.Triop.arg2, e->Iex.Triop.arg3
2827 );
2828
sewardj95448072004-11-22 20:19:51 +00002829 case Iex_Binop:
2830 return expr2vbits_Binop(
2831 mce,
2832 e->Iex.Binop.op,
2833 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2834 );
2835
2836 case Iex_Unop:
2837 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2838
sewardj2e595852005-06-30 23:33:37 +00002839 case Iex_Load:
2840 return expr2vbits_Load( mce, e->Iex.Load.end,
2841 e->Iex.Load.ty,
2842 e->Iex.Load.addr, 0/*addr bias*/ );
sewardj95448072004-11-22 20:19:51 +00002843
2844 case Iex_CCall:
2845 return mkLazyN( mce, e->Iex.CCall.args,
2846 e->Iex.CCall.retty,
2847 e->Iex.CCall.cee );
2848
2849 case Iex_Mux0X:
2850 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2851 e->Iex.Mux0X.exprX);
njn25e49d8e72002-09-23 09:36:25 +00002852
2853 default:
sewardj95448072004-11-22 20:19:51 +00002854 VG_(printf)("\n");
2855 ppIRExpr(e);
2856 VG_(printf)("\n");
2857 VG_(tool_panic)("memcheck: expr2vbits");
njn25e49d8e72002-09-23 09:36:25 +00002858 }
njn25e49d8e72002-09-23 09:36:25 +00002859}
2860
2861/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00002862/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
njn25e49d8e72002-09-23 09:36:25 +00002863/*------------------------------------------------------------*/
2864
sewardj95448072004-11-22 20:19:51 +00002865/* Widen a value to the host word size. */
njn25e49d8e72002-09-23 09:36:25 +00002866
2867static
sewardj95448072004-11-22 20:19:51 +00002868IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
njn25e49d8e72002-09-23 09:36:25 +00002869{
sewardj7cf97ee2004-11-28 14:25:01 +00002870 IRType ty, tyH;
2871
sewardj95448072004-11-22 20:19:51 +00002872 /* vatom is vbits-value and as such can only have a shadow type. */
2873 tl_assert(isShadowAtom(mce,vatom));
njn25e49d8e72002-09-23 09:36:25 +00002874
sewardj7cf97ee2004-11-28 14:25:01 +00002875 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2876 tyH = mce->hWordTy;
njn25e49d8e72002-09-23 09:36:25 +00002877
sewardj95448072004-11-22 20:19:51 +00002878 if (tyH == Ity_I32) {
2879 switch (ty) {
sewardj7cf4e6b2008-05-01 20:24:26 +00002880 case Ity_I32:
2881 return vatom;
2882 case Ity_I16:
2883 return assignNew('V', mce, tyH, unop(Iop_16Uto32, vatom));
2884 case Ity_I8:
2885 return assignNew('V', mce, tyH, unop(Iop_8Uto32, vatom));
2886 default:
2887 goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00002888 }
sewardj6cf40ff2005-04-20 22:31:26 +00002889 } else
2890 if (tyH == Ity_I64) {
2891 switch (ty) {
sewardj7cf4e6b2008-05-01 20:24:26 +00002892 case Ity_I32:
2893 return assignNew('V', mce, tyH, unop(Iop_32Uto64, vatom));
2894 case Ity_I16:
2895 return assignNew('V', mce, tyH, unop(Iop_32Uto64,
2896 assignNew('V', mce, Ity_I32, unop(Iop_16Uto32, vatom))));
2897 case Ity_I8:
2898 return assignNew('V', mce, tyH, unop(Iop_32Uto64,
2899 assignNew('V', mce, Ity_I32, unop(Iop_8Uto32, vatom))));
2900 default:
2901 goto unhandled;
sewardj6cf40ff2005-04-20 22:31:26 +00002902 }
sewardj95448072004-11-22 20:19:51 +00002903 } else {
2904 goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00002905 }
sewardj95448072004-11-22 20:19:51 +00002906 unhandled:
2907 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
2908 VG_(tool_panic)("zwidenToHostWord");
njn25e49d8e72002-09-23 09:36:25 +00002909}
2910
njn25e49d8e72002-09-23 09:36:25 +00002911
sewardj95448072004-11-22 20:19:51 +00002912/* Generate a shadow store. addr is always the original address atom.
2913 You can pass in either originals or V-bits for the data atom, but
2914 obviously not both. */
njn25e49d8e72002-09-23 09:36:25 +00002915
sewardj95448072004-11-22 20:19:51 +00002916static
sewardj2e595852005-06-30 23:33:37 +00002917void do_shadow_Store ( MCEnv* mce,
2918 IREndness end,
2919 IRAtom* addr, UInt bias,
2920 IRAtom* data, IRAtom* vdata )
njn25e49d8e72002-09-23 09:36:25 +00002921{
sewardj170ee212004-12-10 18:57:51 +00002922 IROp mkAdd;
2923 IRType ty, tyAddr;
2924 IRDirty *di, *diLo64, *diHi64;
2925 IRAtom *addrAct, *addrLo64, *addrHi64;
2926 IRAtom *vdataLo64, *vdataHi64;
sewardj2e595852005-06-30 23:33:37 +00002927 IRAtom *eBias, *eBiasLo64, *eBiasHi64;
sewardj95448072004-11-22 20:19:51 +00002928 void* helper = NULL;
2929 Char* hname = NULL;
njn1d0825f2006-03-27 11:37:07 +00002930 IRConst* c;
sewardj170ee212004-12-10 18:57:51 +00002931
2932 tyAddr = mce->hWordTy;
2933 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2934 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj2e595852005-06-30 23:33:37 +00002935 tl_assert( end == Iend_LE || end == Iend_BE );
sewardj170ee212004-12-10 18:57:51 +00002936
2937 di = diLo64 = diHi64 = NULL;
sewardj2e595852005-06-30 23:33:37 +00002938 eBias = eBiasLo64 = eBiasHi64 = NULL;
sewardj170ee212004-12-10 18:57:51 +00002939 addrAct = addrLo64 = addrHi64 = NULL;
2940 vdataLo64 = vdataHi64 = NULL;
njn25e49d8e72002-09-23 09:36:25 +00002941
sewardj95448072004-11-22 20:19:51 +00002942 if (data) {
2943 tl_assert(!vdata);
2944 tl_assert(isOriginalAtom(mce, data));
2945 tl_assert(bias == 0);
2946 vdata = expr2vbits( mce, data );
2947 } else {
2948 tl_assert(vdata);
2949 }
njn25e49d8e72002-09-23 09:36:25 +00002950
sewardj95448072004-11-22 20:19:51 +00002951 tl_assert(isOriginalAtom(mce,addr));
2952 tl_assert(isShadowAtom(mce,vdata));
njn25e49d8e72002-09-23 09:36:25 +00002953
sewardj95448072004-11-22 20:19:51 +00002954 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
njn25e49d8e72002-09-23 09:36:25 +00002955
njn1d0825f2006-03-27 11:37:07 +00002956 // If we're not doing undefined value checking, pretend that this value
2957 // is "all valid". That lets Vex's optimiser remove some of the V bit
2958 // shadow computation ops that precede it.
sewardj7cf4e6b2008-05-01 20:24:26 +00002959 if (MC_(clo_mc_level) == 1) {
njn1d0825f2006-03-27 11:37:07 +00002960 switch (ty) {
2961 case Ity_V128: c = IRConst_V128(V_BITS16_DEFINED); break; // V128 weirdness
2962 case Ity_I64: c = IRConst_U64 (V_BITS64_DEFINED); break;
2963 case Ity_I32: c = IRConst_U32 (V_BITS32_DEFINED); break;
2964 case Ity_I16: c = IRConst_U16 (V_BITS16_DEFINED); break;
2965 case Ity_I8: c = IRConst_U8 (V_BITS8_DEFINED); break;
2966 default: VG_(tool_panic)("memcheck:do_shadow_Store(LE)");
2967 }
2968 vdata = IRExpr_Const( c );
2969 }
2970
sewardj95448072004-11-22 20:19:51 +00002971 /* First, emit a definedness test for the address. This also sets
2972 the address (shadow) to 'defined' following the test. */
2973 complainIfUndefined( mce, addr );
njn25e49d8e72002-09-23 09:36:25 +00002974
sewardj170ee212004-12-10 18:57:51 +00002975 /* Now decide which helper function to call to write the data V
2976 bits into shadow memory. */
sewardj2e595852005-06-30 23:33:37 +00002977 if (end == Iend_LE) {
2978 switch (ty) {
2979 case Ity_V128: /* we'll use the helper twice */
njn1d0825f2006-03-27 11:37:07 +00002980 case Ity_I64: helper = &MC_(helperc_STOREV64le);
2981 hname = "MC_(helperc_STOREV64le)";
sewardj2e595852005-06-30 23:33:37 +00002982 break;
njn1d0825f2006-03-27 11:37:07 +00002983 case Ity_I32: helper = &MC_(helperc_STOREV32le);
2984 hname = "MC_(helperc_STOREV32le)";
sewardj2e595852005-06-30 23:33:37 +00002985 break;
njn1d0825f2006-03-27 11:37:07 +00002986 case Ity_I16: helper = &MC_(helperc_STOREV16le);
2987 hname = "MC_(helperc_STOREV16le)";
sewardj2e595852005-06-30 23:33:37 +00002988 break;
njn1d0825f2006-03-27 11:37:07 +00002989 case Ity_I8: helper = &MC_(helperc_STOREV8);
2990 hname = "MC_(helperc_STOREV8)";
sewardj2e595852005-06-30 23:33:37 +00002991 break;
2992 default: VG_(tool_panic)("memcheck:do_shadow_Store(LE)");
2993 }
2994 } else {
sewardj8cf88b72005-07-08 01:29:33 +00002995 switch (ty) {
2996 case Ity_V128: /* we'll use the helper twice */
njn1d0825f2006-03-27 11:37:07 +00002997 case Ity_I64: helper = &MC_(helperc_STOREV64be);
2998 hname = "MC_(helperc_STOREV64be)";
sewardj8cf88b72005-07-08 01:29:33 +00002999 break;
njn1d0825f2006-03-27 11:37:07 +00003000 case Ity_I32: helper = &MC_(helperc_STOREV32be);
3001 hname = "MC_(helperc_STOREV32be)";
sewardj8cf88b72005-07-08 01:29:33 +00003002 break;
njn1d0825f2006-03-27 11:37:07 +00003003 case Ity_I16: helper = &MC_(helperc_STOREV16be);
3004 hname = "MC_(helperc_STOREV16be)";
sewardj8cf88b72005-07-08 01:29:33 +00003005 break;
njn1d0825f2006-03-27 11:37:07 +00003006 case Ity_I8: helper = &MC_(helperc_STOREV8);
3007 hname = "MC_(helperc_STOREV8)";
sewardj8cf88b72005-07-08 01:29:33 +00003008 break;
3009 default: VG_(tool_panic)("memcheck:do_shadow_Store(BE)");
3010 }
sewardj95448072004-11-22 20:19:51 +00003011 }
njn25e49d8e72002-09-23 09:36:25 +00003012
sewardj170ee212004-12-10 18:57:51 +00003013 if (ty == Ity_V128) {
3014
sewardj20d38f22005-02-07 23:50:18 +00003015 /* V128-bit case */
sewardj170ee212004-12-10 18:57:51 +00003016 /* See comment in next clause re 64-bit regparms */
sewardj2e595852005-06-30 23:33:37 +00003017 /* also, need to be careful about endianness */
3018
3019 Int offLo64, offHi64;
3020 if (end == Iend_LE) {
3021 offLo64 = 0;
3022 offHi64 = 8;
3023 } else {
sewardj2e595852005-06-30 23:33:37 +00003024 offLo64 = 8;
3025 offHi64 = 0;
3026 }
3027
3028 eBiasLo64 = tyAddr==Ity_I32 ? mkU32(bias+offLo64) : mkU64(bias+offLo64);
sewardj7cf4e6b2008-05-01 20:24:26 +00003029 addrLo64 = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBiasLo64) );
3030 vdataLo64 = assignNew('V', mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj170ee212004-12-10 18:57:51 +00003031 diLo64 = unsafeIRDirty_0_N(
sewardj53ee1fc2005-12-23 02:29:58 +00003032 1/*regparms*/,
3033 hname, VG_(fnptr_to_fnentry)( helper ),
3034 mkIRExprVec_2( addrLo64, vdataLo64 )
3035 );
sewardj2e595852005-06-30 23:33:37 +00003036 eBiasHi64 = tyAddr==Ity_I32 ? mkU32(bias+offHi64) : mkU64(bias+offHi64);
sewardj7cf4e6b2008-05-01 20:24:26 +00003037 addrHi64 = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBiasHi64) );
3038 vdataHi64 = assignNew('V', mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj170ee212004-12-10 18:57:51 +00003039 diHi64 = unsafeIRDirty_0_N(
sewardj53ee1fc2005-12-23 02:29:58 +00003040 1/*regparms*/,
3041 hname, VG_(fnptr_to_fnentry)( helper ),
3042 mkIRExprVec_2( addrHi64, vdataHi64 )
3043 );
sewardj170ee212004-12-10 18:57:51 +00003044 setHelperAnns( mce, diLo64 );
3045 setHelperAnns( mce, diHi64 );
sewardj7cf4e6b2008-05-01 20:24:26 +00003046 stmt( 'V', mce, IRStmt_Dirty(diLo64) );
3047 stmt( 'V', mce, IRStmt_Dirty(diHi64) );
sewardj170ee212004-12-10 18:57:51 +00003048
sewardj95448072004-11-22 20:19:51 +00003049 } else {
sewardj170ee212004-12-10 18:57:51 +00003050
3051 /* 8/16/32/64-bit cases */
3052 /* Generate the actual address into addrAct. */
3053 if (bias == 0) {
3054 addrAct = addr;
3055 } else {
3056 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj7cf4e6b2008-05-01 20:24:26 +00003057 addrAct = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBias));
sewardj170ee212004-12-10 18:57:51 +00003058 }
3059
3060 if (ty == Ity_I64) {
3061 /* We can't do this with regparm 2 on 32-bit platforms, since
3062 the back ends aren't clever enough to handle 64-bit
3063 regparm args. Therefore be different. */
3064 di = unsafeIRDirty_0_N(
sewardj53ee1fc2005-12-23 02:29:58 +00003065 1/*regparms*/,
3066 hname, VG_(fnptr_to_fnentry)( helper ),
3067 mkIRExprVec_2( addrAct, vdata )
3068 );
sewardj170ee212004-12-10 18:57:51 +00003069 } else {
3070 di = unsafeIRDirty_0_N(
sewardj53ee1fc2005-12-23 02:29:58 +00003071 2/*regparms*/,
3072 hname, VG_(fnptr_to_fnentry)( helper ),
sewardj170ee212004-12-10 18:57:51 +00003073 mkIRExprVec_2( addrAct,
sewardj53ee1fc2005-12-23 02:29:58 +00003074 zwidenToHostWord( mce, vdata ))
3075 );
sewardj170ee212004-12-10 18:57:51 +00003076 }
3077 setHelperAnns( mce, di );
sewardj7cf4e6b2008-05-01 20:24:26 +00003078 stmt( 'V', mce, IRStmt_Dirty(di) );
sewardj95448072004-11-22 20:19:51 +00003079 }
njn25e49d8e72002-09-23 09:36:25 +00003080
sewardj95448072004-11-22 20:19:51 +00003081}
njn25e49d8e72002-09-23 09:36:25 +00003082
njn25e49d8e72002-09-23 09:36:25 +00003083
sewardj95448072004-11-22 20:19:51 +00003084/* Do lazy pessimistic propagation through a dirty helper call, by
3085 looking at the annotations on it. This is the most complex part of
3086 Memcheck. */
njn25e49d8e72002-09-23 09:36:25 +00003087
sewardj95448072004-11-22 20:19:51 +00003088static IRType szToITy ( Int n )
3089{
3090 switch (n) {
3091 case 1: return Ity_I8;
3092 case 2: return Ity_I16;
3093 case 4: return Ity_I32;
3094 case 8: return Ity_I64;
3095 default: VG_(tool_panic)("szToITy(memcheck)");
3096 }
3097}
njn25e49d8e72002-09-23 09:36:25 +00003098
sewardj95448072004-11-22 20:19:51 +00003099static
3100void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
3101{
sewardj2e595852005-06-30 23:33:37 +00003102 Int i, n, offset, toDo, gSz, gOff;
3103 IRAtom *src, *here, *curr;
3104 IRType tyAddr, tySrc, tyDst;
3105 IRTemp dst;
3106 IREndness end;
3107
3108 /* What's the native endianness? We need to know this. */
sewardj6e340c72005-07-10 00:53:42 +00003109# if defined(VG_BIGENDIAN)
sewardj2e595852005-06-30 23:33:37 +00003110 end = Iend_BE;
sewardj6e340c72005-07-10 00:53:42 +00003111# elif defined(VG_LITTLEENDIAN)
sewardj2e595852005-06-30 23:33:37 +00003112 end = Iend_LE;
3113# else
3114# error "Unknown endianness"
3115# endif
njn25e49d8e72002-09-23 09:36:25 +00003116
sewardj95448072004-11-22 20:19:51 +00003117 /* First check the guard. */
3118 complainIfUndefined(mce, d->guard);
3119
3120 /* Now round up all inputs and PCast over them. */
sewardj7cf97ee2004-11-28 14:25:01 +00003121 curr = definedOfType(Ity_I32);
sewardj95448072004-11-22 20:19:51 +00003122
3123 /* Inputs: unmasked args */
3124 for (i = 0; d->args[i]; i++) {
3125 if (d->cee->mcx_mask & (1<<i)) {
3126 /* ignore this arg */
njn25e49d8e72002-09-23 09:36:25 +00003127 } else {
sewardj95448072004-11-22 20:19:51 +00003128 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
3129 curr = mkUifU32(mce, here, curr);
njn25e49d8e72002-09-23 09:36:25 +00003130 }
3131 }
sewardj95448072004-11-22 20:19:51 +00003132
3133 /* Inputs: guest state that we read. */
3134 for (i = 0; i < d->nFxState; i++) {
3135 tl_assert(d->fxState[i].fx != Ifx_None);
3136 if (d->fxState[i].fx == Ifx_Write)
3137 continue;
sewardja7203252004-11-26 19:17:47 +00003138
3139 /* Ignore any sections marked as 'always defined'. */
3140 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
sewardje9e16d32004-12-10 13:17:55 +00003141 if (0)
sewardja7203252004-11-26 19:17:47 +00003142 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
3143 d->fxState[i].offset, d->fxState[i].size );
3144 continue;
3145 }
3146
sewardj95448072004-11-22 20:19:51 +00003147 /* This state element is read or modified. So we need to
sewardje9e16d32004-12-10 13:17:55 +00003148 consider it. If larger than 8 bytes, deal with it in 8-byte
3149 chunks. */
3150 gSz = d->fxState[i].size;
3151 gOff = d->fxState[i].offset;
3152 tl_assert(gSz > 0);
3153 while (True) {
3154 if (gSz == 0) break;
3155 n = gSz <= 8 ? gSz : 8;
3156 /* update 'curr' with UifU of the state slice
3157 gOff .. gOff+n-1 */
3158 tySrc = szToITy( n );
sewardj7cf4e6b2008-05-01 20:24:26 +00003159 src = assignNew( 'V', mce, tySrc,
3160 shadow_GET(mce, gOff, tySrc ) );
sewardje9e16d32004-12-10 13:17:55 +00003161 here = mkPCastTo( mce, Ity_I32, src );
3162 curr = mkUifU32(mce, here, curr);
3163 gSz -= n;
3164 gOff += n;
3165 }
3166
sewardj95448072004-11-22 20:19:51 +00003167 }
3168
3169 /* Inputs: memory. First set up some info needed regardless of
3170 whether we're doing reads or writes. */
3171 tyAddr = Ity_INVALID;
3172
3173 if (d->mFx != Ifx_None) {
3174 /* Because we may do multiple shadow loads/stores from the same
3175 base address, it's best to do a single test of its
3176 definedness right now. Post-instrumentation optimisation
3177 should remove all but this test. */
3178 tl_assert(d->mAddr);
3179 complainIfUndefined(mce, d->mAddr);
3180
3181 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
3182 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
3183 tl_assert(tyAddr == mce->hWordTy); /* not really right */
3184 }
3185
3186 /* Deal with memory inputs (reads or modifies) */
3187 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
3188 offset = 0;
3189 toDo = d->mSize;
sewardj2e595852005-06-30 23:33:37 +00003190 /* chew off 32-bit chunks. We don't care about the endianness
3191 since it's all going to be condensed down to a single bit,
3192 but nevertheless choose an endianness which is hopefully
3193 native to the platform. */
sewardj95448072004-11-22 20:19:51 +00003194 while (toDo >= 4) {
3195 here = mkPCastTo(
3196 mce, Ity_I32,
sewardj2e595852005-06-30 23:33:37 +00003197 expr2vbits_Load ( mce, end, Ity_I32,
sewardj95448072004-11-22 20:19:51 +00003198 d->mAddr, d->mSize - toDo )
3199 );
3200 curr = mkUifU32(mce, here, curr);
3201 toDo -= 4;
3202 }
3203 /* chew off 16-bit chunks */
3204 while (toDo >= 2) {
3205 here = mkPCastTo(
3206 mce, Ity_I32,
sewardj2e595852005-06-30 23:33:37 +00003207 expr2vbits_Load ( mce, end, Ity_I16,
sewardj95448072004-11-22 20:19:51 +00003208 d->mAddr, d->mSize - toDo )
3209 );
3210 curr = mkUifU32(mce, here, curr);
3211 toDo -= 2;
3212 }
3213 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
3214 }
3215
3216 /* Whew! So curr is a 32-bit V-value summarising pessimistically
3217 all the inputs to the helper. Now we need to re-distribute the
3218 results to all destinations. */
3219
3220 /* Outputs: the destination temporary, if there is one. */
3221 if (d->tmp != IRTemp_INVALID) {
sewardj7cf4e6b2008-05-01 20:24:26 +00003222 dst = findShadowTmpV(mce, d->tmp);
sewardj95448072004-11-22 20:19:51 +00003223 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
sewardj7cf4e6b2008-05-01 20:24:26 +00003224 assign( 'V', mce, dst, mkPCastTo( mce, tyDst, curr) );
sewardj95448072004-11-22 20:19:51 +00003225 }
3226
3227 /* Outputs: guest state that we write or modify. */
3228 for (i = 0; i < d->nFxState; i++) {
3229 tl_assert(d->fxState[i].fx != Ifx_None);
3230 if (d->fxState[i].fx == Ifx_Read)
3231 continue;
sewardja7203252004-11-26 19:17:47 +00003232 /* Ignore any sections marked as 'always defined'. */
3233 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
3234 continue;
sewardje9e16d32004-12-10 13:17:55 +00003235 /* This state element is written or modified. So we need to
3236 consider it. If larger than 8 bytes, deal with it in 8-byte
3237 chunks. */
3238 gSz = d->fxState[i].size;
3239 gOff = d->fxState[i].offset;
3240 tl_assert(gSz > 0);
3241 while (True) {
3242 if (gSz == 0) break;
3243 n = gSz <= 8 ? gSz : 8;
3244 /* Write suitably-casted 'curr' to the state slice
3245 gOff .. gOff+n-1 */
3246 tyDst = szToITy( n );
3247 do_shadow_PUT( mce, gOff,
3248 NULL, /* original atom */
3249 mkPCastTo( mce, tyDst, curr ) );
3250 gSz -= n;
3251 gOff += n;
3252 }
sewardj95448072004-11-22 20:19:51 +00003253 }
3254
sewardj2e595852005-06-30 23:33:37 +00003255 /* Outputs: memory that we write or modify. Same comments about
3256 endianness as above apply. */
sewardj95448072004-11-22 20:19:51 +00003257 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
3258 offset = 0;
3259 toDo = d->mSize;
3260 /* chew off 32-bit chunks */
3261 while (toDo >= 4) {
sewardj2e595852005-06-30 23:33:37 +00003262 do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
3263 NULL, /* original data */
3264 mkPCastTo( mce, Ity_I32, curr ) );
sewardj95448072004-11-22 20:19:51 +00003265 toDo -= 4;
3266 }
3267 /* chew off 16-bit chunks */
3268 while (toDo >= 2) {
sewardj2e595852005-06-30 23:33:37 +00003269 do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
3270 NULL, /* original data */
3271 mkPCastTo( mce, Ity_I16, curr ) );
sewardj95448072004-11-22 20:19:51 +00003272 toDo -= 2;
3273 }
3274 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
3275 }
3276
njn25e49d8e72002-09-23 09:36:25 +00003277}
3278
sewardj826ec492005-05-12 18:05:00 +00003279/* We have an ABI hint telling us that [base .. base+len-1] is to
3280 become undefined ("writable"). Generate code to call a helper to
3281 notify the A/V bit machinery of this fact.
3282
3283 We call
sewardj7cf4e6b2008-05-01 20:24:26 +00003284 void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len,
3285 Addr nia );
sewardj826ec492005-05-12 18:05:00 +00003286*/
3287static
sewardj7cf4e6b2008-05-01 20:24:26 +00003288void do_AbiHint ( MCEnv* mce, IRExpr* base, Int len, IRExpr* nia )
sewardj826ec492005-05-12 18:05:00 +00003289{
3290 IRDirty* di;
sewardj7cf4e6b2008-05-01 20:24:26 +00003291 /* Minor optimisation: if not doing origin tracking, ignore the
3292 supplied nia and pass zero instead. This is on the basis that
3293 MC_(helperc_MAKE_STACK_UNINIT) will ignore it anyway, and we can
3294 almost always generate a shorter instruction to put zero into a
3295 register than any other value. */
3296 if (MC_(clo_mc_level) < 3)
3297 nia = mkIRExpr_HWord(0);
3298
sewardj826ec492005-05-12 18:05:00 +00003299 di = unsafeIRDirty_0_N(
3300 0/*regparms*/,
3301 "MC_(helperc_MAKE_STACK_UNINIT)",
sewardj53ee1fc2005-12-23 02:29:58 +00003302 VG_(fnptr_to_fnentry)( &MC_(helperc_MAKE_STACK_UNINIT) ),
sewardj7cf4e6b2008-05-01 20:24:26 +00003303 mkIRExprVec_3( base, mkIRExpr_HWord( (UInt)len), nia )
sewardj826ec492005-05-12 18:05:00 +00003304 );
sewardj7cf4e6b2008-05-01 20:24:26 +00003305 stmt( 'V', mce, IRStmt_Dirty(di) );
sewardj826ec492005-05-12 18:05:00 +00003306}
3307
njn25e49d8e72002-09-23 09:36:25 +00003308
sewardj95448072004-11-22 20:19:51 +00003309/*------------------------------------------------------------*/
3310/*--- Memcheck main ---*/
3311/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00003312
sewardj7cf4e6b2008-05-01 20:24:26 +00003313static void schemeS ( MCEnv* mce, IRStmt* st );
3314
sewardj95448072004-11-22 20:19:51 +00003315static Bool isBogusAtom ( IRAtom* at )
njn25e49d8e72002-09-23 09:36:25 +00003316{
sewardj95448072004-11-22 20:19:51 +00003317 ULong n = 0;
3318 IRConst* con;
sewardj710d6c22005-03-20 18:55:15 +00003319 tl_assert(isIRAtom(at));
sewardj0b9d74a2006-12-24 02:24:11 +00003320 if (at->tag == Iex_RdTmp)
sewardj95448072004-11-22 20:19:51 +00003321 return False;
3322 tl_assert(at->tag == Iex_Const);
3323 con = at->Iex.Const.con;
3324 switch (con->tag) {
sewardjd5204dc2004-12-31 01:16:11 +00003325 case Ico_U1: return False;
3326 case Ico_U8: n = (ULong)con->Ico.U8; break;
3327 case Ico_U16: n = (ULong)con->Ico.U16; break;
3328 case Ico_U32: n = (ULong)con->Ico.U32; break;
3329 case Ico_U64: n = (ULong)con->Ico.U64; break;
3330 case Ico_F64: return False;
3331 case Ico_F64i: return False;
3332 case Ico_V128: return False;
sewardj95448072004-11-22 20:19:51 +00003333 default: ppIRExpr(at); tl_assert(0);
3334 }
3335 /* VG_(printf)("%llx\n", n); */
sewardj96a922e2005-04-23 23:26:29 +00003336 return (/*32*/ n == 0xFEFEFEFFULL
3337 /*32*/ || n == 0x80808080ULL
sewardj17b47432008-12-17 01:12:58 +00003338 /*32*/ || n == 0x7F7F7F7FULL
tomd9774d72005-06-27 08:11:01 +00003339 /*64*/ || n == 0xFFFFFFFFFEFEFEFFULL
sewardj96a922e2005-04-23 23:26:29 +00003340 /*64*/ || n == 0xFEFEFEFEFEFEFEFFULL
tomd9774d72005-06-27 08:11:01 +00003341 /*64*/ || n == 0x0000000000008080ULL
sewardj96a922e2005-04-23 23:26:29 +00003342 /*64*/ || n == 0x8080808080808080ULL
sewardj17b47432008-12-17 01:12:58 +00003343 /*64*/ || n == 0x0101010101010101ULL
sewardj96a922e2005-04-23 23:26:29 +00003344 );
sewardj95448072004-11-22 20:19:51 +00003345}
njn25e49d8e72002-09-23 09:36:25 +00003346
sewardj95448072004-11-22 20:19:51 +00003347static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
3348{
sewardjd5204dc2004-12-31 01:16:11 +00003349 Int i;
3350 IRExpr* e;
3351 IRDirty* d;
sewardj95448072004-11-22 20:19:51 +00003352 switch (st->tag) {
sewardj0b9d74a2006-12-24 02:24:11 +00003353 case Ist_WrTmp:
3354 e = st->Ist.WrTmp.data;
sewardj95448072004-11-22 20:19:51 +00003355 switch (e->tag) {
3356 case Iex_Get:
sewardj0b9d74a2006-12-24 02:24:11 +00003357 case Iex_RdTmp:
sewardj95448072004-11-22 20:19:51 +00003358 return False;
sewardjd5204dc2004-12-31 01:16:11 +00003359 case Iex_Const:
3360 return isBogusAtom(e);
sewardj95448072004-11-22 20:19:51 +00003361 case Iex_Unop:
3362 return isBogusAtom(e->Iex.Unop.arg);
sewardjd5204dc2004-12-31 01:16:11 +00003363 case Iex_GetI:
3364 return isBogusAtom(e->Iex.GetI.ix);
sewardj95448072004-11-22 20:19:51 +00003365 case Iex_Binop:
3366 return isBogusAtom(e->Iex.Binop.arg1)
3367 || isBogusAtom(e->Iex.Binop.arg2);
sewardjed69fdb2006-02-03 16:12:27 +00003368 case Iex_Triop:
3369 return isBogusAtom(e->Iex.Triop.arg1)
3370 || isBogusAtom(e->Iex.Triop.arg2)
3371 || isBogusAtom(e->Iex.Triop.arg3);
sewardje91cea72006-02-08 19:32:02 +00003372 case Iex_Qop:
3373 return isBogusAtom(e->Iex.Qop.arg1)
3374 || isBogusAtom(e->Iex.Qop.arg2)
3375 || isBogusAtom(e->Iex.Qop.arg3)
3376 || isBogusAtom(e->Iex.Qop.arg4);
sewardj95448072004-11-22 20:19:51 +00003377 case Iex_Mux0X:
3378 return isBogusAtom(e->Iex.Mux0X.cond)
3379 || isBogusAtom(e->Iex.Mux0X.expr0)
3380 || isBogusAtom(e->Iex.Mux0X.exprX);
sewardj2e595852005-06-30 23:33:37 +00003381 case Iex_Load:
3382 return isBogusAtom(e->Iex.Load.addr);
sewardj95448072004-11-22 20:19:51 +00003383 case Iex_CCall:
3384 for (i = 0; e->Iex.CCall.args[i]; i++)
3385 if (isBogusAtom(e->Iex.CCall.args[i]))
3386 return True;
3387 return False;
3388 default:
3389 goto unhandled;
3390 }
sewardjd5204dc2004-12-31 01:16:11 +00003391 case Ist_Dirty:
3392 d = st->Ist.Dirty.details;
3393 for (i = 0; d->args[i]; i++)
3394 if (isBogusAtom(d->args[i]))
3395 return True;
3396 if (d->guard && isBogusAtom(d->guard))
3397 return True;
3398 if (d->mAddr && isBogusAtom(d->mAddr))
3399 return True;
3400 return False;
sewardj95448072004-11-22 20:19:51 +00003401 case Ist_Put:
3402 return isBogusAtom(st->Ist.Put.data);
sewardjd5204dc2004-12-31 01:16:11 +00003403 case Ist_PutI:
3404 return isBogusAtom(st->Ist.PutI.ix)
3405 || isBogusAtom(st->Ist.PutI.data);
sewardj2e595852005-06-30 23:33:37 +00003406 case Ist_Store:
3407 return isBogusAtom(st->Ist.Store.addr)
3408 || isBogusAtom(st->Ist.Store.data);
sewardj95448072004-11-22 20:19:51 +00003409 case Ist_Exit:
sewardjd5204dc2004-12-31 01:16:11 +00003410 return isBogusAtom(st->Ist.Exit.guard);
sewardj826ec492005-05-12 18:05:00 +00003411 case Ist_AbiHint:
sewardj7cf4e6b2008-05-01 20:24:26 +00003412 return isBogusAtom(st->Ist.AbiHint.base)
3413 || isBogusAtom(st->Ist.AbiHint.nia);
sewardj21dc3452005-03-21 00:27:41 +00003414 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00003415 case Ist_IMark:
sewardj72d75132007-11-09 23:06:35 +00003416 case Ist_MBE:
sewardjbd598e12005-01-07 12:10:21 +00003417 return False;
sewardj95448072004-11-22 20:19:51 +00003418 default:
3419 unhandled:
3420 ppIRStmt(st);
3421 VG_(tool_panic)("hasBogusLiterals");
3422 }
3423}
njn25e49d8e72002-09-23 09:36:25 +00003424
njn25e49d8e72002-09-23 09:36:25 +00003425
sewardj0b9d74a2006-12-24 02:24:11 +00003426IRSB* MC_(instrument) ( VgCallbackClosure* closure,
3427 IRSB* bb_in,
sewardj461df9c2006-01-17 02:06:39 +00003428 VexGuestLayout* layout,
3429 VexGuestExtents* vge,
sewardjd54babf2005-03-21 00:55:49 +00003430 IRType gWordTy, IRType hWordTy )
sewardj95448072004-11-22 20:19:51 +00003431{
sewardj7cf4e6b2008-05-01 20:24:26 +00003432 Bool verboze = 0||False;
sewardj151b90d2005-07-06 19:42:23 +00003433 Bool bogus;
sewardjd5204dc2004-12-31 01:16:11 +00003434 Int i, j, first_stmt;
sewardj95448072004-11-22 20:19:51 +00003435 IRStmt* st;
sewardjd5204dc2004-12-31 01:16:11 +00003436 MCEnv mce;
sewardj0b9d74a2006-12-24 02:24:11 +00003437 IRSB* bb;
sewardjd54babf2005-03-21 00:55:49 +00003438
3439 if (gWordTy != hWordTy) {
3440 /* We don't currently support this case. */
3441 VG_(tool_panic)("host/guest word size mismatch");
3442 }
njn25e49d8e72002-09-23 09:36:25 +00003443
sewardj6cf40ff2005-04-20 22:31:26 +00003444 /* Check we're not completely nuts */
sewardj7cf4e6b2008-05-01 20:24:26 +00003445 tl_assert(sizeof(UWord) == sizeof(void*));
3446 tl_assert(sizeof(Word) == sizeof(void*));
3447 tl_assert(sizeof(Addr) == sizeof(void*));
3448 tl_assert(sizeof(ULong) == 8);
3449 tl_assert(sizeof(Long) == 8);
3450 tl_assert(sizeof(Addr64) == 8);
3451 tl_assert(sizeof(UInt) == 4);
3452 tl_assert(sizeof(Int) == 4);
3453
3454 tl_assert(MC_(clo_mc_level) >= 1 && MC_(clo_mc_level) <= 3);
sewardj6cf40ff2005-04-20 22:31:26 +00003455
sewardj0b9d74a2006-12-24 02:24:11 +00003456 /* Set up SB */
3457 bb = deepCopyIRSBExceptStmts(bb_in);
njn25e49d8e72002-09-23 09:36:25 +00003458
sewardj95448072004-11-22 20:19:51 +00003459 /* Set up the running environment. Only .bb is modified as we go
3460 along. */
3461 mce.bb = bb;
sewardj7cf4e6b2008-05-01 20:24:26 +00003462 mce.trace = verboze;
sewardj95448072004-11-22 20:19:51 +00003463 mce.layout = layout;
3464 mce.n_originalTmps = bb->tyenv->types_used;
3465 mce.hWordTy = hWordTy;
sewardjd5204dc2004-12-31 01:16:11 +00003466 mce.bogusLiterals = False;
sewardj7cf4e6b2008-05-01 20:24:26 +00003467 mce.tmpMapV = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
3468 mce.tmpMapB = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
3469 for (i = 0; i < mce.n_originalTmps; i++) {
3470 mce.tmpMapV[i] = IRTemp_INVALID;
3471 mce.tmpMapB[i] = IRTemp_INVALID;
3472 }
sewardj95448072004-11-22 20:19:51 +00003473
sewardj151b90d2005-07-06 19:42:23 +00003474 /* Make a preliminary inspection of the statements, to see if there
3475 are any dodgy-looking literals. If there are, we generate
3476 extra-detailed (hence extra-expensive) instrumentation in
3477 places. Scan the whole bb even if dodgyness is found earlier,
3478 so that the flatness assertion is applied to all stmts. */
3479
3480 bogus = False;
sewardj95448072004-11-22 20:19:51 +00003481
sewardjf1962d32006-10-19 13:22:16 +00003482 for (i = 0; i < bb_in->stmts_used; i++) {
sewardj151b90d2005-07-06 19:42:23 +00003483
sewardj95448072004-11-22 20:19:51 +00003484 st = bb_in->stmts[i];
sewardj21dc3452005-03-21 00:27:41 +00003485 tl_assert(st);
sewardj95448072004-11-22 20:19:51 +00003486 tl_assert(isFlatIRStmt(st));
3487
sewardj151b90d2005-07-06 19:42:23 +00003488 if (!bogus) {
3489 bogus = checkForBogusLiterals(st);
3490 if (0 && bogus) {
sewardj95448072004-11-22 20:19:51 +00003491 VG_(printf)("bogus: ");
3492 ppIRStmt(st);
3493 VG_(printf)("\n");
3494 }
3495 }
sewardjd5204dc2004-12-31 01:16:11 +00003496
sewardj151b90d2005-07-06 19:42:23 +00003497 }
3498
3499 mce.bogusLiterals = bogus;
3500
sewardja0871482006-10-18 12:41:55 +00003501 /* Copy verbatim any IR preamble preceding the first IMark */
sewardj151b90d2005-07-06 19:42:23 +00003502
sewardjf1962d32006-10-19 13:22:16 +00003503 tl_assert(mce.bb == bb);
3504
sewardja0871482006-10-18 12:41:55 +00003505 i = 0;
3506 while (i < bb_in->stmts_used && bb_in->stmts[i]->tag != Ist_IMark) {
3507
3508 st = bb_in->stmts[i];
3509 tl_assert(st);
3510 tl_assert(isFlatIRStmt(st));
3511
sewardj7cf4e6b2008-05-01 20:24:26 +00003512 stmt( 'C', &mce, bb_in->stmts[i] );
sewardja0871482006-10-18 12:41:55 +00003513 i++;
3514 }
3515
sewardjf1962d32006-10-19 13:22:16 +00003516 /* Nasty problem. IR optimisation of the pre-instrumented IR may
3517 cause the IR following the preamble to contain references to IR
3518 temporaries defined in the preamble. Because the preamble isn't
3519 instrumented, these temporaries don't have any shadows.
3520 Nevertheless uses of them following the preamble will cause
3521 memcheck to generate references to their shadows. End effect is
3522 to cause IR sanity check failures, due to references to
3523 non-existent shadows. This is only evident for the complex
3524 preambles used for function wrapping on TOC-afflicted platforms
3525 (ppc64-linux, ppc32-aix5, ppc64-aix5).
3526
3527 The following loop therefore scans the preamble looking for
3528 assignments to temporaries. For each one found it creates an
sewardjafa617b2008-07-22 09:59:48 +00003529 assignment to the corresponding (V) shadow temp, marking it as
sewardjf1962d32006-10-19 13:22:16 +00003530 'defined'. This is the same resulting IR as if the main
3531 instrumentation loop before had been applied to the statement
3532 'tmp = CONSTANT'.
sewardjafa617b2008-07-22 09:59:48 +00003533
3534 Similarly, if origin tracking is enabled, we must generate an
3535 assignment for the corresponding origin (B) shadow, claiming
3536 no-origin, as appropriate for a defined value.
sewardjf1962d32006-10-19 13:22:16 +00003537 */
3538 for (j = 0; j < i; j++) {
sewardj0b9d74a2006-12-24 02:24:11 +00003539 if (bb_in->stmts[j]->tag == Ist_WrTmp) {
sewardj7cf4e6b2008-05-01 20:24:26 +00003540 /* findShadowTmpV checks its arg is an original tmp;
sewardjf1962d32006-10-19 13:22:16 +00003541 no need to assert that here. */
sewardj0b9d74a2006-12-24 02:24:11 +00003542 IRTemp tmp_o = bb_in->stmts[j]->Ist.WrTmp.tmp;
sewardjafa617b2008-07-22 09:59:48 +00003543 IRTemp tmp_v = findShadowTmpV(&mce, tmp_o);
3544 IRType ty_v = typeOfIRTemp(bb->tyenv, tmp_v);
3545 assign( 'V', &mce, tmp_v, definedOfType( ty_v ) );
3546 if (MC_(clo_mc_level) == 3) {
3547 IRTemp tmp_b = findShadowTmpB(&mce, tmp_o);
3548 tl_assert(typeOfIRTemp(bb->tyenv, tmp_b) == Ity_I32);
3549 assign( 'B', &mce, tmp_b, mkU32(0)/* UNKNOWN ORIGIN */);
3550 }
sewardjf1962d32006-10-19 13:22:16 +00003551 if (0) {
sewardjafa617b2008-07-22 09:59:48 +00003552 VG_(printf)("create shadow tmp(s) for preamble tmp [%d] ty ", j);
3553 ppIRType( ty_v );
sewardjf1962d32006-10-19 13:22:16 +00003554 VG_(printf)("\n");
3555 }
3556 }
3557 }
3558
sewardja0871482006-10-18 12:41:55 +00003559 /* Iterate over the remaining stmts to generate instrumentation. */
3560
3561 tl_assert(bb_in->stmts_used > 0);
3562 tl_assert(i >= 0);
3563 tl_assert(i < bb_in->stmts_used);
3564 tl_assert(bb_in->stmts[i]->tag == Ist_IMark);
3565
3566 for (/* use current i*/; i < bb_in->stmts_used; i++) {
sewardj151b90d2005-07-06 19:42:23 +00003567
3568 st = bb_in->stmts[i];
sewardj95448072004-11-22 20:19:51 +00003569 first_stmt = bb->stmts_used;
3570
3571 if (verboze) {
sewardj7cf4e6b2008-05-01 20:24:26 +00003572 VG_(printf)("\n");
sewardj95448072004-11-22 20:19:51 +00003573 ppIRStmt(st);
sewardj7cf4e6b2008-05-01 20:24:26 +00003574 VG_(printf)("\n");
sewardj95448072004-11-22 20:19:51 +00003575 }
3576
sewardj7cf4e6b2008-05-01 20:24:26 +00003577 if (MC_(clo_mc_level) == 3)
3578 schemeS( &mce, st );
3579
sewardj29faa502005-03-16 18:20:21 +00003580 /* Generate instrumentation code for each stmt ... */
3581
sewardj95448072004-11-22 20:19:51 +00003582 switch (st->tag) {
3583
sewardj0b9d74a2006-12-24 02:24:11 +00003584 case Ist_WrTmp:
sewardj7cf4e6b2008-05-01 20:24:26 +00003585 assign( 'V', &mce, findShadowTmpV(&mce, st->Ist.WrTmp.tmp),
3586 expr2vbits( &mce, st->Ist.WrTmp.data) );
njn25e49d8e72002-09-23 09:36:25 +00003587 break;
3588
sewardj95448072004-11-22 20:19:51 +00003589 case Ist_Put:
3590 do_shadow_PUT( &mce,
3591 st->Ist.Put.offset,
3592 st->Ist.Put.data,
3593 NULL /* shadow atom */ );
njn25e49d8e72002-09-23 09:36:25 +00003594 break;
3595
sewardj95448072004-11-22 20:19:51 +00003596 case Ist_PutI:
3597 do_shadow_PUTI( &mce,
3598 st->Ist.PutI.descr,
3599 st->Ist.PutI.ix,
3600 st->Ist.PutI.bias,
3601 st->Ist.PutI.data );
njn25e49d8e72002-09-23 09:36:25 +00003602 break;
3603
sewardj2e595852005-06-30 23:33:37 +00003604 case Ist_Store:
3605 do_shadow_Store( &mce, st->Ist.Store.end,
3606 st->Ist.Store.addr, 0/* addr bias */,
3607 st->Ist.Store.data,
3608 NULL /* shadow data */ );
njn25e49d8e72002-09-23 09:36:25 +00003609 break;
3610
sewardj95448072004-11-22 20:19:51 +00003611 case Ist_Exit:
sewardjd5204dc2004-12-31 01:16:11 +00003612 complainIfUndefined( &mce, st->Ist.Exit.guard );
njn25e49d8e72002-09-23 09:36:25 +00003613 break;
3614
sewardj29faa502005-03-16 18:20:21 +00003615 case Ist_IMark:
sewardj7cf4e6b2008-05-01 20:24:26 +00003616 break;
3617
3618 case Ist_NoOp:
sewardj72d75132007-11-09 23:06:35 +00003619 case Ist_MBE:
sewardjbd598e12005-01-07 12:10:21 +00003620 break;
3621
sewardj95448072004-11-22 20:19:51 +00003622 case Ist_Dirty:
3623 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
njn25e49d8e72002-09-23 09:36:25 +00003624 break;
3625
sewardj826ec492005-05-12 18:05:00 +00003626 case Ist_AbiHint:
sewardj7cf4e6b2008-05-01 20:24:26 +00003627 do_AbiHint( &mce, st->Ist.AbiHint.base,
3628 st->Ist.AbiHint.len,
3629 st->Ist.AbiHint.nia );
sewardj826ec492005-05-12 18:05:00 +00003630 break;
3631
njn25e49d8e72002-09-23 09:36:25 +00003632 default:
sewardj95448072004-11-22 20:19:51 +00003633 VG_(printf)("\n");
3634 ppIRStmt(st);
3635 VG_(printf)("\n");
3636 VG_(tool_panic)("memcheck: unhandled IRStmt");
3637
3638 } /* switch (st->tag) */
3639
sewardj7cf4e6b2008-05-01 20:24:26 +00003640 if (0 && verboze) {
sewardj95448072004-11-22 20:19:51 +00003641 for (j = first_stmt; j < bb->stmts_used; j++) {
3642 VG_(printf)(" ");
3643 ppIRStmt(bb->stmts[j]);
3644 VG_(printf)("\n");
3645 }
3646 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00003647 }
sewardj95448072004-11-22 20:19:51 +00003648
sewardj29faa502005-03-16 18:20:21 +00003649 /* ... and finally copy the stmt itself to the output. */
sewardj7cf4e6b2008-05-01 20:24:26 +00003650 stmt('C', &mce, st);
sewardj95448072004-11-22 20:19:51 +00003651
njn25e49d8e72002-09-23 09:36:25 +00003652 }
njn25e49d8e72002-09-23 09:36:25 +00003653
sewardj95448072004-11-22 20:19:51 +00003654 /* Now we need to complain if the jump target is undefined. */
3655 first_stmt = bb->stmts_used;
njn25e49d8e72002-09-23 09:36:25 +00003656
sewardj95448072004-11-22 20:19:51 +00003657 if (verboze) {
3658 VG_(printf)("bb->next = ");
3659 ppIRExpr(bb->next);
3660 VG_(printf)("\n\n");
3661 }
njn25e49d8e72002-09-23 09:36:25 +00003662
sewardj95448072004-11-22 20:19:51 +00003663 complainIfUndefined( &mce, bb->next );
njn25e49d8e72002-09-23 09:36:25 +00003664
sewardj7cf4e6b2008-05-01 20:24:26 +00003665 if (0 && verboze) {
sewardj95448072004-11-22 20:19:51 +00003666 for (j = first_stmt; j < bb->stmts_used; j++) {
3667 VG_(printf)(" ");
3668 ppIRStmt(bb->stmts[j]);
3669 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00003670 }
sewardj95448072004-11-22 20:19:51 +00003671 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00003672 }
njn25e49d8e72002-09-23 09:36:25 +00003673
sewardj95448072004-11-22 20:19:51 +00003674 return bb;
3675}
njn25e49d8e72002-09-23 09:36:25 +00003676
sewardj81651dc2007-08-28 06:05:20 +00003677/*------------------------------------------------------------*/
3678/*--- Post-tree-build final tidying ---*/
3679/*------------------------------------------------------------*/
3680
3681/* This exploits the observation that Memcheck often produces
3682 repeated conditional calls of the form
3683
sewardj7cf4e6b2008-05-01 20:24:26 +00003684 Dirty G MC_(helperc_value_check0/1/4/8_fail)(UInt otag)
sewardj81651dc2007-08-28 06:05:20 +00003685
3686 with the same guard expression G guarding the same helper call.
3687 The second and subsequent calls are redundant. This usually
3688 results from instrumentation of guest code containing multiple
3689 memory references at different constant offsets from the same base
3690 register. After optimisation of the instrumentation, you get a
3691 test for the definedness of the base register for each memory
3692 reference, which is kinda pointless. MC_(final_tidy) therefore
3693 looks for such repeated calls and removes all but the first. */
3694
3695/* A struct for recording which (helper, guard) pairs we have already
3696 seen. */
3697typedef
3698 struct { void* entry; IRExpr* guard; }
3699 Pair;
3700
3701/* Return True if e1 and e2 definitely denote the same value (used to
3702 compare guards). Return False if unknown; False is the safe
3703 answer. Since guest registers and guest memory do not have the
3704 SSA property we must return False if any Gets or Loads appear in
3705 the expression. */
3706
3707static Bool sameIRValue ( IRExpr* e1, IRExpr* e2 )
3708{
3709 if (e1->tag != e2->tag)
3710 return False;
3711 switch (e1->tag) {
3712 case Iex_Const:
3713 return eqIRConst( e1->Iex.Const.con, e2->Iex.Const.con );
3714 case Iex_Binop:
3715 return e1->Iex.Binop.op == e2->Iex.Binop.op
3716 && sameIRValue(e1->Iex.Binop.arg1, e2->Iex.Binop.arg1)
3717 && sameIRValue(e1->Iex.Binop.arg2, e2->Iex.Binop.arg2);
3718 case Iex_Unop:
3719 return e1->Iex.Unop.op == e2->Iex.Unop.op
3720 && sameIRValue(e1->Iex.Unop.arg, e2->Iex.Unop.arg);
3721 case Iex_RdTmp:
3722 return e1->Iex.RdTmp.tmp == e2->Iex.RdTmp.tmp;
3723 case Iex_Mux0X:
3724 return sameIRValue( e1->Iex.Mux0X.cond, e2->Iex.Mux0X.cond )
3725 && sameIRValue( e1->Iex.Mux0X.expr0, e2->Iex.Mux0X.expr0 )
3726 && sameIRValue( e1->Iex.Mux0X.exprX, e2->Iex.Mux0X.exprX );
3727 case Iex_Qop:
3728 case Iex_Triop:
3729 case Iex_CCall:
3730 /* be lazy. Could define equality for these, but they never
3731 appear to be used. */
3732 return False;
3733 case Iex_Get:
3734 case Iex_GetI:
3735 case Iex_Load:
3736 /* be conservative - these may not give the same value each
3737 time */
3738 return False;
3739 case Iex_Binder:
3740 /* should never see this */
3741 /* fallthrough */
3742 default:
3743 VG_(printf)("mc_translate.c: sameIRValue: unhandled: ");
3744 ppIRExpr(e1);
3745 VG_(tool_panic)("memcheck:sameIRValue");
3746 return False;
3747 }
3748}
3749
3750/* See if 'pairs' already has an entry for (entry, guard). Return
3751 True if so. If not, add an entry. */
3752
3753static
3754Bool check_or_add ( XArray* /*of Pair*/ pairs, IRExpr* guard, void* entry )
3755{
3756 Pair p;
3757 Pair* pp;
3758 Int i, n = VG_(sizeXA)( pairs );
3759 for (i = 0; i < n; i++) {
3760 pp = VG_(indexXA)( pairs, i );
3761 if (pp->entry == entry && sameIRValue(pp->guard, guard))
3762 return True;
3763 }
3764 p.guard = guard;
3765 p.entry = entry;
3766 VG_(addToXA)( pairs, &p );
3767 return False;
3768}
3769
3770static Bool is_helperc_value_checkN_fail ( HChar* name )
3771{
3772 return
sewardj7cf4e6b2008-05-01 20:24:26 +00003773 0==VG_(strcmp)(name, "MC_(helperc_value_check0_fail_no_o)")
3774 || 0==VG_(strcmp)(name, "MC_(helperc_value_check1_fail_no_o)")
3775 || 0==VG_(strcmp)(name, "MC_(helperc_value_check4_fail_no_o)")
3776 || 0==VG_(strcmp)(name, "MC_(helperc_value_check8_fail_no_o)")
3777 || 0==VG_(strcmp)(name, "MC_(helperc_value_check0_fail_w_o)")
3778 || 0==VG_(strcmp)(name, "MC_(helperc_value_check1_fail_w_o)")
3779 || 0==VG_(strcmp)(name, "MC_(helperc_value_check4_fail_w_o)")
3780 || 0==VG_(strcmp)(name, "MC_(helperc_value_check8_fail_w_o)");
sewardj81651dc2007-08-28 06:05:20 +00003781}
3782
3783IRSB* MC_(final_tidy) ( IRSB* sb_in )
3784{
3785 Int i;
3786 IRStmt* st;
3787 IRDirty* di;
3788 IRExpr* guard;
3789 IRCallee* cee;
3790 Bool alreadyPresent;
sewardj9c606bd2008-09-18 18:12:50 +00003791 XArray* pairs = VG_(newXA)( VG_(malloc), "mc.ft.1",
3792 VG_(free), sizeof(Pair) );
sewardj81651dc2007-08-28 06:05:20 +00003793 /* Scan forwards through the statements. Each time a call to one
3794 of the relevant helpers is seen, check if we have made a
3795 previous call to the same helper using the same guard
3796 expression, and if so, delete the call. */
3797 for (i = 0; i < sb_in->stmts_used; i++) {
3798 st = sb_in->stmts[i];
3799 tl_assert(st);
3800 if (st->tag != Ist_Dirty)
3801 continue;
3802 di = st->Ist.Dirty.details;
3803 guard = di->guard;
3804 if (!guard)
3805 continue;
3806 if (0) { ppIRExpr(guard); VG_(printf)("\n"); }
3807 cee = di->cee;
3808 if (!is_helperc_value_checkN_fail( cee->name ))
3809 continue;
3810 /* Ok, we have a call to helperc_value_check0/1/4/8_fail with
3811 guard 'guard'. Check if we have already seen a call to this
3812 function with the same guard. If so, delete it. If not,
3813 add it to the set of calls we do know about. */
3814 alreadyPresent = check_or_add( pairs, guard, cee->addr );
3815 if (alreadyPresent) {
3816 sb_in->stmts[i] = IRStmt_NoOp();
3817 if (0) VG_(printf)("XX\n");
3818 }
3819 }
3820 VG_(deleteXA)( pairs );
3821 return sb_in;
3822}
3823
3824
sewardj7cf4e6b2008-05-01 20:24:26 +00003825/*------------------------------------------------------------*/
3826/*--- Origin tracking stuff ---*/
3827/*------------------------------------------------------------*/
3828
3829static IRTemp findShadowTmpB ( MCEnv* mce, IRTemp orig )
3830{
3831 tl_assert(orig < mce->n_originalTmps);
3832 if (mce->tmpMapB[orig] == IRTemp_INVALID) {
3833 mce->tmpMapB[orig]
3834 = newIRTemp(mce->bb->tyenv, Ity_I32);
3835 }
3836 return mce->tmpMapB[orig];
3837}
3838
3839static IRAtom* gen_maxU32 ( MCEnv* mce, IRAtom* b1, IRAtom* b2 )
3840{
3841 return assignNew( 'B', mce, Ity_I32, binop(Iop_Max32U, b1, b2) );
3842}
3843
3844static IRAtom* gen_load_b ( MCEnv* mce, Int szB,
3845 IRAtom* baseaddr, Int offset )
3846{
3847 void* hFun;
3848 HChar* hName;
3849 IRTemp bTmp;
3850 IRDirty* di;
3851 IRType aTy = typeOfIRExpr( mce->bb->tyenv, baseaddr );
3852 IROp opAdd = aTy == Ity_I32 ? Iop_Add32 : Iop_Add64;
3853 IRAtom* ea = baseaddr;
3854 if (offset != 0) {
3855 IRAtom* off = aTy == Ity_I32 ? mkU32( offset )
3856 : mkU64( (Long)(Int)offset );
3857 ea = assignNew( 'B', mce, aTy, binop(opAdd, ea, off));
3858 }
3859 bTmp = newIRTemp(mce->bb->tyenv, mce->hWordTy);
3860
3861 switch (szB) {
3862 case 1: hFun = (void*)&MC_(helperc_b_load1);
3863 hName = "MC_(helperc_b_load1)";
3864 break;
3865 case 2: hFun = (void*)&MC_(helperc_b_load2);
3866 hName = "MC_(helperc_b_load2)";
3867 break;
3868 case 4: hFun = (void*)&MC_(helperc_b_load4);
3869 hName = "MC_(helperc_b_load4)";
3870 break;
3871 case 8: hFun = (void*)&MC_(helperc_b_load8);
3872 hName = "MC_(helperc_b_load8)";
3873 break;
3874 case 16: hFun = (void*)&MC_(helperc_b_load16);
3875 hName = "MC_(helperc_b_load16)";
3876 break;
3877 default:
3878 VG_(printf)("mc_translate.c: gen_load_b: unhandled szB == %d\n", szB);
3879 tl_assert(0);
3880 }
3881 di = unsafeIRDirty_1_N(
3882 bTmp, 1/*regparms*/, hName, VG_(fnptr_to_fnentry)( hFun ),
3883 mkIRExprVec_1( ea )
3884 );
3885 /* no need to mess with any annotations. This call accesses
3886 neither guest state nor guest memory. */
3887 stmt( 'B', mce, IRStmt_Dirty(di) );
3888 if (mce->hWordTy == Ity_I64) {
3889 /* 64-bit host */
3890 IRTemp bTmp32 = newIRTemp(mce->bb->tyenv, Ity_I32);
3891 assign( 'B', mce, bTmp32, unop(Iop_64to32, mkexpr(bTmp)) );
3892 return mkexpr(bTmp32);
3893 } else {
3894 /* 32-bit host */
3895 return mkexpr(bTmp);
3896 }
3897}
3898static void gen_store_b ( MCEnv* mce, Int szB,
3899 IRAtom* baseaddr, Int offset, IRAtom* dataB )
3900{
3901 void* hFun;
3902 HChar* hName;
3903 IRDirty* di;
3904 IRType aTy = typeOfIRExpr( mce->bb->tyenv, baseaddr );
3905 IROp opAdd = aTy == Ity_I32 ? Iop_Add32 : Iop_Add64;
3906 IRAtom* ea = baseaddr;
3907 if (offset != 0) {
3908 IRAtom* off = aTy == Ity_I32 ? mkU32( offset )
3909 : mkU64( (Long)(Int)offset );
3910 ea = assignNew( 'B', mce, aTy, binop(opAdd, ea, off));
3911 }
3912 if (mce->hWordTy == Ity_I64)
3913 dataB = assignNew( 'B', mce, Ity_I64, unop(Iop_32Uto64, dataB));
3914
3915 switch (szB) {
3916 case 1: hFun = (void*)&MC_(helperc_b_store1);
3917 hName = "MC_(helperc_b_store1)";
3918 break;
3919 case 2: hFun = (void*)&MC_(helperc_b_store2);
3920 hName = "MC_(helperc_b_store2)";
3921 break;
3922 case 4: hFun = (void*)&MC_(helperc_b_store4);
3923 hName = "MC_(helperc_b_store4)";
3924 break;
3925 case 8: hFun = (void*)&MC_(helperc_b_store8);
3926 hName = "MC_(helperc_b_store8)";
3927 break;
3928 case 16: hFun = (void*)&MC_(helperc_b_store16);
3929 hName = "MC_(helperc_b_store16)";
3930 break;
3931 default:
3932 tl_assert(0);
3933 }
3934 di = unsafeIRDirty_0_N( 2/*regparms*/,
3935 hName, VG_(fnptr_to_fnentry)( hFun ),
3936 mkIRExprVec_2( ea, dataB )
3937 );
3938 /* no need to mess with any annotations. This call accesses
3939 neither guest state nor guest memory. */
3940 stmt( 'B', mce, IRStmt_Dirty(di) );
3941}
3942
3943static IRAtom* narrowTo32 ( MCEnv* mce, IRAtom* e ) {
3944 IRType eTy = typeOfIRExpr(mce->bb->tyenv, e);
3945 if (eTy == Ity_I64)
3946 return assignNew( 'B', mce, Ity_I32, unop(Iop_64to32, e) );
3947 if (eTy == Ity_I32)
3948 return e;
3949 tl_assert(0);
3950}
3951
3952static IRAtom* zWidenFrom32 ( MCEnv* mce, IRType dstTy, IRAtom* e ) {
3953 IRType eTy = typeOfIRExpr(mce->bb->tyenv, e);
3954 tl_assert(eTy == Ity_I32);
3955 if (dstTy == Ity_I64)
3956 return assignNew( 'B', mce, Ity_I64, unop(Iop_32Uto64, e) );
3957 tl_assert(0);
3958}
3959
3960static IRAtom* schemeE ( MCEnv* mce, IRExpr* e )
3961{
3962 tl_assert(MC_(clo_mc_level) == 3);
3963
3964 switch (e->tag) {
3965
3966 case Iex_GetI: {
3967 IRRegArray* descr_b;
3968 IRAtom *t1, *t2, *t3, *t4;
3969 IRRegArray* descr = e->Iex.GetI.descr;
3970 IRType equivIntTy
3971 = MC_(get_otrack_reg_array_equiv_int_type)(descr);
3972 /* If this array is unshadowable for whatever reason, use the
3973 usual approximation. */
3974 if (equivIntTy == Ity_INVALID)
3975 return mkU32(0);
3976 tl_assert(sizeofIRType(equivIntTy) >= 4);
3977 tl_assert(sizeofIRType(equivIntTy) == sizeofIRType(descr->elemTy));
3978 descr_b = mkIRRegArray( descr->base + 2*mce->layout->total_sizeB,
3979 equivIntTy, descr->nElems );
3980 /* Do a shadow indexed get of the same size, giving t1. Take
3981 the bottom 32 bits of it, giving t2. Compute into t3 the
3982 origin for the index (almost certainly zero, but there's
3983 no harm in being completely general here, since iropt will
3984 remove any useless code), and fold it in, giving a final
3985 value t4. */
3986 t1 = assignNew( 'B', mce, equivIntTy,
3987 IRExpr_GetI( descr_b, e->Iex.GetI.ix,
3988 e->Iex.GetI.bias ));
3989 t2 = narrowTo32( mce, t1 );
3990 t3 = schemeE( mce, e->Iex.GetI.ix );
3991 t4 = gen_maxU32( mce, t2, t3 );
3992 return t4;
3993 }
3994 case Iex_CCall: {
3995 Int i;
3996 IRAtom* here;
3997 IRExpr** args = e->Iex.CCall.args;
3998 IRAtom* curr = mkU32(0);
3999 for (i = 0; args[i]; i++) {
4000 tl_assert(i < 32);
4001 tl_assert(isOriginalAtom(mce, args[i]));
4002 /* Only take notice of this arg if the callee's
4003 mc-exclusion mask does not say it is to be excluded. */
4004 if (e->Iex.CCall.cee->mcx_mask & (1<<i)) {
4005 /* the arg is to be excluded from definedness checking.
4006 Do nothing. */
4007 if (0) VG_(printf)("excluding %s(%d)\n",
4008 e->Iex.CCall.cee->name, i);
4009 } else {
4010 /* calculate the arg's definedness, and pessimistically
4011 merge it in. */
4012 here = schemeE( mce, args[i] );
4013 curr = gen_maxU32( mce, curr, here );
4014 }
4015 }
4016 return curr;
4017 }
4018 case Iex_Load: {
4019 Int dszB;
4020 dszB = sizeofIRType(e->Iex.Load.ty);
4021 /* assert that the B value for the address is already
4022 available (somewhere) */
4023 tl_assert(isIRAtom(e->Iex.Load.addr));
4024 tl_assert(mce->hWordTy == Ity_I32 || mce->hWordTy == Ity_I64);
4025 return gen_load_b( mce, dszB, e->Iex.Load.addr, 0 );
4026 }
4027 case Iex_Mux0X: {
4028 IRAtom* b1 = schemeE( mce, e->Iex.Mux0X.cond );
4029 IRAtom* b2 = schemeE( mce, e->Iex.Mux0X.expr0 );
4030 IRAtom* b3 = schemeE( mce, e->Iex.Mux0X.exprX );
4031 return gen_maxU32( mce, b1, gen_maxU32( mce, b2, b3 ));
4032 }
4033 case Iex_Qop: {
4034 IRAtom* b1 = schemeE( mce, e->Iex.Qop.arg1 );
4035 IRAtom* b2 = schemeE( mce, e->Iex.Qop.arg2 );
4036 IRAtom* b3 = schemeE( mce, e->Iex.Qop.arg3 );
4037 IRAtom* b4 = schemeE( mce, e->Iex.Qop.arg4 );
4038 return gen_maxU32( mce, gen_maxU32( mce, b1, b2 ),
4039 gen_maxU32( mce, b3, b4 ) );
4040 }
4041 case Iex_Triop: {
4042 IRAtom* b1 = schemeE( mce, e->Iex.Triop.arg1 );
4043 IRAtom* b2 = schemeE( mce, e->Iex.Triop.arg2 );
4044 IRAtom* b3 = schemeE( mce, e->Iex.Triop.arg3 );
4045 return gen_maxU32( mce, b1, gen_maxU32( mce, b2, b3 ) );
4046 }
4047 case Iex_Binop: {
4048 IRAtom* b1 = schemeE( mce, e->Iex.Binop.arg1 );
4049 IRAtom* b2 = schemeE( mce, e->Iex.Binop.arg2 );
4050 return gen_maxU32( mce, b1, b2 );
4051 }
4052 case Iex_Unop: {
4053 IRAtom* b1 = schemeE( mce, e->Iex.Unop.arg );
4054 return b1;
4055 }
4056 case Iex_Const:
4057 return mkU32(0);
4058 case Iex_RdTmp:
4059 return mkexpr( findShadowTmpB( mce, e->Iex.RdTmp.tmp ));
4060 case Iex_Get: {
4061 Int b_offset = MC_(get_otrack_shadow_offset)(
4062 e->Iex.Get.offset,
4063 sizeofIRType(e->Iex.Get.ty)
4064 );
4065 tl_assert(b_offset >= -1
4066 && b_offset <= mce->layout->total_sizeB -4);
4067 if (b_offset >= 0) {
4068 /* FIXME: this isn't an atom! */
4069 return IRExpr_Get( b_offset + 2*mce->layout->total_sizeB,
4070 Ity_I32 );
4071 }
4072 return mkU32(0);
4073 }
4074 default:
4075 VG_(printf)("mc_translate.c: schemeE: unhandled: ");
4076 ppIRExpr(e);
4077 VG_(tool_panic)("memcheck:schemeE");
4078 }
4079}
4080
4081static void do_origins_Dirty ( MCEnv* mce, IRDirty* d )
4082{
4083 // This is a hacked version of do_shadow_Dirty
4084 Int i, n, offset, toDo, gSz, gOff;
4085 IRAtom *here, *curr;
4086 IRTemp dst;
4087 IREndness end;
4088
4089 /* What's the native endianness? We need to know this. */
4090# if defined(VG_BIGENDIAN)
4091 end = Iend_BE;
4092# elif defined(VG_LITTLEENDIAN)
4093 end = Iend_LE;
4094# else
4095# error "Unknown endianness"
4096# endif
4097
4098 /* First check the guard. */
4099 curr = schemeE( mce, d->guard );
4100
4101 /* Now round up all inputs and maxU32 over them. */
4102
4103 /* Inputs: unmasked args */
4104 for (i = 0; d->args[i]; i++) {
4105 if (d->cee->mcx_mask & (1<<i)) {
4106 /* ignore this arg */
4107 } else {
4108 here = schemeE( mce, d->args[i] );
4109 curr = gen_maxU32( mce, curr, here );
4110 }
4111 }
4112
4113 /* Inputs: guest state that we read. */
4114 for (i = 0; i < d->nFxState; i++) {
4115 tl_assert(d->fxState[i].fx != Ifx_None);
4116 if (d->fxState[i].fx == Ifx_Write)
4117 continue;
4118
4119 /* Ignore any sections marked as 'always defined'. */
4120 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
4121 if (0)
4122 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
4123 d->fxState[i].offset, d->fxState[i].size );
4124 continue;
4125 }
4126
4127 /* This state element is read or modified. So we need to
4128 consider it. If larger than 4 bytes, deal with it in 4-byte
4129 chunks. */
4130 gSz = d->fxState[i].size;
4131 gOff = d->fxState[i].offset;
4132 tl_assert(gSz > 0);
4133 while (True) {
4134 Int b_offset;
4135 if (gSz == 0) break;
4136 n = gSz <= 4 ? gSz : 4;
4137 /* update 'curr' with maxU32 of the state slice
4138 gOff .. gOff+n-1 */
4139 b_offset = MC_(get_otrack_shadow_offset)(gOff, 4);
4140 if (b_offset != -1) {
4141 here = assignNew( 'B',mce,
4142 Ity_I32,
4143 IRExpr_Get(b_offset + 2*mce->layout->total_sizeB,
4144 Ity_I32));
4145 curr = gen_maxU32( mce, curr, here );
4146 }
4147 gSz -= n;
4148 gOff += n;
4149 }
4150
4151 }
4152
4153 /* Inputs: memory */
4154
4155 if (d->mFx != Ifx_None) {
4156 /* Because we may do multiple shadow loads/stores from the same
4157 base address, it's best to do a single test of its
4158 definedness right now. Post-instrumentation optimisation
4159 should remove all but this test. */
4160 tl_assert(d->mAddr);
4161 here = schemeE( mce, d->mAddr );
4162 curr = gen_maxU32( mce, curr, here );
4163 }
4164
4165 /* Deal with memory inputs (reads or modifies) */
4166 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
4167 offset = 0;
4168 toDo = d->mSize;
4169 /* chew off 32-bit chunks. We don't care about the endianness
4170 since it's all going to be condensed down to a single bit,
4171 but nevertheless choose an endianness which is hopefully
4172 native to the platform. */
4173 while (toDo >= 4) {
4174 here = gen_load_b( mce, 4, d->mAddr, d->mSize - toDo );
4175 curr = gen_maxU32( mce, curr, here );
4176 toDo -= 4;
4177 }
sewardj8c93fcc2008-10-30 13:08:31 +00004178 /* handle possible 16-bit excess */
4179 while (toDo >= 2) {
4180 here = gen_load_b( mce, 2, d->mAddr, d->mSize - toDo );
4181 curr = gen_maxU32( mce, curr, here );
4182 toDo -= 2;
4183 }
4184 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj7cf4e6b2008-05-01 20:24:26 +00004185 }
4186
4187 /* Whew! So curr is a 32-bit B-value which should give an origin
4188 of some use if any of the inputs to the helper are undefined.
4189 Now we need to re-distribute the results to all destinations. */
4190
4191 /* Outputs: the destination temporary, if there is one. */
4192 if (d->tmp != IRTemp_INVALID) {
4193 dst = findShadowTmpB(mce, d->tmp);
4194 assign( 'V', mce, dst, curr );
4195 }
4196
4197 /* Outputs: guest state that we write or modify. */
4198 for (i = 0; i < d->nFxState; i++) {
4199 tl_assert(d->fxState[i].fx != Ifx_None);
4200 if (d->fxState[i].fx == Ifx_Read)
4201 continue;
4202
4203 /* Ignore any sections marked as 'always defined'. */
4204 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
4205 continue;
4206
4207 /* This state element is written or modified. So we need to
4208 consider it. If larger than 4 bytes, deal with it in 4-byte
4209 chunks. */
4210 gSz = d->fxState[i].size;
4211 gOff = d->fxState[i].offset;
4212 tl_assert(gSz > 0);
4213 while (True) {
4214 Int b_offset;
4215 if (gSz == 0) break;
4216 n = gSz <= 4 ? gSz : 4;
4217 /* Write 'curr' to the state slice gOff .. gOff+n-1 */
4218 b_offset = MC_(get_otrack_shadow_offset)(gOff, 4);
4219 if (b_offset != -1) {
4220 stmt( 'B', mce, IRStmt_Put(b_offset + 2*mce->layout->total_sizeB,
4221 curr ));
4222 }
4223 gSz -= n;
4224 gOff += n;
4225 }
4226 }
4227
4228 /* Outputs: memory that we write or modify. Same comments about
4229 endianness as above apply. */
4230 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
4231 offset = 0;
4232 toDo = d->mSize;
4233 /* chew off 32-bit chunks */
4234 while (toDo >= 4) {
4235 gen_store_b( mce, 4, d->mAddr, d->mSize - toDo, curr );
4236 toDo -= 4;
4237 }
sewardj8c93fcc2008-10-30 13:08:31 +00004238 /* handle possible 16-bit excess */
4239 while (toDo >= 2) {
4240 gen_store_b( mce, 2, d->mAddr, d->mSize - toDo, curr );
4241 toDo -= 2;
4242 }
4243 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
sewardj7cf4e6b2008-05-01 20:24:26 +00004244 }
4245
4246}
4247
4248static void schemeS ( MCEnv* mce, IRStmt* st )
4249{
4250 tl_assert(MC_(clo_mc_level) == 3);
4251
4252 switch (st->tag) {
4253
4254 case Ist_AbiHint:
4255 /* The value-check instrumenter handles this - by arranging
4256 to pass the address of the next instruction to
4257 MC_(helperc_MAKE_STACK_UNINIT). This is all that needs to
4258 happen for origin tracking w.r.t. AbiHints. So there is
4259 nothing to do here. */
4260 break;
4261
4262 case Ist_PutI: {
4263 IRRegArray* descr_b;
4264 IRAtom *t1, *t2, *t3, *t4;
4265 IRRegArray* descr = st->Ist.PutI.descr;
4266 IRType equivIntTy
4267 = MC_(get_otrack_reg_array_equiv_int_type)(descr);
4268 /* If this array is unshadowable for whatever reason,
4269 generate no code. */
4270 if (equivIntTy == Ity_INVALID)
4271 break;
4272 tl_assert(sizeofIRType(equivIntTy) >= 4);
4273 tl_assert(sizeofIRType(equivIntTy) == sizeofIRType(descr->elemTy));
4274 descr_b
4275 = mkIRRegArray( descr->base + 2*mce->layout->total_sizeB,
4276 equivIntTy, descr->nElems );
4277 /* Compute a value to Put - the conjoinment of the origin for
4278 the data to be Put-ted (obviously) and of the index value
4279 (not so obviously). */
4280 t1 = schemeE( mce, st->Ist.PutI.data );
4281 t2 = schemeE( mce, st->Ist.PutI.ix );
4282 t3 = gen_maxU32( mce, t1, t2 );
4283 t4 = zWidenFrom32( mce, equivIntTy, t3 );
4284 stmt( 'B', mce, IRStmt_PutI( descr_b, st->Ist.PutI.ix,
4285 st->Ist.PutI.bias, t4 ));
4286 break;
4287 }
4288 case Ist_Dirty:
4289 do_origins_Dirty( mce, st->Ist.Dirty.details );
4290 break;
4291 case Ist_Store: {
4292 Int dszB;
4293 IRAtom* dataB;
4294 /* assert that the B value for the address is already
4295 available (somewhere) */
4296 tl_assert(isIRAtom(st->Ist.Store.addr));
4297 dszB = sizeofIRType(
4298 typeOfIRExpr(mce->bb->tyenv, st->Ist.Store.data ));
4299 dataB = schemeE( mce, st->Ist.Store.data );
4300 gen_store_b( mce, dszB, st->Ist.Store.addr, 0/*offset*/, dataB );
4301 break;
4302 }
4303 case Ist_Put: {
4304 Int b_offset
4305 = MC_(get_otrack_shadow_offset)(
4306 st->Ist.Put.offset,
4307 sizeofIRType(typeOfIRExpr(mce->bb->tyenv, st->Ist.Put.data))
4308 );
4309 if (b_offset >= 0) {
4310 /* FIXME: this isn't an atom! */
4311 stmt( 'B', mce, IRStmt_Put(b_offset + 2*mce->layout->total_sizeB,
4312 schemeE( mce, st->Ist.Put.data )) );
4313 }
4314 break;
4315 }
4316 case Ist_WrTmp:
4317 assign( 'B', mce, findShadowTmpB(mce, st->Ist.WrTmp.tmp),
4318 schemeE(mce, st->Ist.WrTmp.data) );
4319 break;
4320 case Ist_MBE:
4321 case Ist_NoOp:
4322 case Ist_Exit:
4323 case Ist_IMark:
4324 break;
4325 default:
4326 VG_(printf)("mc_translate.c: schemeS: unhandled: ");
4327 ppIRStmt(st);
4328 VG_(tool_panic)("memcheck:schemeS");
4329 }
4330}
4331
4332
njn25e49d8e72002-09-23 09:36:25 +00004333/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00004334/*--- end mc_translate.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00004335/*--------------------------------------------------------------------*/