blob: 38ca17de0e43482f7b57ff4affbfc9aa6393f6b7 [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
njn53612422005-03-12 16:22:54 +000011 Copyright (C) 2000-2005 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"
33#include "pub_tool_hashtable.h" // For mac_shared.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_profile.h"
37#include "pub_tool_tooliface.h"
38#include "mc_include.h"
njn25e49d8e72002-09-23 09:36:25 +000039
njn25e49d8e72002-09-23 09:36:25 +000040
sewardj95448072004-11-22 20:19:51 +000041/*------------------------------------------------------------*/
42/*--- Forward decls ---*/
43/*------------------------------------------------------------*/
44
45struct _MCEnv;
46
47static IRType shadowType ( IRType ty );
48static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
49
50
51/*------------------------------------------------------------*/
52/*--- Memcheck running state, and tmp management. ---*/
53/*------------------------------------------------------------*/
54
55/* Carries around state during memcheck instrumentation. */
56typedef
57 struct _MCEnv {
58 /* MODIFIED: the bb being constructed. IRStmts are added. */
59 IRBB* bb;
60
61 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
62 original temps to their current their current shadow temp.
63 Initially all entries are IRTemp_INVALID. Entries are added
64 lazily since many original temps are not used due to
65 optimisation prior to instrumentation. Note that floating
66 point original tmps are shadowed by integer tmps of the same
67 size, and Bit-typed original tmps are shadowed by the type
68 Ity_I8. See comment below. */
69 IRTemp* tmpMap;
70 Int n_originalTmps; /* for range checking */
71
sewardjd5204dc2004-12-31 01:16:11 +000072 /* MODIFIED: indicates whether "bogus" literals have so far been
73 found. Starts off False, and may change to True. */
74 Bool bogusLiterals;
75
sewardj95448072004-11-22 20:19:51 +000076 /* READONLY: the guest layout. This indicates which parts of
77 the guest state should be regarded as 'always defined'. */
78 VexGuestLayout* layout;
79 /* READONLY: the host word type. Needed for constructing
80 arguments of type 'HWord' to be passed to helper functions.
81 Ity_I32 or Ity_I64 only. */
82 IRType hWordTy;
83 }
84 MCEnv;
85
86/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
87 demand), as they are encountered. This is for two reasons.
88
89 (1) (less important reason): Many original tmps are unused due to
90 initial IR optimisation, and we do not want to spaces in tables
91 tracking them.
92
93 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
94 table indexed [0 .. n_types-1], which gives the current shadow for
95 each original tmp, or INVALID_IRTEMP if none is so far assigned.
96 It is necessary to support making multiple assignments to a shadow
97 -- specifically, after testing a shadow for definedness, it needs
98 to be made defined. But IR's SSA property disallows this.
99
100 (2) (more important reason): Therefore, when a shadow needs to get
101 a new value, a new temporary is created, the value is assigned to
102 that, and the tmpMap is updated to reflect the new binding.
103
104 A corollary is that if the tmpMap maps a given tmp to
105 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
106 there's a read-before-write error in the original tmps. The IR
107 sanity checker should catch all such anomalies, however.
njn25e49d8e72002-09-23 09:36:25 +0000108*/
sewardj95448072004-11-22 20:19:51 +0000109
110/* Find the tmp currently shadowing the given original tmp. If none
111 so far exists, allocate one. */
112static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
njn25e49d8e72002-09-23 09:36:25 +0000113{
sewardj95448072004-11-22 20:19:51 +0000114 tl_assert(orig < mce->n_originalTmps);
115 if (mce->tmpMap[orig] == IRTemp_INVALID) {
116 mce->tmpMap[orig]
117 = newIRTemp(mce->bb->tyenv,
118 shadowType(mce->bb->tyenv->types[orig]));
njn25e49d8e72002-09-23 09:36:25 +0000119 }
sewardj95448072004-11-22 20:19:51 +0000120 return mce->tmpMap[orig];
njn25e49d8e72002-09-23 09:36:25 +0000121}
122
sewardj95448072004-11-22 20:19:51 +0000123/* Allocate a new shadow for the given original tmp. This means any
124 previous shadow is abandoned. This is needed because it is
125 necessary to give a new value to a shadow once it has been tested
126 for undefinedness, but unfortunately IR's SSA property disallows
127 this. Instead we must abandon the old shadow, allocate a new one
128 and use that instead. */
129static void newShadowTmp ( MCEnv* mce, IRTemp orig )
njn25e49d8e72002-09-23 09:36:25 +0000130{
sewardj95448072004-11-22 20:19:51 +0000131 tl_assert(orig < mce->n_originalTmps);
132 mce->tmpMap[orig]
133 = newIRTemp(mce->bb->tyenv,
134 shadowType(mce->bb->tyenv->types[orig]));
135}
136
137
138/*------------------------------------------------------------*/
139/*--- IRAtoms -- a subset of IRExprs ---*/
140/*------------------------------------------------------------*/
141
142/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj710d6c22005-03-20 18:55:15 +0000143 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardj95448072004-11-22 20:19:51 +0000144 input, most of this code deals in atoms. Usefully, a value atom
145 always has a V-value which is also an atom: constants are shadowed
146 by constants, and temps are shadowed by the corresponding shadow
147 temporary. */
148
149typedef IRExpr IRAtom;
150
151/* (used for sanity checks only): is this an atom which looks
152 like it's from original code? */
153static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
154{
155 if (a1->tag == Iex_Const)
156 return True;
157 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
158 return True;
159 return False;
160}
161
162/* (used for sanity checks only): is this an atom which looks
163 like it's from shadow code? */
164static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
165{
166 if (a1->tag == Iex_Const)
167 return True;
168 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
169 return True;
170 return False;
171}
172
173/* (used for sanity checks only): check that both args are atoms and
174 are identically-kinded. */
175static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
176{
sewardjbef552a2005-08-30 12:54:36 +0000177 if (a1->tag == Iex_Tmp && a2->tag == Iex_Tmp)
sewardj95448072004-11-22 20:19:51 +0000178 return True;
sewardjbef552a2005-08-30 12:54:36 +0000179 if (a1->tag == Iex_Const && a2->tag == Iex_Const)
sewardj95448072004-11-22 20:19:51 +0000180 return True;
181 return False;
182}
183
184
185/*------------------------------------------------------------*/
186/*--- Type management ---*/
187/*------------------------------------------------------------*/
188
189/* Shadow state is always accessed using integer types. This returns
190 an integer type with the same size (as per sizeofIRType) as the
191 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj3245c912004-12-10 14:58:26 +0000192 I64, V128. */
sewardj95448072004-11-22 20:19:51 +0000193
194static IRType shadowType ( IRType ty )
195{
196 switch (ty) {
197 case Ity_I1:
198 case Ity_I8:
199 case Ity_I16:
200 case Ity_I32:
sewardj6cf40ff2005-04-20 22:31:26 +0000201 case Ity_I64:
202 case Ity_I128: return ty;
sewardj3245c912004-12-10 14:58:26 +0000203 case Ity_F32: return Ity_I32;
204 case Ity_F64: return Ity_I64;
205 case Ity_V128: return Ity_V128;
sewardj95448072004-11-22 20:19:51 +0000206 default: ppIRType(ty);
207 VG_(tool_panic)("memcheck:shadowType");
208 }
209}
210
211/* Produce a 'defined' value of the given shadow type. Should only be
212 supplied shadow types (Bit/I8/I16/I32/UI64). */
213static IRExpr* definedOfType ( IRType ty ) {
214 switch (ty) {
sewardj170ee212004-12-10 18:57:51 +0000215 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
216 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
217 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
218 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
219 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
220 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
sewardj95448072004-11-22 20:19:51 +0000221 default: VG_(tool_panic)("memcheck:definedOfType");
njn25e49d8e72002-09-23 09:36:25 +0000222 }
223}
224
225
sewardj95448072004-11-22 20:19:51 +0000226/*------------------------------------------------------------*/
227/*--- Constructing IR fragments ---*/
228/*------------------------------------------------------------*/
229
230/* assign value to tmp */
231#define assign(_bb,_tmp,_expr) \
232 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
233
234/* add stmt to a bb */
235#define stmt(_bb,_stmt) \
236 addStmtToIRBB((_bb), (_stmt))
237
238/* build various kinds of expressions */
239#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
240#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
241#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
242#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
243#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
244#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj170ee212004-12-10 18:57:51 +0000245#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardj95448072004-11-22 20:19:51 +0000246#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
247
248/* bind the given expression to a new temporary, and return the
249 temporary. This effectively converts an arbitrary expression into
250 an atom. */
251static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
252 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
253 assign(mce->bb, t, e);
254 return mkexpr(t);
255}
256
257
258/*------------------------------------------------------------*/
259/*--- Constructing definedness primitive ops ---*/
260/*------------------------------------------------------------*/
261
262/* --------- Defined-if-either-defined --------- */
263
264static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
265 tl_assert(isShadowAtom(mce,a1));
266 tl_assert(isShadowAtom(mce,a2));
267 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
268}
269
270static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
271 tl_assert(isShadowAtom(mce,a1));
272 tl_assert(isShadowAtom(mce,a2));
273 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
274}
275
276static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
277 tl_assert(isShadowAtom(mce,a1));
278 tl_assert(isShadowAtom(mce,a2));
279 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
280}
281
sewardj7010f6e2004-12-10 13:35:22 +0000282static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
283 tl_assert(isShadowAtom(mce,a1));
284 tl_assert(isShadowAtom(mce,a2));
285 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
286}
287
sewardj20d38f22005-02-07 23:50:18 +0000288static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj170ee212004-12-10 18:57:51 +0000289 tl_assert(isShadowAtom(mce,a1));
290 tl_assert(isShadowAtom(mce,a2));
sewardj20d38f22005-02-07 23:50:18 +0000291 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj170ee212004-12-10 18:57:51 +0000292}
293
sewardj95448072004-11-22 20:19:51 +0000294/* --------- Undefined-if-either-undefined --------- */
295
296static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
297 tl_assert(isShadowAtom(mce,a1));
298 tl_assert(isShadowAtom(mce,a2));
299 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
300}
301
302static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
303 tl_assert(isShadowAtom(mce,a1));
304 tl_assert(isShadowAtom(mce,a2));
305 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
306}
307
308static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
309 tl_assert(isShadowAtom(mce,a1));
310 tl_assert(isShadowAtom(mce,a2));
311 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
312}
313
314static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
315 tl_assert(isShadowAtom(mce,a1));
316 tl_assert(isShadowAtom(mce,a2));
317 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
318}
319
sewardj20d38f22005-02-07 23:50:18 +0000320static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj3245c912004-12-10 14:58:26 +0000321 tl_assert(isShadowAtom(mce,a1));
322 tl_assert(isShadowAtom(mce,a2));
sewardj20d38f22005-02-07 23:50:18 +0000323 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj3245c912004-12-10 14:58:26 +0000324}
325
sewardje50a1b12004-12-17 01:24:54 +0000326static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardj95448072004-11-22 20:19:51 +0000327 switch (vty) {
sewardje50a1b12004-12-17 01:24:54 +0000328 case Ity_I8: return mkUifU8(mce, a1, a2);
sewardja1d93302004-12-12 16:45:06 +0000329 case Ity_I16: return mkUifU16(mce, a1, a2);
330 case Ity_I32: return mkUifU32(mce, a1, a2);
331 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardj20d38f22005-02-07 23:50:18 +0000332 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardj95448072004-11-22 20:19:51 +0000333 default:
334 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
335 VG_(tool_panic)("memcheck:mkUifU");
njn25e49d8e72002-09-23 09:36:25 +0000336 }
337}
338
sewardj95448072004-11-22 20:19:51 +0000339/* --------- The Left-family of operations. --------- */
njn25e49d8e72002-09-23 09:36:25 +0000340
sewardj95448072004-11-22 20:19:51 +0000341static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
342 tl_assert(isShadowAtom(mce,a1));
343 /* It's safe to duplicate a1 since it's only an atom */
344 return assignNew(mce, Ity_I8,
345 binop(Iop_Or8, a1,
346 assignNew(mce, Ity_I8,
sewardj37c31cc2005-04-26 23:49:24 +0000347 unop(Iop_Neg8, a1))));
sewardj95448072004-11-22 20:19:51 +0000348}
349
350static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
351 tl_assert(isShadowAtom(mce,a1));
352 /* It's safe to duplicate a1 since it's only an atom */
353 return assignNew(mce, Ity_I16,
354 binop(Iop_Or16, a1,
355 assignNew(mce, Ity_I16,
sewardj37c31cc2005-04-26 23:49:24 +0000356 unop(Iop_Neg16, a1))));
sewardj95448072004-11-22 20:19:51 +0000357}
358
359static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
360 tl_assert(isShadowAtom(mce,a1));
361 /* It's safe to duplicate a1 since it's only an atom */
362 return assignNew(mce, Ity_I32,
363 binop(Iop_Or32, a1,
364 assignNew(mce, Ity_I32,
sewardj37c31cc2005-04-26 23:49:24 +0000365 unop(Iop_Neg32, a1))));
sewardj95448072004-11-22 20:19:51 +0000366}
367
sewardj681be302005-01-15 20:43:58 +0000368static IRAtom* mkLeft64 ( MCEnv* mce, IRAtom* a1 ) {
369 tl_assert(isShadowAtom(mce,a1));
370 /* It's safe to duplicate a1 since it's only an atom */
371 return assignNew(mce, Ity_I64,
372 binop(Iop_Or64, a1,
373 assignNew(mce, Ity_I64,
sewardj37c31cc2005-04-26 23:49:24 +0000374 unop(Iop_Neg64, a1))));
sewardj681be302005-01-15 20:43:58 +0000375}
376
sewardj95448072004-11-22 20:19:51 +0000377/* --------- 'Improvement' functions for AND/OR. --------- */
378
379/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
380 defined (0); all other -> undefined (1).
381*/
382static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
njn25e49d8e72002-09-23 09:36:25 +0000383{
sewardj95448072004-11-22 20:19:51 +0000384 tl_assert(isOriginalAtom(mce, data));
385 tl_assert(isShadowAtom(mce, vbits));
386 tl_assert(sameKindedAtoms(data, vbits));
387 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
388}
njn25e49d8e72002-09-23 09:36:25 +0000389
sewardj95448072004-11-22 20:19:51 +0000390static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
391{
392 tl_assert(isOriginalAtom(mce, data));
393 tl_assert(isShadowAtom(mce, vbits));
394 tl_assert(sameKindedAtoms(data, vbits));
395 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
396}
njn25e49d8e72002-09-23 09:36:25 +0000397
sewardj95448072004-11-22 20:19:51 +0000398static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
399{
400 tl_assert(isOriginalAtom(mce, data));
401 tl_assert(isShadowAtom(mce, vbits));
402 tl_assert(sameKindedAtoms(data, vbits));
403 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
404}
njn25e49d8e72002-09-23 09:36:25 +0000405
sewardj7010f6e2004-12-10 13:35:22 +0000406static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
407{
408 tl_assert(isOriginalAtom(mce, data));
409 tl_assert(isShadowAtom(mce, vbits));
410 tl_assert(sameKindedAtoms(data, vbits));
411 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
412}
413
sewardj20d38f22005-02-07 23:50:18 +0000414static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj170ee212004-12-10 18:57:51 +0000415{
416 tl_assert(isOriginalAtom(mce, data));
417 tl_assert(isShadowAtom(mce, vbits));
418 tl_assert(sameKindedAtoms(data, vbits));
sewardj20d38f22005-02-07 23:50:18 +0000419 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj170ee212004-12-10 18:57:51 +0000420}
421
sewardj95448072004-11-22 20:19:51 +0000422/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
423 defined (0); all other -> undefined (1).
424*/
425static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
426{
427 tl_assert(isOriginalAtom(mce, data));
428 tl_assert(isShadowAtom(mce, vbits));
429 tl_assert(sameKindedAtoms(data, vbits));
430 return assignNew(
431 mce, Ity_I8,
432 binop(Iop_Or8,
433 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
434 vbits) );
435}
njn25e49d8e72002-09-23 09:36:25 +0000436
sewardj95448072004-11-22 20:19:51 +0000437static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
438{
439 tl_assert(isOriginalAtom(mce, data));
440 tl_assert(isShadowAtom(mce, vbits));
441 tl_assert(sameKindedAtoms(data, vbits));
442 return assignNew(
443 mce, Ity_I16,
444 binop(Iop_Or16,
445 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
446 vbits) );
447}
njn25e49d8e72002-09-23 09:36:25 +0000448
sewardj95448072004-11-22 20:19:51 +0000449static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
450{
451 tl_assert(isOriginalAtom(mce, data));
452 tl_assert(isShadowAtom(mce, vbits));
453 tl_assert(sameKindedAtoms(data, vbits));
454 return assignNew(
455 mce, Ity_I32,
456 binop(Iop_Or32,
457 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
458 vbits) );
459}
460
sewardj7010f6e2004-12-10 13:35:22 +0000461static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
462{
463 tl_assert(isOriginalAtom(mce, data));
464 tl_assert(isShadowAtom(mce, vbits));
465 tl_assert(sameKindedAtoms(data, vbits));
466 return assignNew(
467 mce, Ity_I64,
468 binop(Iop_Or64,
469 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
470 vbits) );
471}
472
sewardj20d38f22005-02-07 23:50:18 +0000473static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj170ee212004-12-10 18:57:51 +0000474{
475 tl_assert(isOriginalAtom(mce, data));
476 tl_assert(isShadowAtom(mce, vbits));
477 tl_assert(sameKindedAtoms(data, vbits));
478 return assignNew(
479 mce, Ity_V128,
sewardj20d38f22005-02-07 23:50:18 +0000480 binop(Iop_OrV128,
481 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj170ee212004-12-10 18:57:51 +0000482 vbits) );
483}
484
sewardj95448072004-11-22 20:19:51 +0000485/* --------- Pessimising casts. --------- */
486
487static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
488{
sewardj7cf97ee2004-11-28 14:25:01 +0000489 IRType ty;
490 IRAtom* tmp1;
sewardj95448072004-11-22 20:19:51 +0000491 /* Note, dst_ty is a shadow type, not an original type. */
492 /* First of all, collapse vbits down to a single bit. */
493 tl_assert(isShadowAtom(mce,vbits));
sewardj7cf97ee2004-11-28 14:25:01 +0000494 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
495 tmp1 = NULL;
sewardj95448072004-11-22 20:19:51 +0000496 switch (ty) {
497 case Ity_I1:
498 tmp1 = vbits;
njn25e49d8e72002-09-23 09:36:25 +0000499 break;
sewardj95448072004-11-22 20:19:51 +0000500 case Ity_I8:
sewardj37c31cc2005-04-26 23:49:24 +0000501 tmp1 = assignNew(mce, Ity_I1, unop(Iop_CmpNEZ8, vbits));
sewardj95448072004-11-22 20:19:51 +0000502 break;
503 case Ity_I16:
sewardj37c31cc2005-04-26 23:49:24 +0000504 tmp1 = assignNew(mce, Ity_I1, unop(Iop_CmpNEZ16, vbits));
sewardj95448072004-11-22 20:19:51 +0000505 break;
506 case Ity_I32:
sewardj37c31cc2005-04-26 23:49:24 +0000507 tmp1 = assignNew(mce, Ity_I1, unop(Iop_CmpNEZ32, vbits));
sewardj95448072004-11-22 20:19:51 +0000508 break;
509 case Ity_I64:
sewardj37c31cc2005-04-26 23:49:24 +0000510 tmp1 = assignNew(mce, Ity_I1, unop(Iop_CmpNEZ64, vbits));
sewardj95448072004-11-22 20:19:51 +0000511 break;
sewardj69a13322005-04-23 01:14:51 +0000512 case Ity_I128: {
513 /* Gah. Chop it in half, OR the halves together, and compare
514 that with zero. */
515 IRAtom* tmp2 = assignNew(mce, Ity_I64, unop(Iop_128HIto64, vbits));
516 IRAtom* tmp3 = assignNew(mce, Ity_I64, unop(Iop_128to64, vbits));
517 IRAtom* tmp4 = assignNew(mce, Ity_I64, binop(Iop_Or64, tmp2, tmp3));
518 tmp1 = assignNew(mce, Ity_I1,
sewardj37c31cc2005-04-26 23:49:24 +0000519 unop(Iop_CmpNEZ64, tmp4));
sewardj69a13322005-04-23 01:14:51 +0000520 break;
521 }
sewardj95448072004-11-22 20:19:51 +0000522 default:
sewardj69a13322005-04-23 01:14:51 +0000523 ppIRType(ty);
sewardj95448072004-11-22 20:19:51 +0000524 VG_(tool_panic)("mkPCastTo(1)");
525 }
526 tl_assert(tmp1);
527 /* Now widen up to the dst type. */
528 switch (dst_ty) {
529 case Ity_I1:
530 return tmp1;
531 case Ity_I8:
532 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
533 case Ity_I16:
534 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
535 case Ity_I32:
536 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
537 case Ity_I64:
538 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardja1d93302004-12-12 16:45:06 +0000539 case Ity_V128:
540 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj20d38f22005-02-07 23:50:18 +0000541 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardja1d93302004-12-12 16:45:06 +0000542 return tmp1;
sewardj69a13322005-04-23 01:14:51 +0000543 case Ity_I128:
544 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
545 tmp1 = assignNew(mce, Ity_I128, binop(Iop_64HLto128, tmp1, tmp1));
546 return tmp1;
sewardj95448072004-11-22 20:19:51 +0000547 default:
548 ppIRType(dst_ty);
549 VG_(tool_panic)("mkPCastTo(2)");
550 }
551}
552
sewardjd5204dc2004-12-31 01:16:11 +0000553/* --------- Accurate interpretation of CmpEQ/CmpNE. --------- */
554/*
555 Normally, we can do CmpEQ/CmpNE by doing UifU on the arguments, and
556 PCasting to Ity_U1. However, sometimes it is necessary to be more
557 accurate. The insight is that the result is defined if two
558 corresponding bits can be found, one from each argument, so that
559 both bits are defined but are different -- that makes EQ say "No"
560 and NE say "Yes". Hence, we compute an improvement term and DifD
561 it onto the "normal" (UifU) result.
562
563 The result is:
564
565 PCastTo<1> (
sewardje6f8af42005-07-06 18:48:59 +0000566 -- naive version
567 PCastTo<sz>( UifU<sz>(vxx, vyy) )
568
sewardjd5204dc2004-12-31 01:16:11 +0000569 `DifD<sz>`
sewardje6f8af42005-07-06 18:48:59 +0000570
571 -- improvement term
572 PCastTo<sz>( PCast<sz>( CmpEQ<sz> ( vec, 1...1 ) ) )
sewardjd5204dc2004-12-31 01:16:11 +0000573 )
sewardje6f8af42005-07-06 18:48:59 +0000574
sewardjd5204dc2004-12-31 01:16:11 +0000575 where
576 vec contains 0 (defined) bits where the corresponding arg bits
sewardje6f8af42005-07-06 18:48:59 +0000577 are defined but different, and 1 bits otherwise.
sewardjd5204dc2004-12-31 01:16:11 +0000578
sewardje6f8af42005-07-06 18:48:59 +0000579 vec = Or<sz>( vxx, // 0 iff bit defined
580 vyy, // 0 iff bit defined
581 Not<sz>(Xor<sz>( xx, yy )) // 0 iff bits different
582 )
583
584 If any bit of vec is 0, the result is defined and so the
585 improvement term should produce 0...0, else it should produce
586 1...1.
587
588 Hence require for the improvement term:
589
590 if vec == 1...1 then 1...1 else 0...0
591 ->
592 PCast<sz>( CmpEQ<sz> ( vec, 1...1 ) )
593
594 This was extensively re-analysed and checked on 6 July 05.
sewardjd5204dc2004-12-31 01:16:11 +0000595*/
596static IRAtom* expensiveCmpEQorNE ( MCEnv* mce,
597 IRType ty,
598 IRAtom* vxx, IRAtom* vyy,
599 IRAtom* xx, IRAtom* yy )
600{
sewardje6f8af42005-07-06 18:48:59 +0000601 IRAtom *naive, *vec, *improvement_term;
602 IRAtom *improved, *final_cast, *top;
603 IROp opDIFD, opUIFU, opXOR, opNOT, opCMP, opOR;
sewardjd5204dc2004-12-31 01:16:11 +0000604
605 tl_assert(isShadowAtom(mce,vxx));
606 tl_assert(isShadowAtom(mce,vyy));
607 tl_assert(isOriginalAtom(mce,xx));
608 tl_assert(isOriginalAtom(mce,yy));
609 tl_assert(sameKindedAtoms(vxx,xx));
610 tl_assert(sameKindedAtoms(vyy,yy));
611
612 switch (ty) {
613 case Ity_I32:
sewardje6f8af42005-07-06 18:48:59 +0000614 opOR = Iop_Or32;
sewardjd5204dc2004-12-31 01:16:11 +0000615 opDIFD = Iop_And32;
616 opUIFU = Iop_Or32;
617 opNOT = Iop_Not32;
618 opXOR = Iop_Xor32;
619 opCMP = Iop_CmpEQ32;
620 top = mkU32(0xFFFFFFFF);
621 break;
tomcd986332005-04-26 07:44:48 +0000622 case Ity_I64:
sewardje6f8af42005-07-06 18:48:59 +0000623 opOR = Iop_Or64;
tomcd986332005-04-26 07:44:48 +0000624 opDIFD = Iop_And64;
625 opUIFU = Iop_Or64;
626 opNOT = Iop_Not64;
627 opXOR = Iop_Xor64;
628 opCMP = Iop_CmpEQ64;
sewardj37c31cc2005-04-26 23:49:24 +0000629 top = mkU64(0xFFFFFFFFFFFFFFFFULL);
tomcd986332005-04-26 07:44:48 +0000630 break;
sewardjd5204dc2004-12-31 01:16:11 +0000631 default:
632 VG_(tool_panic)("expensiveCmpEQorNE");
633 }
634
635 naive
636 = mkPCastTo(mce,ty, assignNew(mce, ty, binop(opUIFU, vxx, vyy)));
637
638 vec
639 = assignNew(
640 mce,ty,
sewardje6f8af42005-07-06 18:48:59 +0000641 binop( opOR,
642 assignNew(mce,ty, binop(opOR, vxx, vyy)),
sewardjd5204dc2004-12-31 01:16:11 +0000643 assignNew(
644 mce,ty,
645 unop( opNOT,
646 assignNew(mce,ty, binop(opXOR, xx, yy))))));
647
sewardje6f8af42005-07-06 18:48:59 +0000648 improvement_term
sewardjd5204dc2004-12-31 01:16:11 +0000649 = mkPCastTo( mce,ty, assignNew(mce,Ity_I1, binop(opCMP, vec, top)));
650
651 improved
sewardje6f8af42005-07-06 18:48:59 +0000652 = assignNew( mce,ty, binop(opDIFD, naive, improvement_term) );
sewardjd5204dc2004-12-31 01:16:11 +0000653
654 final_cast
655 = mkPCastTo( mce, Ity_I1, improved );
656
657 return final_cast;
658}
659
sewardj95448072004-11-22 20:19:51 +0000660
661/*------------------------------------------------------------*/
662/*--- Emit a test and complaint if something is undefined. ---*/
663/*------------------------------------------------------------*/
664
665/* Set the annotations on a dirty helper to indicate that the stack
666 pointer and instruction pointers might be read. This is the
667 behaviour of all 'emit-a-complaint' style functions we might
668 call. */
669
670static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
671 di->nFxState = 2;
672 di->fxState[0].fx = Ifx_Read;
673 di->fxState[0].offset = mce->layout->offset_SP;
674 di->fxState[0].size = mce->layout->sizeof_SP;
675 di->fxState[1].fx = Ifx_Read;
676 di->fxState[1].offset = mce->layout->offset_IP;
677 di->fxState[1].size = mce->layout->sizeof_IP;
678}
679
680
681/* Check the supplied **original** atom for undefinedness, and emit a
682 complaint if so. Once that happens, mark it as defined. This is
683 possible because the atom is either a tmp or literal. If it's a
684 tmp, it will be shadowed by a tmp, and so we can set the shadow to
685 be defined. In fact as mentioned above, we will have to allocate a
686 new tmp to carry the new 'defined' shadow value, and update the
687 original->tmp mapping accordingly; we cannot simply assign a new
688 value to an existing shadow tmp as this breaks SSAness -- resulting
689 in the post-instrumentation sanity checker spluttering in disapproval.
690*/
691static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
692{
sewardj7cf97ee2004-11-28 14:25:01 +0000693 IRAtom* vatom;
694 IRType ty;
695 Int sz;
696 IRDirty* di;
697 IRAtom* cond;
698
sewardj95448072004-11-22 20:19:51 +0000699 /* Since the original expression is atomic, there's no duplicated
700 work generated by making multiple V-expressions for it. So we
701 don't really care about the possibility that someone else may
702 also create a V-interpretion for it. */
703 tl_assert(isOriginalAtom(mce, atom));
sewardj7cf97ee2004-11-28 14:25:01 +0000704 vatom = expr2vbits( mce, atom );
sewardj95448072004-11-22 20:19:51 +0000705 tl_assert(isShadowAtom(mce, vatom));
706 tl_assert(sameKindedAtoms(atom, vatom));
707
sewardj7cf97ee2004-11-28 14:25:01 +0000708 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj95448072004-11-22 20:19:51 +0000709
710 /* sz is only used for constructing the error message */
sewardj7cf97ee2004-11-28 14:25:01 +0000711 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardj95448072004-11-22 20:19:51 +0000712
sewardj7cf97ee2004-11-28 14:25:01 +0000713 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardj95448072004-11-22 20:19:51 +0000714 /* cond will be 0 if all defined, and 1 if any not defined. */
715
sewardj95448072004-11-22 20:19:51 +0000716 switch (sz) {
717 case 0:
718 di = unsafeIRDirty_0_N( 0/*regparms*/,
719 "MC_(helperc_value_check0_fail)",
720 &MC_(helperc_value_check0_fail),
721 mkIRExprVec_0()
722 );
723 break;
724 case 1:
725 di = unsafeIRDirty_0_N( 0/*regparms*/,
726 "MC_(helperc_value_check1_fail)",
727 &MC_(helperc_value_check1_fail),
728 mkIRExprVec_0()
729 );
730 break;
731 case 4:
732 di = unsafeIRDirty_0_N( 0/*regparms*/,
733 "MC_(helperc_value_check4_fail)",
734 &MC_(helperc_value_check4_fail),
735 mkIRExprVec_0()
736 );
737 break;
sewardj11bcc4e2005-04-23 22:38:38 +0000738 case 8:
739 di = unsafeIRDirty_0_N( 0/*regparms*/,
740 "MC_(helperc_value_check8_fail)",
741 &MC_(helperc_value_check8_fail),
742 mkIRExprVec_0()
743 );
744 break;
sewardj95448072004-11-22 20:19:51 +0000745 default:
746 di = unsafeIRDirty_0_N( 1/*regparms*/,
747 "MC_(helperc_complain_undef)",
748 &MC_(helperc_complain_undef),
749 mkIRExprVec_1( mkIRExpr_HWord( sz ))
750 );
751 break;
752 }
753 di->guard = cond;
754 setHelperAnns( mce, di );
755 stmt( mce->bb, IRStmt_Dirty(di));
756
757 /* Set the shadow tmp to be defined. First, update the
758 orig->shadow tmp mapping to reflect the fact that this shadow is
759 getting a new value. */
sewardj710d6c22005-03-20 18:55:15 +0000760 tl_assert(isIRAtom(vatom));
sewardj95448072004-11-22 20:19:51 +0000761 /* sameKindedAtoms ... */
762 if (vatom->tag == Iex_Tmp) {
763 tl_assert(atom->tag == Iex_Tmp);
764 newShadowTmp(mce, atom->Iex.Tmp.tmp);
765 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
766 definedOfType(ty));
767 }
768}
769
770
771/*------------------------------------------------------------*/
772/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
773/*------------------------------------------------------------*/
774
775/* Examine the always-defined sections declared in layout to see if
776 the (offset,size) section is within one. Note, is is an error to
777 partially fall into such a region: (offset,size) should either be
778 completely in such a region or completely not-in such a region.
779*/
780static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
781{
782 Int minoffD, maxoffD, i;
783 Int minoff = offset;
784 Int maxoff = minoff + size - 1;
785 tl_assert((minoff & ~0xFFFF) == 0);
786 tl_assert((maxoff & ~0xFFFF) == 0);
787
788 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
789 minoffD = mce->layout->alwaysDefd[i].offset;
790 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
791 tl_assert((minoffD & ~0xFFFF) == 0);
792 tl_assert((maxoffD & ~0xFFFF) == 0);
793
794 if (maxoff < minoffD || maxoffD < minoff)
795 continue; /* no overlap */
796 if (minoff >= minoffD && maxoff <= maxoffD)
797 return True; /* completely contained in an always-defd section */
798
799 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
800 }
801 return False; /* could not find any containing section */
802}
803
804
805/* Generate into bb suitable actions to shadow this Put. If the state
806 slice is marked 'always defined', do nothing. Otherwise, write the
807 supplied V bits to the shadow state. We can pass in either an
808 original atom or a V-atom, but not both. In the former case the
809 relevant V-bits are then generated from the original.
810*/
811static
812void do_shadow_PUT ( MCEnv* mce, Int offset,
813 IRAtom* atom, IRAtom* vatom )
814{
sewardj7cf97ee2004-11-28 14:25:01 +0000815 IRType ty;
sewardj95448072004-11-22 20:19:51 +0000816 if (atom) {
817 tl_assert(!vatom);
818 tl_assert(isOriginalAtom(mce, atom));
819 vatom = expr2vbits( mce, atom );
820 } else {
821 tl_assert(vatom);
822 tl_assert(isShadowAtom(mce, vatom));
823 }
824
sewardj7cf97ee2004-11-28 14:25:01 +0000825 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj95448072004-11-22 20:19:51 +0000826 tl_assert(ty != Ity_I1);
827 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
828 /* later: no ... */
829 /* emit code to emit a complaint if any of the vbits are 1. */
830 /* complainIfUndefined(mce, atom); */
831 } else {
832 /* Do a plain shadow Put. */
833 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
834 }
835}
836
837
838/* Return an expression which contains the V bits corresponding to the
839 given GETI (passed in in pieces).
840*/
841static
842void do_shadow_PUTI ( MCEnv* mce,
843 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
844{
sewardj7cf97ee2004-11-28 14:25:01 +0000845 IRAtom* vatom;
846 IRType ty, tyS;
847 Int arrSize;;
848
sewardj95448072004-11-22 20:19:51 +0000849 tl_assert(isOriginalAtom(mce,atom));
sewardj7cf97ee2004-11-28 14:25:01 +0000850 vatom = expr2vbits( mce, atom );
sewardj95448072004-11-22 20:19:51 +0000851 tl_assert(sameKindedAtoms(atom, vatom));
sewardj7cf97ee2004-11-28 14:25:01 +0000852 ty = descr->elemTy;
853 tyS = shadowType(ty);
854 arrSize = descr->nElems * sizeofIRType(ty);
sewardj95448072004-11-22 20:19:51 +0000855 tl_assert(ty != Ity_I1);
856 tl_assert(isOriginalAtom(mce,ix));
857 complainIfUndefined(mce,ix);
858 if (isAlwaysDefd(mce, descr->base, arrSize)) {
859 /* later: no ... */
860 /* emit code to emit a complaint if any of the vbits are 1. */
861 /* complainIfUndefined(mce, atom); */
862 } else {
863 /* Do a cloned version of the Put that refers to the shadow
864 area. */
865 IRArray* new_descr
866 = mkIRArray( descr->base + mce->layout->total_sizeB,
867 tyS, descr->nElems);
868 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
869 }
870}
871
872
873/* Return an expression which contains the V bits corresponding to the
874 given GET (passed in in pieces).
875*/
876static
877IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
878{
879 IRType tyS = shadowType(ty);
880 tl_assert(ty != Ity_I1);
881 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
882 /* Always defined, return all zeroes of the relevant type */
883 return definedOfType(tyS);
884 } else {
885 /* return a cloned version of the Get that refers to the shadow
886 area. */
887 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
888 }
889}
890
891
892/* Return an expression which contains the V bits corresponding to the
893 given GETI (passed in in pieces).
894*/
895static
896IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
897{
898 IRType ty = descr->elemTy;
899 IRType tyS = shadowType(ty);
900 Int arrSize = descr->nElems * sizeofIRType(ty);
901 tl_assert(ty != Ity_I1);
902 tl_assert(isOriginalAtom(mce,ix));
903 complainIfUndefined(mce,ix);
904 if (isAlwaysDefd(mce, descr->base, arrSize)) {
905 /* Always defined, return all zeroes of the relevant type */
906 return definedOfType(tyS);
907 } else {
908 /* return a cloned version of the Get that refers to the shadow
909 area. */
910 IRArray* new_descr
911 = mkIRArray( descr->base + mce->layout->total_sizeB,
912 tyS, descr->nElems);
913 return IRExpr_GetI( new_descr, ix, bias );
914 }
915}
916
917
918/*------------------------------------------------------------*/
919/*--- Generating approximations for unknown operations, ---*/
920/*--- using lazy-propagate semantics ---*/
921/*------------------------------------------------------------*/
922
923/* Lazy propagation of undefinedness from two values, resulting in the
924 specified shadow type.
925*/
926static
927IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
928{
sewardj95448072004-11-22 20:19:51 +0000929 IRAtom* at;
sewardj37c31cc2005-04-26 23:49:24 +0000930 IRType t1 = typeOfIRExpr(mce->bb->tyenv, va1);
931 IRType t2 = typeOfIRExpr(mce->bb->tyenv, va2);
sewardj95448072004-11-22 20:19:51 +0000932 tl_assert(isShadowAtom(mce,va1));
933 tl_assert(isShadowAtom(mce,va2));
sewardj37c31cc2005-04-26 23:49:24 +0000934
935 /* The general case is inefficient because PCast is an expensive
936 operation. Here are some special cases which use PCast only
937 once rather than twice. */
938
939 /* I64 x I64 -> I64 */
940 if (t1 == Ity_I64 && t2 == Ity_I64 && finalVty == Ity_I64) {
941 if (0) VG_(printf)("mkLazy2: I64 x I64 -> I64\n");
942 at = mkUifU(mce, Ity_I64, va1, va2);
943 at = mkPCastTo(mce, Ity_I64, at);
944 return at;
945 }
946
947 /* I64 x I64 -> I32 */
948 if (t1 == Ity_I64 && t2 == Ity_I64 && finalVty == Ity_I32) {
949 if (0) VG_(printf)("mkLazy2: I64 x I64 -> I32\n");
950 at = mkUifU(mce, Ity_I64, va1, va2);
951 at = mkPCastTo(mce, Ity_I32, at);
952 return at;
953 }
954
955 if (0) {
956 VG_(printf)("mkLazy2 ");
957 ppIRType(t1);
958 VG_(printf)("_");
959 ppIRType(t2);
960 VG_(printf)("_");
961 ppIRType(finalVty);
962 VG_(printf)("\n");
963 }
964
965 /* General case: force everything via 32-bit intermediaries. */
sewardj95448072004-11-22 20:19:51 +0000966 at = mkPCastTo(mce, Ity_I32, va1);
967 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
968 at = mkPCastTo(mce, finalVty, at);
969 return at;
970}
971
972
973/* Do the lazy propagation game from a null-terminated vector of
974 atoms. This is presumably the arguments to a helper call, so the
975 IRCallee info is also supplied in order that we can know which
976 arguments should be ignored (via the .mcx_mask field).
977*/
978static
979IRAtom* mkLazyN ( MCEnv* mce,
980 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
981{
982 Int i;
983 IRAtom* here;
984 IRAtom* curr = definedOfType(Ity_I32);
985 for (i = 0; exprvec[i]; i++) {
986 tl_assert(i < 32);
987 tl_assert(isOriginalAtom(mce, exprvec[i]));
988 /* Only take notice of this arg if the callee's mc-exclusion
989 mask does not say it is to be excluded. */
990 if (cee->mcx_mask & (1<<i)) {
991 /* the arg is to be excluded from definedness checking. Do
992 nothing. */
993 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
994 } else {
995 /* calculate the arg's definedness, and pessimistically merge
996 it in. */
997 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
998 curr = mkUifU32(mce, here, curr);
999 }
1000 }
1001 return mkPCastTo(mce, finalVtype, curr );
1002}
1003
1004
1005/*------------------------------------------------------------*/
1006/*--- Generating expensive sequences for exact carry-chain ---*/
1007/*--- propagation in add/sub and related operations. ---*/
1008/*------------------------------------------------------------*/
1009
1010static
sewardjd5204dc2004-12-31 01:16:11 +00001011IRAtom* expensiveAddSub ( MCEnv* mce,
1012 Bool add,
1013 IRType ty,
1014 IRAtom* qaa, IRAtom* qbb,
1015 IRAtom* aa, IRAtom* bb )
sewardj95448072004-11-22 20:19:51 +00001016{
sewardj7cf97ee2004-11-28 14:25:01 +00001017 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardjd5204dc2004-12-31 01:16:11 +00001018 IROp opAND, opOR, opXOR, opNOT, opADD, opSUB;
sewardj7cf97ee2004-11-28 14:25:01 +00001019
sewardj95448072004-11-22 20:19:51 +00001020 tl_assert(isShadowAtom(mce,qaa));
1021 tl_assert(isShadowAtom(mce,qbb));
1022 tl_assert(isOriginalAtom(mce,aa));
1023 tl_assert(isOriginalAtom(mce,bb));
1024 tl_assert(sameKindedAtoms(qaa,aa));
1025 tl_assert(sameKindedAtoms(qbb,bb));
1026
sewardjd5204dc2004-12-31 01:16:11 +00001027 switch (ty) {
1028 case Ity_I32:
1029 opAND = Iop_And32;
1030 opOR = Iop_Or32;
1031 opXOR = Iop_Xor32;
1032 opNOT = Iop_Not32;
1033 opADD = Iop_Add32;
1034 opSUB = Iop_Sub32;
1035 break;
tomd9774d72005-06-27 08:11:01 +00001036 case Ity_I64:
1037 opAND = Iop_And64;
1038 opOR = Iop_Or64;
1039 opXOR = Iop_Xor64;
1040 opNOT = Iop_Not64;
1041 opADD = Iop_Add64;
1042 opSUB = Iop_Sub64;
1043 break;
sewardjd5204dc2004-12-31 01:16:11 +00001044 default:
1045 VG_(tool_panic)("expensiveAddSub");
1046 }
sewardj95448072004-11-22 20:19:51 +00001047
1048 // a_min = aa & ~qaa
1049 a_min = assignNew(mce,ty,
1050 binop(opAND, aa,
1051 assignNew(mce,ty, unop(opNOT, qaa))));
1052
1053 // b_min = bb & ~qbb
1054 b_min = assignNew(mce,ty,
1055 binop(opAND, bb,
1056 assignNew(mce,ty, unop(opNOT, qbb))));
1057
1058 // a_max = aa | qaa
1059 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1060
1061 // b_max = bb | qbb
1062 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1063
sewardjd5204dc2004-12-31 01:16:11 +00001064 if (add) {
1065 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1066 return
1067 assignNew(mce,ty,
1068 binop( opOR,
1069 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1070 assignNew(mce,ty,
1071 binop( opXOR,
1072 assignNew(mce,ty, binop(opADD, a_min, b_min)),
1073 assignNew(mce,ty, binop(opADD, a_max, b_max))
1074 )
sewardj95448072004-11-22 20:19:51 +00001075 )
sewardjd5204dc2004-12-31 01:16:11 +00001076 )
1077 );
1078 } else {
1079 // result = (qaa | qbb) | ((a_min - b_max) ^ (a_max + b_min))
1080 return
1081 assignNew(mce,ty,
1082 binop( opOR,
1083 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1084 assignNew(mce,ty,
1085 binop( opXOR,
1086 assignNew(mce,ty, binop(opSUB, a_min, b_max)),
1087 assignNew(mce,ty, binop(opSUB, a_max, b_min))
1088 )
1089 )
1090 )
1091 );
1092 }
1093
sewardj95448072004-11-22 20:19:51 +00001094}
1095
1096
1097/*------------------------------------------------------------*/
sewardj3245c912004-12-10 14:58:26 +00001098/*--- Helpers for dealing with vector primops. ---*/
1099/*------------------------------------------------------------*/
1100
sewardja1d93302004-12-12 16:45:06 +00001101/* Vector pessimisation -- pessimise within each lane individually. */
1102
1103static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1104{
1105 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1106}
1107
1108static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1109{
1110 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1111}
1112
1113static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1114{
1115 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1116}
1117
1118static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1119{
1120 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1121}
1122
sewardjacd2e912005-01-13 19:17:06 +00001123static IRAtom* mkPCast32x2 ( MCEnv* mce, IRAtom* at )
1124{
1125 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ32x2, at));
1126}
1127
1128static IRAtom* mkPCast16x4 ( MCEnv* mce, IRAtom* at )
1129{
1130 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ16x4, at));
1131}
1132
1133static IRAtom* mkPCast8x8 ( MCEnv* mce, IRAtom* at )
1134{
1135 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ8x8, at));
1136}
1137
sewardja1d93302004-12-12 16:45:06 +00001138
sewardj3245c912004-12-10 14:58:26 +00001139/* Here's a simple scheme capable of handling ops derived from SSE1
1140 code and while only generating ops that can be efficiently
1141 implemented in SSE1. */
1142
1143/* All-lanes versions are straightforward:
1144
sewardj20d38f22005-02-07 23:50:18 +00001145 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj3245c912004-12-10 14:58:26 +00001146
1147 unary32Fx4(x,y) ==> PCast32x4(x#)
1148
1149 Lowest-lane-only versions are more complex:
1150
sewardj20d38f22005-02-07 23:50:18 +00001151 binary32F0x4(x,y) ==> SetV128lo32(
sewardj3245c912004-12-10 14:58:26 +00001152 x#,
sewardj20d38f22005-02-07 23:50:18 +00001153 PCast32(V128to32(UifUV128(x#,y#)))
sewardj3245c912004-12-10 14:58:26 +00001154 )
1155
1156 This is perhaps not so obvious. In particular, it's faster to
sewardj20d38f22005-02-07 23:50:18 +00001157 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj3245c912004-12-10 14:58:26 +00001158 obvious scheme of taking the bottom 32 bits of each operand
1159 and doing a 32-bit UifU. Basically since UifU is fast and
1160 chopping lanes off vector values is slow.
1161
1162 Finally:
1163
sewardj20d38f22005-02-07 23:50:18 +00001164 unary32F0x4(x) ==> SetV128lo32(
sewardj3245c912004-12-10 14:58:26 +00001165 x#,
sewardj20d38f22005-02-07 23:50:18 +00001166 PCast32(V128to32(x#))
sewardj3245c912004-12-10 14:58:26 +00001167 )
1168
1169 Where:
1170
1171 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1172 PCast32x4(v#) = CmpNEZ32x4(v#)
1173*/
1174
1175static
1176IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1177{
1178 IRAtom* at;
1179 tl_assert(isShadowAtom(mce, vatomX));
1180 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001181 at = mkUifUV128(mce, vatomX, vatomY);
sewardja1d93302004-12-12 16:45:06 +00001182 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
sewardj3245c912004-12-10 14:58:26 +00001183 return at;
1184}
1185
1186static
1187IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1188{
1189 IRAtom* at;
1190 tl_assert(isShadowAtom(mce, vatomX));
sewardja1d93302004-12-12 16:45:06 +00001191 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
sewardj3245c912004-12-10 14:58:26 +00001192 return at;
1193}
1194
1195static
1196IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1197{
1198 IRAtom* at;
1199 tl_assert(isShadowAtom(mce, vatomX));
1200 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001201 at = mkUifUV128(mce, vatomX, vatomY);
1202 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj3245c912004-12-10 14:58:26 +00001203 at = mkPCastTo(mce, Ity_I32, at);
sewardj20d38f22005-02-07 23:50:18 +00001204 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj3245c912004-12-10 14:58:26 +00001205 return at;
1206}
1207
1208static
1209IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1210{
1211 IRAtom* at;
1212 tl_assert(isShadowAtom(mce, vatomX));
sewardj20d38f22005-02-07 23:50:18 +00001213 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj3245c912004-12-10 14:58:26 +00001214 at = mkPCastTo(mce, Ity_I32, at);
sewardj20d38f22005-02-07 23:50:18 +00001215 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj3245c912004-12-10 14:58:26 +00001216 return at;
1217}
1218
sewardj0b070592004-12-10 21:44:22 +00001219/* --- ... and ... 64Fx2 versions of the same ... --- */
1220
1221static
1222IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1223{
1224 IRAtom* at;
1225 tl_assert(isShadowAtom(mce, vatomX));
1226 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001227 at = mkUifUV128(mce, vatomX, vatomY);
sewardja1d93302004-12-12 16:45:06 +00001228 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
sewardj0b070592004-12-10 21:44:22 +00001229 return at;
1230}
1231
1232static
1233IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1234{
1235 IRAtom* at;
1236 tl_assert(isShadowAtom(mce, vatomX));
sewardja1d93302004-12-12 16:45:06 +00001237 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
sewardj0b070592004-12-10 21:44:22 +00001238 return at;
1239}
1240
1241static
1242IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1243{
1244 IRAtom* at;
1245 tl_assert(isShadowAtom(mce, vatomX));
1246 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001247 at = mkUifUV128(mce, vatomX, vatomY);
1248 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj0b070592004-12-10 21:44:22 +00001249 at = mkPCastTo(mce, Ity_I64, at);
sewardj20d38f22005-02-07 23:50:18 +00001250 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj0b070592004-12-10 21:44:22 +00001251 return at;
1252}
1253
1254static
1255IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1256{
1257 IRAtom* at;
1258 tl_assert(isShadowAtom(mce, vatomX));
sewardj20d38f22005-02-07 23:50:18 +00001259 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj0b070592004-12-10 21:44:22 +00001260 at = mkPCastTo(mce, Ity_I64, at);
sewardj20d38f22005-02-07 23:50:18 +00001261 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj0b070592004-12-10 21:44:22 +00001262 return at;
1263}
1264
sewardja1d93302004-12-12 16:45:06 +00001265/* --- --- Vector saturated narrowing --- --- */
1266
1267/* This is quite subtle. What to do is simple:
1268
1269 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1270
1271 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1272
1273 Why this is right is not so simple. Consider a lane in the args,
1274 vatom1 or 2, doesn't matter.
1275
1276 After the PCast, that lane is all 0s (defined) or all
1277 1s(undefined).
1278
1279 Both signed and unsigned saturating narrowing of all 0s produces
1280 all 0s, which is what we want.
1281
1282 The all-1s case is more complex. Unsigned narrowing interprets an
1283 all-1s input as the largest unsigned integer, and so produces all
1284 1s as a result since that is the largest unsigned value at the
1285 smaller width.
1286
1287 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1288 to -1, so we still wind up with all 1s at the smaller width.
1289
1290 So: In short, pessimise the args, then apply the original narrowing
1291 op.
1292*/
1293static
sewardj20d38f22005-02-07 23:50:18 +00001294IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardja1d93302004-12-12 16:45:06 +00001295 IRAtom* vatom1, IRAtom* vatom2)
1296{
1297 IRAtom *at1, *at2, *at3;
1298 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1299 switch (narrow_op) {
1300 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1301 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1302 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardj20d38f22005-02-07 23:50:18 +00001303 default: VG_(tool_panic)("vectorNarrowV128");
sewardja1d93302004-12-12 16:45:06 +00001304 }
1305 tl_assert(isShadowAtom(mce,vatom1));
1306 tl_assert(isShadowAtom(mce,vatom2));
1307 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1308 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1309 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1310 return at3;
1311}
1312
sewardjacd2e912005-01-13 19:17:06 +00001313static
1314IRAtom* vectorNarrow64 ( MCEnv* mce, IROp narrow_op,
1315 IRAtom* vatom1, IRAtom* vatom2)
1316{
1317 IRAtom *at1, *at2, *at3;
1318 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1319 switch (narrow_op) {
1320 case Iop_QNarrow32Sx2: pcast = mkPCast32x2; break;
1321 case Iop_QNarrow16Sx4: pcast = mkPCast16x4; break;
1322 case Iop_QNarrow16Ux4: pcast = mkPCast16x4; break;
1323 default: VG_(tool_panic)("vectorNarrow64");
1324 }
1325 tl_assert(isShadowAtom(mce,vatom1));
1326 tl_assert(isShadowAtom(mce,vatom2));
1327 at1 = assignNew(mce, Ity_I64, pcast(mce, vatom1));
1328 at2 = assignNew(mce, Ity_I64, pcast(mce, vatom2));
1329 at3 = assignNew(mce, Ity_I64, binop(narrow_op, at1, at2));
1330 return at3;
1331}
1332
sewardja1d93302004-12-12 16:45:06 +00001333
1334/* --- --- Vector integer arithmetic --- --- */
1335
1336/* Simple ... UifU the args and per-lane pessimise the results. */
sewardjacd2e912005-01-13 19:17:06 +00001337
sewardj20d38f22005-02-07 23:50:18 +00001338/* --- V128-bit versions --- */
sewardjacd2e912005-01-13 19:17:06 +00001339
sewardja1d93302004-12-12 16:45:06 +00001340static
1341IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1342{
1343 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001344 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001345 at = mkPCast8x16(mce, at);
1346 return at;
1347}
1348
1349static
1350IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1351{
1352 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001353 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001354 at = mkPCast16x8(mce, at);
1355 return at;
1356}
1357
1358static
1359IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1360{
1361 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001362 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001363 at = mkPCast32x4(mce, at);
1364 return at;
1365}
1366
1367static
1368IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1369{
1370 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001371 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001372 at = mkPCast64x2(mce, at);
1373 return at;
1374}
sewardj3245c912004-12-10 14:58:26 +00001375
sewardjacd2e912005-01-13 19:17:06 +00001376/* --- 64-bit versions --- */
1377
1378static
1379IRAtom* binary8Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1380{
1381 IRAtom* at;
1382 at = mkUifU64(mce, vatom1, vatom2);
1383 at = mkPCast8x8(mce, at);
1384 return at;
1385}
1386
1387static
1388IRAtom* binary16Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1389{
1390 IRAtom* at;
1391 at = mkUifU64(mce, vatom1, vatom2);
1392 at = mkPCast16x4(mce, at);
1393 return at;
1394}
1395
1396static
1397IRAtom* binary32Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1398{
1399 IRAtom* at;
1400 at = mkUifU64(mce, vatom1, vatom2);
1401 at = mkPCast32x2(mce, at);
1402 return at;
1403}
1404
sewardj3245c912004-12-10 14:58:26 +00001405
1406/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00001407/*--- Generate shadow values from all kinds of IRExprs. ---*/
1408/*------------------------------------------------------------*/
1409
1410static
1411IRAtom* expr2vbits_Binop ( MCEnv* mce,
1412 IROp op,
1413 IRAtom* atom1, IRAtom* atom2 )
1414{
1415 IRType and_or_ty;
1416 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1417 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1418 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1419
1420 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1421 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1422
1423 tl_assert(isOriginalAtom(mce,atom1));
1424 tl_assert(isOriginalAtom(mce,atom2));
1425 tl_assert(isShadowAtom(mce,vatom1));
1426 tl_assert(isShadowAtom(mce,vatom2));
1427 tl_assert(sameKindedAtoms(atom1,vatom1));
1428 tl_assert(sameKindedAtoms(atom2,vatom2));
1429 switch (op) {
1430
sewardjacd2e912005-01-13 19:17:06 +00001431 /* 64-bit SIMD */
1432
1433 case Iop_ShrN16x4:
1434 case Iop_ShrN32x2:
1435 case Iop_SarN16x4:
1436 case Iop_SarN32x2:
1437 case Iop_ShlN16x4:
1438 case Iop_ShlN32x2:
1439 /* Same scheme as with all other shifts. */
1440 complainIfUndefined(mce, atom2);
1441 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1442
1443 case Iop_QNarrow32Sx2:
1444 case Iop_QNarrow16Sx4:
1445 case Iop_QNarrow16Ux4:
1446 return vectorNarrow64(mce, op, vatom1, vatom2);
1447
1448 case Iop_Min8Ux8:
1449 case Iop_Max8Ux8:
1450 case Iop_Avg8Ux8:
1451 case Iop_QSub8Sx8:
1452 case Iop_QSub8Ux8:
1453 case Iop_Sub8x8:
1454 case Iop_CmpGT8Sx8:
1455 case Iop_CmpEQ8x8:
1456 case Iop_QAdd8Sx8:
1457 case Iop_QAdd8Ux8:
1458 case Iop_Add8x8:
1459 return binary8Ix8(mce, vatom1, vatom2);
1460
1461 case Iop_Min16Sx4:
1462 case Iop_Max16Sx4:
1463 case Iop_Avg16Ux4:
1464 case Iop_QSub16Ux4:
1465 case Iop_QSub16Sx4:
1466 case Iop_Sub16x4:
1467 case Iop_Mul16x4:
1468 case Iop_MulHi16Sx4:
1469 case Iop_MulHi16Ux4:
1470 case Iop_CmpGT16Sx4:
1471 case Iop_CmpEQ16x4:
1472 case Iop_QAdd16Sx4:
1473 case Iop_QAdd16Ux4:
1474 case Iop_Add16x4:
1475 return binary16Ix4(mce, vatom1, vatom2);
1476
1477 case Iop_Sub32x2:
1478 case Iop_CmpGT32Sx2:
1479 case Iop_CmpEQ32x2:
1480 case Iop_Add32x2:
1481 return binary32Ix2(mce, vatom1, vatom2);
1482
1483 /* 64-bit data-steering */
1484 case Iop_InterleaveLO32x2:
1485 case Iop_InterleaveLO16x4:
1486 case Iop_InterleaveLO8x8:
1487 case Iop_InterleaveHI32x2:
1488 case Iop_InterleaveHI16x4:
1489 case Iop_InterleaveHI8x8:
1490 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
1491
sewardj20d38f22005-02-07 23:50:18 +00001492 /* V128-bit SIMD */
sewardj0b070592004-12-10 21:44:22 +00001493
sewardja1d93302004-12-12 16:45:06 +00001494 case Iop_ShrN16x8:
1495 case Iop_ShrN32x4:
1496 case Iop_ShrN64x2:
1497 case Iop_SarN16x8:
1498 case Iop_SarN32x4:
1499 case Iop_ShlN16x8:
1500 case Iop_ShlN32x4:
1501 case Iop_ShlN64x2:
1502 /* Same scheme as with all other shifts. */
1503 complainIfUndefined(mce, atom2);
1504 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1505
1506 case Iop_QSub8Ux16:
1507 case Iop_QSub8Sx16:
1508 case Iop_Sub8x16:
1509 case Iop_Min8Ux16:
1510 case Iop_Max8Ux16:
1511 case Iop_CmpGT8Sx16:
1512 case Iop_CmpEQ8x16:
1513 case Iop_Avg8Ux16:
1514 case Iop_QAdd8Ux16:
1515 case Iop_QAdd8Sx16:
1516 case Iop_Add8x16:
1517 return binary8Ix16(mce, vatom1, vatom2);
1518
1519 case Iop_QSub16Ux8:
1520 case Iop_QSub16Sx8:
1521 case Iop_Sub16x8:
1522 case Iop_Mul16x8:
1523 case Iop_MulHi16Sx8:
1524 case Iop_MulHi16Ux8:
1525 case Iop_Min16Sx8:
1526 case Iop_Max16Sx8:
1527 case Iop_CmpGT16Sx8:
1528 case Iop_CmpEQ16x8:
1529 case Iop_Avg16Ux8:
1530 case Iop_QAdd16Ux8:
1531 case Iop_QAdd16Sx8:
1532 case Iop_Add16x8:
1533 return binary16Ix8(mce, vatom1, vatom2);
1534
1535 case Iop_Sub32x4:
1536 case Iop_CmpGT32Sx4:
1537 case Iop_CmpEQ32x4:
1538 case Iop_Add32x4:
1539 return binary32Ix4(mce, vatom1, vatom2);
1540
1541 case Iop_Sub64x2:
1542 case Iop_Add64x2:
1543 return binary64Ix2(mce, vatom1, vatom2);
1544
1545 case Iop_QNarrow32Sx4:
1546 case Iop_QNarrow16Sx8:
1547 case Iop_QNarrow16Ux8:
sewardj20d38f22005-02-07 23:50:18 +00001548 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001549
sewardj0b070592004-12-10 21:44:22 +00001550 case Iop_Sub64Fx2:
1551 case Iop_Mul64Fx2:
1552 case Iop_Min64Fx2:
1553 case Iop_Max64Fx2:
1554 case Iop_Div64Fx2:
1555 case Iop_CmpLT64Fx2:
1556 case Iop_CmpLE64Fx2:
1557 case Iop_CmpEQ64Fx2:
1558 case Iop_Add64Fx2:
1559 return binary64Fx2(mce, vatom1, vatom2);
1560
1561 case Iop_Sub64F0x2:
1562 case Iop_Mul64F0x2:
1563 case Iop_Min64F0x2:
1564 case Iop_Max64F0x2:
1565 case Iop_Div64F0x2:
1566 case Iop_CmpLT64F0x2:
1567 case Iop_CmpLE64F0x2:
1568 case Iop_CmpEQ64F0x2:
1569 case Iop_Add64F0x2:
1570 return binary64F0x2(mce, vatom1, vatom2);
1571
sewardj170ee212004-12-10 18:57:51 +00001572 case Iop_Sub32Fx4:
1573 case Iop_Mul32Fx4:
1574 case Iop_Min32Fx4:
1575 case Iop_Max32Fx4:
1576 case Iop_Div32Fx4:
1577 case Iop_CmpLT32Fx4:
1578 case Iop_CmpLE32Fx4:
1579 case Iop_CmpEQ32Fx4:
sewardj3245c912004-12-10 14:58:26 +00001580 case Iop_Add32Fx4:
1581 return binary32Fx4(mce, vatom1, vatom2);
1582
sewardj170ee212004-12-10 18:57:51 +00001583 case Iop_Sub32F0x4:
1584 case Iop_Mul32F0x4:
1585 case Iop_Min32F0x4:
1586 case Iop_Max32F0x4:
1587 case Iop_Div32F0x4:
1588 case Iop_CmpLT32F0x4:
1589 case Iop_CmpLE32F0x4:
1590 case Iop_CmpEQ32F0x4:
1591 case Iop_Add32F0x4:
1592 return binary32F0x4(mce, vatom1, vatom2);
1593
sewardj20d38f22005-02-07 23:50:18 +00001594 /* V128-bit data-steering */
1595 case Iop_SetV128lo32:
1596 case Iop_SetV128lo64:
1597 case Iop_64HLtoV128:
sewardja1d93302004-12-12 16:45:06 +00001598 case Iop_InterleaveLO64x2:
1599 case Iop_InterleaveLO32x4:
1600 case Iop_InterleaveLO16x8:
1601 case Iop_InterleaveLO8x16:
1602 case Iop_InterleaveHI64x2:
1603 case Iop_InterleaveHI32x4:
1604 case Iop_InterleaveHI16x8:
1605 case Iop_InterleaveHI8x16:
sewardj170ee212004-12-10 18:57:51 +00001606 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1607
sewardj69a13322005-04-23 01:14:51 +00001608 /* I128-bit data-steering */
1609 case Iop_64HLto128:
1610 return assignNew(mce, Ity_I128, binop(op, vatom1, vatom2));
1611
sewardj3245c912004-12-10 14:58:26 +00001612 /* Scalar floating point */
1613
sewardj95448072004-11-22 20:19:51 +00001614 case Iop_RoundF64:
1615 case Iop_F64toI64:
sewardje9e16d32004-12-10 13:17:55 +00001616 case Iop_I64toF64:
1617 /* First arg is I32 (rounding mode), second is F64 or I64
1618 (data). */
sewardj95448072004-11-22 20:19:51 +00001619 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1620
1621 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1622 /* Takes two F64 args. */
1623 case Iop_F64toI32:
sewardje9e16d32004-12-10 13:17:55 +00001624 case Iop_F64toF32:
sewardj95448072004-11-22 20:19:51 +00001625 /* First arg is I32 (rounding mode), second is F64 (data). */
1626 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1627
1628 case Iop_F64toI16:
1629 /* First arg is I32 (rounding mode), second is F64 (data). */
1630 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1631
1632 case Iop_ScaleF64:
1633 case Iop_Yl2xF64:
1634 case Iop_Yl2xp1F64:
1635 case Iop_PRemF64:
sewardj96403eb2005-04-01 20:20:12 +00001636 case Iop_PRem1F64:
sewardj95448072004-11-22 20:19:51 +00001637 case Iop_AtanF64:
1638 case Iop_AddF64:
1639 case Iop_DivF64:
1640 case Iop_SubF64:
1641 case Iop_MulF64:
1642 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1643
1644 case Iop_CmpF64:
1645 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1646
1647 /* non-FP after here */
1648
1649 case Iop_DivModU64to32:
1650 case Iop_DivModS64to32:
1651 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1652
sewardj69a13322005-04-23 01:14:51 +00001653 case Iop_DivModU128to64:
1654 case Iop_DivModS128to64:
1655 return mkLazy2(mce, Ity_I128, vatom1, vatom2);
1656
sewardj95448072004-11-22 20:19:51 +00001657 case Iop_16HLto32:
sewardj170ee212004-12-10 18:57:51 +00001658 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardj95448072004-11-22 20:19:51 +00001659 case Iop_32HLto64:
sewardj170ee212004-12-10 18:57:51 +00001660 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardj95448072004-11-22 20:19:51 +00001661
sewardj6cf40ff2005-04-20 22:31:26 +00001662 case Iop_MullS64:
1663 case Iop_MullU64: {
1664 IRAtom* vLo64 = mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
1665 IRAtom* vHi64 = mkPCastTo(mce, Ity_I64, vLo64);
1666 return assignNew(mce, Ity_I128, binop(Iop_64HLto128, vHi64, vLo64));
1667 }
1668
sewardj95448072004-11-22 20:19:51 +00001669 case Iop_MullS32:
1670 case Iop_MullU32: {
1671 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1672 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1673 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1674 }
1675
1676 case Iop_MullS16:
1677 case Iop_MullU16: {
1678 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1679 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1680 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1681 }
1682
1683 case Iop_MullS8:
1684 case Iop_MullU8: {
1685 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1686 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1687 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1688 }
1689
cerion9e591082005-06-23 15:28:34 +00001690 case Iop_DivS32:
1691 case Iop_DivU32:
1692 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1693
sewardj95448072004-11-22 20:19:51 +00001694 case Iop_Add32:
sewardjd5204dc2004-12-31 01:16:11 +00001695 if (mce->bogusLiterals)
1696 return expensiveAddSub(mce,True,Ity_I32,
1697 vatom1,vatom2, atom1,atom2);
1698 else
1699 goto cheap_AddSub32;
sewardj95448072004-11-22 20:19:51 +00001700 case Iop_Sub32:
sewardjd5204dc2004-12-31 01:16:11 +00001701 if (mce->bogusLiterals)
1702 return expensiveAddSub(mce,False,Ity_I32,
1703 vatom1,vatom2, atom1,atom2);
1704 else
1705 goto cheap_AddSub32;
1706
1707 cheap_AddSub32:
sewardj95448072004-11-22 20:19:51 +00001708 case Iop_Mul32:
sewardj463b3d92005-07-18 11:41:15 +00001709 case Iop_CmpORD32S:
1710 case Iop_CmpORD32U:
sewardj95448072004-11-22 20:19:51 +00001711 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1712
sewardj681be302005-01-15 20:43:58 +00001713 case Iop_Add64:
tomd9774d72005-06-27 08:11:01 +00001714 if (mce->bogusLiterals)
1715 return expensiveAddSub(mce,True,Ity_I64,
1716 vatom1,vatom2, atom1,atom2);
1717 else
1718 goto cheap_AddSub64;
sewardj681be302005-01-15 20:43:58 +00001719 case Iop_Sub64:
tomd9774d72005-06-27 08:11:01 +00001720 if (mce->bogusLiterals)
1721 return expensiveAddSub(mce,False,Ity_I64,
1722 vatom1,vatom2, atom1,atom2);
1723 else
1724 goto cheap_AddSub64;
1725
1726 cheap_AddSub64:
1727 case Iop_Mul64:
sewardj681be302005-01-15 20:43:58 +00001728 return mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
1729
sewardj95448072004-11-22 20:19:51 +00001730 case Iop_Mul16:
1731 case Iop_Add16:
1732 case Iop_Sub16:
1733 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1734
1735 case Iop_Sub8:
1736 case Iop_Add8:
1737 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1738
sewardj69a13322005-04-23 01:14:51 +00001739 case Iop_CmpEQ64:
sewardje6f8af42005-07-06 18:48:59 +00001740 case Iop_CmpNE64:
sewardj69a13322005-04-23 01:14:51 +00001741 if (mce->bogusLiterals)
1742 return expensiveCmpEQorNE(mce,Ity_I64, vatom1,vatom2, atom1,atom2 );
1743 else
1744 goto cheap_cmp64;
1745 cheap_cmp64:
tomcd986332005-04-26 07:44:48 +00001746 case Iop_CmpLE64S: case Iop_CmpLE64U:
1747 case Iop_CmpLT64U: case Iop_CmpLT64S:
sewardj69a13322005-04-23 01:14:51 +00001748 return mkPCastTo(mce, Ity_I1, mkUifU64(mce, vatom1,vatom2));
1749
sewardjd5204dc2004-12-31 01:16:11 +00001750 case Iop_CmpEQ32:
sewardje6f8af42005-07-06 18:48:59 +00001751 case Iop_CmpNE32:
sewardjd5204dc2004-12-31 01:16:11 +00001752 if (mce->bogusLiterals)
1753 return expensiveCmpEQorNE(mce,Ity_I32, vatom1,vatom2, atom1,atom2 );
1754 else
1755 goto cheap_cmp32;
sewardjd5204dc2004-12-31 01:16:11 +00001756 cheap_cmp32:
sewardj95448072004-11-22 20:19:51 +00001757 case Iop_CmpLE32S: case Iop_CmpLE32U:
1758 case Iop_CmpLT32U: case Iop_CmpLT32S:
sewardj95448072004-11-22 20:19:51 +00001759 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
1760
1761 case Iop_CmpEQ16: case Iop_CmpNE16:
1762 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
1763
1764 case Iop_CmpEQ8: case Iop_CmpNE8:
1765 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
1766
1767 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1768 /* Complain if the shift amount is undefined. Then simply
1769 shift the first arg's V bits by the real shift amount. */
1770 complainIfUndefined(mce, atom2);
1771 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1772
sewardjdb67f5f2004-12-14 01:15:31 +00001773 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardj95448072004-11-22 20:19:51 +00001774 /* Same scheme as with 32-bit shifts. */
1775 complainIfUndefined(mce, atom2);
1776 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1777
1778 case Iop_Shl8: case Iop_Shr8:
1779 /* Same scheme as with 32-bit shifts. */
1780 complainIfUndefined(mce, atom2);
1781 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1782
sewardj69a13322005-04-23 01:14:51 +00001783 case Iop_Shl64: case Iop_Shr64: case Iop_Sar64:
sewardj95448072004-11-22 20:19:51 +00001784 /* Same scheme as with 32-bit shifts. */
1785 complainIfUndefined(mce, atom2);
1786 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1787
sewardj20d38f22005-02-07 23:50:18 +00001788 case Iop_AndV128:
1789 uifu = mkUifUV128; difd = mkDifDV128;
1790 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj7010f6e2004-12-10 13:35:22 +00001791 case Iop_And64:
1792 uifu = mkUifU64; difd = mkDifD64;
1793 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardj95448072004-11-22 20:19:51 +00001794 case Iop_And32:
1795 uifu = mkUifU32; difd = mkDifD32;
1796 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
1797 case Iop_And16:
1798 uifu = mkUifU16; difd = mkDifD16;
1799 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
1800 case Iop_And8:
1801 uifu = mkUifU8; difd = mkDifD8;
1802 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1803
sewardj20d38f22005-02-07 23:50:18 +00001804 case Iop_OrV128:
1805 uifu = mkUifUV128; difd = mkDifDV128;
1806 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj7010f6e2004-12-10 13:35:22 +00001807 case Iop_Or64:
1808 uifu = mkUifU64; difd = mkDifD64;
1809 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardj95448072004-11-22 20:19:51 +00001810 case Iop_Or32:
1811 uifu = mkUifU32; difd = mkDifD32;
1812 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1813 case Iop_Or16:
1814 uifu = mkUifU16; difd = mkDifD16;
1815 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1816 case Iop_Or8:
1817 uifu = mkUifU8; difd = mkDifD8;
1818 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1819
1820 do_And_Or:
1821 return
1822 assignNew(
1823 mce,
1824 and_or_ty,
1825 difd(mce, uifu(mce, vatom1, vatom2),
1826 difd(mce, improve(mce, atom1, vatom1),
1827 improve(mce, atom2, vatom2) ) ) );
1828
1829 case Iop_Xor8:
1830 return mkUifU8(mce, vatom1, vatom2);
1831 case Iop_Xor16:
1832 return mkUifU16(mce, vatom1, vatom2);
1833 case Iop_Xor32:
1834 return mkUifU32(mce, vatom1, vatom2);
sewardj7010f6e2004-12-10 13:35:22 +00001835 case Iop_Xor64:
1836 return mkUifU64(mce, vatom1, vatom2);
sewardj20d38f22005-02-07 23:50:18 +00001837 case Iop_XorV128:
1838 return mkUifUV128(mce, vatom1, vatom2);
njn25e49d8e72002-09-23 09:36:25 +00001839
1840 default:
sewardj95448072004-11-22 20:19:51 +00001841 ppIROp(op);
1842 VG_(tool_panic)("memcheck:expr2vbits_Binop");
njn25e49d8e72002-09-23 09:36:25 +00001843 }
njn25e49d8e72002-09-23 09:36:25 +00001844}
1845
njn25e49d8e72002-09-23 09:36:25 +00001846
sewardj95448072004-11-22 20:19:51 +00001847static
1848IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1849{
1850 IRAtom* vatom = expr2vbits( mce, atom );
1851 tl_assert(isOriginalAtom(mce,atom));
1852 switch (op) {
1853
sewardj0b070592004-12-10 21:44:22 +00001854 case Iop_Sqrt64Fx2:
1855 return unary64Fx2(mce, vatom);
1856
1857 case Iop_Sqrt64F0x2:
1858 return unary64F0x2(mce, vatom);
1859
sewardj170ee212004-12-10 18:57:51 +00001860 case Iop_Sqrt32Fx4:
1861 case Iop_RSqrt32Fx4:
1862 case Iop_Recip32Fx4:
1863 return unary32Fx4(mce, vatom);
1864
1865 case Iop_Sqrt32F0x4:
1866 case Iop_RSqrt32F0x4:
1867 case Iop_Recip32F0x4:
1868 return unary32F0x4(mce, vatom);
1869
sewardj20d38f22005-02-07 23:50:18 +00001870 case Iop_32UtoV128:
1871 case Iop_64UtoV128:
sewardj170ee212004-12-10 18:57:51 +00001872 return assignNew(mce, Ity_V128, unop(op, vatom));
1873
sewardj95448072004-11-22 20:19:51 +00001874 case Iop_F32toF64:
1875 case Iop_I32toF64:
sewardj95448072004-11-22 20:19:51 +00001876 case Iop_NegF64:
1877 case Iop_SinF64:
1878 case Iop_CosF64:
1879 case Iop_TanF64:
1880 case Iop_SqrtF64:
1881 case Iop_AbsF64:
1882 case Iop_2xm1F64:
sewardj39cc7352005-06-09 21:31:55 +00001883 case Iop_Clz64:
1884 case Iop_Ctz64:
sewardj95448072004-11-22 20:19:51 +00001885 return mkPCastTo(mce, Ity_I64, vatom);
1886
sewardj95448072004-11-22 20:19:51 +00001887 case Iop_Clz32:
1888 case Iop_Ctz32:
1889 return mkPCastTo(mce, Ity_I32, vatom);
1890
sewardjd9dbc192005-04-27 11:40:27 +00001891 case Iop_1Uto64:
1892 case Iop_8Uto64:
1893 case Iop_8Sto64:
1894 case Iop_16Uto64:
1895 case Iop_16Sto64:
sewardj95448072004-11-22 20:19:51 +00001896 case Iop_32Sto64:
1897 case Iop_32Uto64:
sewardj20d38f22005-02-07 23:50:18 +00001898 case Iop_V128to64:
1899 case Iop_V128HIto64:
sewardj6cf40ff2005-04-20 22:31:26 +00001900 case Iop_128HIto64:
1901 case Iop_128to64:
sewardj95448072004-11-22 20:19:51 +00001902 return assignNew(mce, Ity_I64, unop(op, vatom));
1903
1904 case Iop_64to32:
1905 case Iop_64HIto32:
1906 case Iop_1Uto32:
sewardj463b3d92005-07-18 11:41:15 +00001907 case Iop_1Sto32:
sewardj95448072004-11-22 20:19:51 +00001908 case Iop_8Uto32:
1909 case Iop_16Uto32:
1910 case Iop_16Sto32:
1911 case Iop_8Sto32:
cerionfafaa0d2005-09-12 22:29:38 +00001912 case Iop_V128to32:
sewardj95448072004-11-22 20:19:51 +00001913 return assignNew(mce, Ity_I32, unop(op, vatom));
1914
1915 case Iop_8Sto16:
1916 case Iop_8Uto16:
1917 case Iop_32to16:
1918 case Iop_32HIto16:
sewardjd9dbc192005-04-27 11:40:27 +00001919 case Iop_64to16:
sewardj95448072004-11-22 20:19:51 +00001920 return assignNew(mce, Ity_I16, unop(op, vatom));
1921
1922 case Iop_1Uto8:
1923 case Iop_16to8:
1924 case Iop_32to8:
sewardjd9dbc192005-04-27 11:40:27 +00001925 case Iop_64to8:
sewardj95448072004-11-22 20:19:51 +00001926 return assignNew(mce, Ity_I8, unop(op, vatom));
1927
1928 case Iop_32to1:
1929 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
1930
sewardjd9dbc192005-04-27 11:40:27 +00001931 case Iop_64to1:
1932 return assignNew(mce, Ity_I1, unop(Iop_64to1, vatom));
1933
sewardj95448072004-11-22 20:19:51 +00001934 case Iop_ReinterpF64asI64:
1935 case Iop_ReinterpI64asF64:
sewardj0b070592004-12-10 21:44:22 +00001936 case Iop_ReinterpI32asF32:
sewardj20d38f22005-02-07 23:50:18 +00001937 case Iop_NotV128:
sewardj7010f6e2004-12-10 13:35:22 +00001938 case Iop_Not64:
sewardj95448072004-11-22 20:19:51 +00001939 case Iop_Not32:
1940 case Iop_Not16:
1941 case Iop_Not8:
1942 case Iop_Not1:
1943 return vatom;
sewardj7010f6e2004-12-10 13:35:22 +00001944
sewardje53bd992005-05-03 12:22:00 +00001945 /* Neg* really fall under the Add/Sub banner, and as such you
1946 might think would qualify for the 'expensive add/sub'
1947 treatment. However, in this case since the implied literal
1948 is zero (0 - arg), we just do the cheap thing anyway. */
1949 case Iop_Neg8:
1950 return mkLeft8(mce, vatom);
1951 case Iop_Neg16:
1952 return mkLeft16(mce, vatom);
1953 case Iop_Neg32:
1954 return mkLeft32(mce, vatom);
1955
sewardj95448072004-11-22 20:19:51 +00001956 default:
1957 ppIROp(op);
1958 VG_(tool_panic)("memcheck:expr2vbits_Unop");
1959 }
1960}
1961
1962
sewardj170ee212004-12-10 18:57:51 +00001963/* Worker function; do not call directly. */
sewardj95448072004-11-22 20:19:51 +00001964static
sewardj2e595852005-06-30 23:33:37 +00001965IRAtom* expr2vbits_Load_WRK ( MCEnv* mce,
1966 IREndness end, IRType ty,
1967 IRAtom* addr, UInt bias )
sewardj95448072004-11-22 20:19:51 +00001968{
1969 void* helper;
1970 Char* hname;
1971 IRDirty* di;
1972 IRTemp datavbits;
1973 IRAtom* addrAct;
1974
1975 tl_assert(isOriginalAtom(mce,addr));
sewardj2e595852005-06-30 23:33:37 +00001976 tl_assert(end == Iend_LE || end == Iend_BE);
sewardj95448072004-11-22 20:19:51 +00001977
1978 /* First, emit a definedness test for the address. This also sets
1979 the address (shadow) to 'defined' following the test. */
1980 complainIfUndefined( mce, addr );
1981
1982 /* Now cook up a call to the relevant helper function, to read the
1983 data V bits from shadow memory. */
1984 ty = shadowType(ty);
sewardj2e595852005-06-30 23:33:37 +00001985
1986 if (end == Iend_LE) {
1987 switch (ty) {
1988 case Ity_I64: helper = &MC_(helperc_LOADV8le);
1989 hname = "MC_(helperc_LOADV8le)";
1990 break;
1991 case Ity_I32: helper = &MC_(helperc_LOADV4le);
1992 hname = "MC_(helperc_LOADV4le)";
1993 break;
1994 case Ity_I16: helper = &MC_(helperc_LOADV2le);
1995 hname = "MC_(helperc_LOADV2le)";
1996 break;
sewardj8cf88b72005-07-08 01:29:33 +00001997 case Ity_I8: helper = &MC_(helperc_LOADV1);
1998 hname = "MC_(helperc_LOADV1)";
sewardj2e595852005-06-30 23:33:37 +00001999 break;
2000 default: ppIRType(ty);
2001 VG_(tool_panic)("memcheck:do_shadow_Load(LE)");
2002 }
2003 } else {
sewardj8cf88b72005-07-08 01:29:33 +00002004 switch (ty) {
2005 case Ity_I64: helper = &MC_(helperc_LOADV8be);
2006 hname = "MC_(helperc_LOADV8be)";
2007 break;
2008 case Ity_I32: helper = &MC_(helperc_LOADV4be);
2009 hname = "MC_(helperc_LOADV4be)";
2010 break;
2011 case Ity_I16: helper = &MC_(helperc_LOADV2be);
2012 hname = "MC_(helperc_LOADV2be)";
2013 break;
2014 case Ity_I8: helper = &MC_(helperc_LOADV1);
2015 hname = "MC_(helperc_LOADV1)";
2016 break;
2017 default: ppIRType(ty);
2018 VG_(tool_panic)("memcheck:do_shadow_Load(BE)");
2019 }
sewardj95448072004-11-22 20:19:51 +00002020 }
2021
2022 /* Generate the actual address into addrAct. */
2023 if (bias == 0) {
2024 addrAct = addr;
2025 } else {
sewardj7cf97ee2004-11-28 14:25:01 +00002026 IROp mkAdd;
2027 IRAtom* eBias;
sewardj95448072004-11-22 20:19:51 +00002028 IRType tyAddr = mce->hWordTy;
2029 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj7cf97ee2004-11-28 14:25:01 +00002030 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2031 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj95448072004-11-22 20:19:51 +00002032 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2033 }
2034
2035 /* We need to have a place to park the V bits we're just about to
2036 read. */
2037 datavbits = newIRTemp(mce->bb->tyenv, ty);
2038 di = unsafeIRDirty_1_N( datavbits,
2039 1/*regparms*/, hname, helper,
2040 mkIRExprVec_1( addrAct ));
2041 setHelperAnns( mce, di );
2042 stmt( mce->bb, IRStmt_Dirty(di) );
2043
2044 return mkexpr(datavbits);
2045}
2046
2047
2048static
sewardj2e595852005-06-30 23:33:37 +00002049IRAtom* expr2vbits_Load ( MCEnv* mce,
2050 IREndness end, IRType ty,
2051 IRAtom* addr, UInt bias )
sewardj170ee212004-12-10 18:57:51 +00002052{
2053 IRAtom *v64hi, *v64lo;
sewardj2e595852005-06-30 23:33:37 +00002054 tl_assert(end == Iend_LE || end == Iend_BE);
sewardj170ee212004-12-10 18:57:51 +00002055 switch (shadowType(ty)) {
2056 case Ity_I8:
2057 case Ity_I16:
2058 case Ity_I32:
2059 case Ity_I64:
sewardj2e595852005-06-30 23:33:37 +00002060 return expr2vbits_Load_WRK(mce, end, ty, addr, bias);
sewardj170ee212004-12-10 18:57:51 +00002061 case Ity_V128:
sewardj2e595852005-06-30 23:33:37 +00002062 if (end == Iend_LE) {
2063 v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
2064 v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
2065 } else {
sewardj2e595852005-06-30 23:33:37 +00002066 v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
2067 v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
2068 }
sewardj170ee212004-12-10 18:57:51 +00002069 return assignNew( mce,
2070 Ity_V128,
sewardj20d38f22005-02-07 23:50:18 +00002071 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj170ee212004-12-10 18:57:51 +00002072 default:
sewardj2e595852005-06-30 23:33:37 +00002073 VG_(tool_panic)("expr2vbits_Load");
sewardj170ee212004-12-10 18:57:51 +00002074 }
2075}
2076
2077
2078static
sewardj95448072004-11-22 20:19:51 +00002079IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
2080 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
2081{
2082 IRAtom *vbitsC, *vbits0, *vbitsX;
2083 IRType ty;
2084 /* Given Mux0X(cond,expr0,exprX), generate
2085 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2086 That is, steer the V bits like the originals, but trash the
2087 result if the steering value is undefined. This gives
2088 lazy propagation. */
2089 tl_assert(isOriginalAtom(mce, cond));
2090 tl_assert(isOriginalAtom(mce, expr0));
2091 tl_assert(isOriginalAtom(mce, exprX));
2092
2093 vbitsC = expr2vbits(mce, cond);
2094 vbits0 = expr2vbits(mce, expr0);
2095 vbitsX = expr2vbits(mce, exprX);
2096 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2097
2098 return
2099 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2100 mkPCastTo(mce, ty, vbitsC) );
2101}
2102
2103/* --------- This is the main expression-handling function. --------- */
2104
2105static
2106IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2107{
2108 switch (e->tag) {
2109
2110 case Iex_Get:
2111 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2112
2113 case Iex_GetI:
2114 return shadow_GETI( mce, e->Iex.GetI.descr,
2115 e->Iex.GetI.ix, e->Iex.GetI.bias );
2116
2117 case Iex_Tmp:
2118 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
2119
2120 case Iex_Const:
2121 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2122
2123 case Iex_Binop:
2124 return expr2vbits_Binop(
2125 mce,
2126 e->Iex.Binop.op,
2127 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2128 );
2129
2130 case Iex_Unop:
2131 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2132
sewardj2e595852005-06-30 23:33:37 +00002133 case Iex_Load:
2134 return expr2vbits_Load( mce, e->Iex.Load.end,
2135 e->Iex.Load.ty,
2136 e->Iex.Load.addr, 0/*addr bias*/ );
sewardj95448072004-11-22 20:19:51 +00002137
2138 case Iex_CCall:
2139 return mkLazyN( mce, e->Iex.CCall.args,
2140 e->Iex.CCall.retty,
2141 e->Iex.CCall.cee );
2142
2143 case Iex_Mux0X:
2144 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2145 e->Iex.Mux0X.exprX);
njn25e49d8e72002-09-23 09:36:25 +00002146
2147 default:
sewardj95448072004-11-22 20:19:51 +00002148 VG_(printf)("\n");
2149 ppIRExpr(e);
2150 VG_(printf)("\n");
2151 VG_(tool_panic)("memcheck: expr2vbits");
njn25e49d8e72002-09-23 09:36:25 +00002152 }
njn25e49d8e72002-09-23 09:36:25 +00002153}
2154
2155/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00002156/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
njn25e49d8e72002-09-23 09:36:25 +00002157/*------------------------------------------------------------*/
2158
sewardj95448072004-11-22 20:19:51 +00002159/* Widen a value to the host word size. */
njn25e49d8e72002-09-23 09:36:25 +00002160
2161static
sewardj95448072004-11-22 20:19:51 +00002162IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
njn25e49d8e72002-09-23 09:36:25 +00002163{
sewardj7cf97ee2004-11-28 14:25:01 +00002164 IRType ty, tyH;
2165
sewardj95448072004-11-22 20:19:51 +00002166 /* vatom is vbits-value and as such can only have a shadow type. */
2167 tl_assert(isShadowAtom(mce,vatom));
njn25e49d8e72002-09-23 09:36:25 +00002168
sewardj7cf97ee2004-11-28 14:25:01 +00002169 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2170 tyH = mce->hWordTy;
njn25e49d8e72002-09-23 09:36:25 +00002171
sewardj95448072004-11-22 20:19:51 +00002172 if (tyH == Ity_I32) {
2173 switch (ty) {
2174 case Ity_I32: return vatom;
2175 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2176 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2177 default: goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00002178 }
sewardj6cf40ff2005-04-20 22:31:26 +00002179 } else
2180 if (tyH == Ity_I64) {
2181 switch (ty) {
2182 case Ity_I32: return assignNew(mce, tyH, unop(Iop_32Uto64, vatom));
sewardj69a13322005-04-23 01:14:51 +00002183 case Ity_I16: return assignNew(mce, tyH, unop(Iop_32Uto64,
2184 assignNew(mce, Ity_I32, unop(Iop_16Uto32, vatom))));
2185 case Ity_I8: return assignNew(mce, tyH, unop(Iop_32Uto64,
2186 assignNew(mce, Ity_I32, unop(Iop_8Uto32, vatom))));
sewardj6cf40ff2005-04-20 22:31:26 +00002187 default: goto unhandled;
2188 }
sewardj95448072004-11-22 20:19:51 +00002189 } else {
2190 goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00002191 }
sewardj95448072004-11-22 20:19:51 +00002192 unhandled:
2193 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
2194 VG_(tool_panic)("zwidenToHostWord");
njn25e49d8e72002-09-23 09:36:25 +00002195}
2196
njn25e49d8e72002-09-23 09:36:25 +00002197
sewardj95448072004-11-22 20:19:51 +00002198/* Generate a shadow store. addr is always the original address atom.
2199 You can pass in either originals or V-bits for the data atom, but
2200 obviously not both. */
njn25e49d8e72002-09-23 09:36:25 +00002201
sewardj95448072004-11-22 20:19:51 +00002202static
sewardj2e595852005-06-30 23:33:37 +00002203void do_shadow_Store ( MCEnv* mce,
2204 IREndness end,
2205 IRAtom* addr, UInt bias,
2206 IRAtom* data, IRAtom* vdata )
njn25e49d8e72002-09-23 09:36:25 +00002207{
sewardj170ee212004-12-10 18:57:51 +00002208 IROp mkAdd;
2209 IRType ty, tyAddr;
2210 IRDirty *di, *diLo64, *diHi64;
2211 IRAtom *addrAct, *addrLo64, *addrHi64;
2212 IRAtom *vdataLo64, *vdataHi64;
sewardj2e595852005-06-30 23:33:37 +00002213 IRAtom *eBias, *eBiasLo64, *eBiasHi64;
sewardj95448072004-11-22 20:19:51 +00002214 void* helper = NULL;
2215 Char* hname = NULL;
sewardj170ee212004-12-10 18:57:51 +00002216
2217 tyAddr = mce->hWordTy;
2218 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2219 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj2e595852005-06-30 23:33:37 +00002220 tl_assert( end == Iend_LE || end == Iend_BE );
sewardj170ee212004-12-10 18:57:51 +00002221
2222 di = diLo64 = diHi64 = NULL;
sewardj2e595852005-06-30 23:33:37 +00002223 eBias = eBiasLo64 = eBiasHi64 = NULL;
sewardj170ee212004-12-10 18:57:51 +00002224 addrAct = addrLo64 = addrHi64 = NULL;
2225 vdataLo64 = vdataHi64 = NULL;
njn25e49d8e72002-09-23 09:36:25 +00002226
sewardj95448072004-11-22 20:19:51 +00002227 if (data) {
2228 tl_assert(!vdata);
2229 tl_assert(isOriginalAtom(mce, data));
2230 tl_assert(bias == 0);
2231 vdata = expr2vbits( mce, data );
2232 } else {
2233 tl_assert(vdata);
2234 }
njn25e49d8e72002-09-23 09:36:25 +00002235
sewardj95448072004-11-22 20:19:51 +00002236 tl_assert(isOriginalAtom(mce,addr));
2237 tl_assert(isShadowAtom(mce,vdata));
njn25e49d8e72002-09-23 09:36:25 +00002238
sewardj95448072004-11-22 20:19:51 +00002239 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
njn25e49d8e72002-09-23 09:36:25 +00002240
sewardj95448072004-11-22 20:19:51 +00002241 /* First, emit a definedness test for the address. This also sets
2242 the address (shadow) to 'defined' following the test. */
2243 complainIfUndefined( mce, addr );
njn25e49d8e72002-09-23 09:36:25 +00002244
sewardj170ee212004-12-10 18:57:51 +00002245 /* Now decide which helper function to call to write the data V
2246 bits into shadow memory. */
sewardj2e595852005-06-30 23:33:37 +00002247 if (end == Iend_LE) {
2248 switch (ty) {
2249 case Ity_V128: /* we'll use the helper twice */
2250 case Ity_I64: helper = &MC_(helperc_STOREV8le);
2251 hname = "MC_(helperc_STOREV8le)";
2252 break;
2253 case Ity_I32: helper = &MC_(helperc_STOREV4le);
2254 hname = "MC_(helperc_STOREV4le)";
2255 break;
2256 case Ity_I16: helper = &MC_(helperc_STOREV2le);
2257 hname = "MC_(helperc_STOREV2le)";
2258 break;
sewardj8cf88b72005-07-08 01:29:33 +00002259 case Ity_I8: helper = &MC_(helperc_STOREV1);
2260 hname = "MC_(helperc_STOREV1)";
sewardj2e595852005-06-30 23:33:37 +00002261 break;
2262 default: VG_(tool_panic)("memcheck:do_shadow_Store(LE)");
2263 }
2264 } else {
sewardj8cf88b72005-07-08 01:29:33 +00002265 switch (ty) {
2266 case Ity_V128: /* we'll use the helper twice */
2267 case Ity_I64: helper = &MC_(helperc_STOREV8be);
2268 hname = "MC_(helperc_STOREV8be)";
2269 break;
2270 case Ity_I32: helper = &MC_(helperc_STOREV4be);
2271 hname = "MC_(helperc_STOREV4be)";
2272 break;
2273 case Ity_I16: helper = &MC_(helperc_STOREV2be);
2274 hname = "MC_(helperc_STOREV2be)";
2275 break;
2276 case Ity_I8: helper = &MC_(helperc_STOREV1);
2277 hname = "MC_(helperc_STOREV1)";
2278 break;
2279 default: VG_(tool_panic)("memcheck:do_shadow_Store(BE)");
2280 }
sewardj95448072004-11-22 20:19:51 +00002281 }
njn25e49d8e72002-09-23 09:36:25 +00002282
sewardj170ee212004-12-10 18:57:51 +00002283 if (ty == Ity_V128) {
2284
sewardj20d38f22005-02-07 23:50:18 +00002285 /* V128-bit case */
sewardj170ee212004-12-10 18:57:51 +00002286 /* See comment in next clause re 64-bit regparms */
sewardj2e595852005-06-30 23:33:37 +00002287 /* also, need to be careful about endianness */
2288
2289 Int offLo64, offHi64;
2290 if (end == Iend_LE) {
2291 offLo64 = 0;
2292 offHi64 = 8;
2293 } else {
sewardj2e595852005-06-30 23:33:37 +00002294 offLo64 = 8;
2295 offHi64 = 0;
2296 }
2297
2298 eBiasLo64 = tyAddr==Ity_I32 ? mkU32(bias+offLo64) : mkU64(bias+offLo64);
2299 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBiasLo64) );
sewardj20d38f22005-02-07 23:50:18 +00002300 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj170ee212004-12-10 18:57:51 +00002301 diLo64 = unsafeIRDirty_0_N(
2302 1/*regparms*/, hname, helper,
2303 mkIRExprVec_2( addrLo64, vdataLo64 ));
2304
sewardj2e595852005-06-30 23:33:37 +00002305 eBiasHi64 = tyAddr==Ity_I32 ? mkU32(bias+offHi64) : mkU64(bias+offHi64);
2306 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBiasHi64) );
sewardj20d38f22005-02-07 23:50:18 +00002307 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj170ee212004-12-10 18:57:51 +00002308 diHi64 = unsafeIRDirty_0_N(
2309 1/*regparms*/, hname, helper,
2310 mkIRExprVec_2( addrHi64, vdataHi64 ));
2311
2312 setHelperAnns( mce, diLo64 );
2313 setHelperAnns( mce, diHi64 );
2314 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2315 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2316
sewardj95448072004-11-22 20:19:51 +00002317 } else {
sewardj170ee212004-12-10 18:57:51 +00002318
2319 /* 8/16/32/64-bit cases */
2320 /* Generate the actual address into addrAct. */
2321 if (bias == 0) {
2322 addrAct = addr;
2323 } else {
2324 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2325 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2326 }
2327
2328 if (ty == Ity_I64) {
2329 /* We can't do this with regparm 2 on 32-bit platforms, since
2330 the back ends aren't clever enough to handle 64-bit
2331 regparm args. Therefore be different. */
2332 di = unsafeIRDirty_0_N(
2333 1/*regparms*/, hname, helper,
2334 mkIRExprVec_2( addrAct, vdata ));
2335 } else {
2336 di = unsafeIRDirty_0_N(
2337 2/*regparms*/, hname, helper,
2338 mkIRExprVec_2( addrAct,
2339 zwidenToHostWord( mce, vdata )));
2340 }
2341 setHelperAnns( mce, di );
2342 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj95448072004-11-22 20:19:51 +00002343 }
njn25e49d8e72002-09-23 09:36:25 +00002344
sewardj95448072004-11-22 20:19:51 +00002345}
njn25e49d8e72002-09-23 09:36:25 +00002346
njn25e49d8e72002-09-23 09:36:25 +00002347
sewardj95448072004-11-22 20:19:51 +00002348/* Do lazy pessimistic propagation through a dirty helper call, by
2349 looking at the annotations on it. This is the most complex part of
2350 Memcheck. */
njn25e49d8e72002-09-23 09:36:25 +00002351
sewardj95448072004-11-22 20:19:51 +00002352static IRType szToITy ( Int n )
2353{
2354 switch (n) {
2355 case 1: return Ity_I8;
2356 case 2: return Ity_I16;
2357 case 4: return Ity_I32;
2358 case 8: return Ity_I64;
2359 default: VG_(tool_panic)("szToITy(memcheck)");
2360 }
2361}
njn25e49d8e72002-09-23 09:36:25 +00002362
sewardj95448072004-11-22 20:19:51 +00002363static
2364void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2365{
sewardj2e595852005-06-30 23:33:37 +00002366 Int i, n, offset, toDo, gSz, gOff;
2367 IRAtom *src, *here, *curr;
2368 IRType tyAddr, tySrc, tyDst;
2369 IRTemp dst;
2370 IREndness end;
2371
2372 /* What's the native endianness? We need to know this. */
sewardj6e340c72005-07-10 00:53:42 +00002373# if defined(VG_BIGENDIAN)
sewardj2e595852005-06-30 23:33:37 +00002374 end = Iend_BE;
sewardj6e340c72005-07-10 00:53:42 +00002375# elif defined(VG_LITTLEENDIAN)
sewardj2e595852005-06-30 23:33:37 +00002376 end = Iend_LE;
2377# else
2378# error "Unknown endianness"
2379# endif
njn25e49d8e72002-09-23 09:36:25 +00002380
sewardj95448072004-11-22 20:19:51 +00002381 /* First check the guard. */
2382 complainIfUndefined(mce, d->guard);
2383
2384 /* Now round up all inputs and PCast over them. */
sewardj7cf97ee2004-11-28 14:25:01 +00002385 curr = definedOfType(Ity_I32);
sewardj95448072004-11-22 20:19:51 +00002386
2387 /* Inputs: unmasked args */
2388 for (i = 0; d->args[i]; i++) {
2389 if (d->cee->mcx_mask & (1<<i)) {
2390 /* ignore this arg */
njn25e49d8e72002-09-23 09:36:25 +00002391 } else {
sewardj95448072004-11-22 20:19:51 +00002392 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2393 curr = mkUifU32(mce, here, curr);
njn25e49d8e72002-09-23 09:36:25 +00002394 }
2395 }
sewardj95448072004-11-22 20:19:51 +00002396
2397 /* Inputs: guest state that we read. */
2398 for (i = 0; i < d->nFxState; i++) {
2399 tl_assert(d->fxState[i].fx != Ifx_None);
2400 if (d->fxState[i].fx == Ifx_Write)
2401 continue;
sewardja7203252004-11-26 19:17:47 +00002402
2403 /* Ignore any sections marked as 'always defined'. */
2404 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
sewardje9e16d32004-12-10 13:17:55 +00002405 if (0)
sewardja7203252004-11-26 19:17:47 +00002406 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2407 d->fxState[i].offset, d->fxState[i].size );
2408 continue;
2409 }
2410
sewardj95448072004-11-22 20:19:51 +00002411 /* This state element is read or modified. So we need to
sewardje9e16d32004-12-10 13:17:55 +00002412 consider it. If larger than 8 bytes, deal with it in 8-byte
2413 chunks. */
2414 gSz = d->fxState[i].size;
2415 gOff = d->fxState[i].offset;
2416 tl_assert(gSz > 0);
2417 while (True) {
2418 if (gSz == 0) break;
2419 n = gSz <= 8 ? gSz : 8;
2420 /* update 'curr' with UifU of the state slice
2421 gOff .. gOff+n-1 */
2422 tySrc = szToITy( n );
2423 src = assignNew( mce, tySrc,
2424 shadow_GET(mce, gOff, tySrc ) );
2425 here = mkPCastTo( mce, Ity_I32, src );
2426 curr = mkUifU32(mce, here, curr);
2427 gSz -= n;
2428 gOff += n;
2429 }
2430
sewardj95448072004-11-22 20:19:51 +00002431 }
2432
2433 /* Inputs: memory. First set up some info needed regardless of
2434 whether we're doing reads or writes. */
2435 tyAddr = Ity_INVALID;
2436
2437 if (d->mFx != Ifx_None) {
2438 /* Because we may do multiple shadow loads/stores from the same
2439 base address, it's best to do a single test of its
2440 definedness right now. Post-instrumentation optimisation
2441 should remove all but this test. */
2442 tl_assert(d->mAddr);
2443 complainIfUndefined(mce, d->mAddr);
2444
2445 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
2446 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2447 tl_assert(tyAddr == mce->hWordTy); /* not really right */
2448 }
2449
2450 /* Deal with memory inputs (reads or modifies) */
2451 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2452 offset = 0;
2453 toDo = d->mSize;
sewardj2e595852005-06-30 23:33:37 +00002454 /* chew off 32-bit chunks. We don't care about the endianness
2455 since it's all going to be condensed down to a single bit,
2456 but nevertheless choose an endianness which is hopefully
2457 native to the platform. */
sewardj95448072004-11-22 20:19:51 +00002458 while (toDo >= 4) {
2459 here = mkPCastTo(
2460 mce, Ity_I32,
sewardj2e595852005-06-30 23:33:37 +00002461 expr2vbits_Load ( mce, end, Ity_I32,
sewardj95448072004-11-22 20:19:51 +00002462 d->mAddr, d->mSize - toDo )
2463 );
2464 curr = mkUifU32(mce, here, curr);
2465 toDo -= 4;
2466 }
2467 /* chew off 16-bit chunks */
2468 while (toDo >= 2) {
2469 here = mkPCastTo(
2470 mce, Ity_I32,
sewardj2e595852005-06-30 23:33:37 +00002471 expr2vbits_Load ( mce, end, Ity_I16,
sewardj95448072004-11-22 20:19:51 +00002472 d->mAddr, d->mSize - toDo )
2473 );
2474 curr = mkUifU32(mce, here, curr);
2475 toDo -= 2;
2476 }
2477 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
2478 }
2479
2480 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2481 all the inputs to the helper. Now we need to re-distribute the
2482 results to all destinations. */
2483
2484 /* Outputs: the destination temporary, if there is one. */
2485 if (d->tmp != IRTemp_INVALID) {
2486 dst = findShadowTmp(mce, d->tmp);
2487 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2488 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2489 }
2490
2491 /* Outputs: guest state that we write or modify. */
2492 for (i = 0; i < d->nFxState; i++) {
2493 tl_assert(d->fxState[i].fx != Ifx_None);
2494 if (d->fxState[i].fx == Ifx_Read)
2495 continue;
sewardja7203252004-11-26 19:17:47 +00002496 /* Ignore any sections marked as 'always defined'. */
2497 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2498 continue;
sewardje9e16d32004-12-10 13:17:55 +00002499 /* This state element is written or modified. So we need to
2500 consider it. If larger than 8 bytes, deal with it in 8-byte
2501 chunks. */
2502 gSz = d->fxState[i].size;
2503 gOff = d->fxState[i].offset;
2504 tl_assert(gSz > 0);
2505 while (True) {
2506 if (gSz == 0) break;
2507 n = gSz <= 8 ? gSz : 8;
2508 /* Write suitably-casted 'curr' to the state slice
2509 gOff .. gOff+n-1 */
2510 tyDst = szToITy( n );
2511 do_shadow_PUT( mce, gOff,
2512 NULL, /* original atom */
2513 mkPCastTo( mce, tyDst, curr ) );
2514 gSz -= n;
2515 gOff += n;
2516 }
sewardj95448072004-11-22 20:19:51 +00002517 }
2518
sewardj2e595852005-06-30 23:33:37 +00002519 /* Outputs: memory that we write or modify. Same comments about
2520 endianness as above apply. */
sewardj95448072004-11-22 20:19:51 +00002521 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2522 offset = 0;
2523 toDo = d->mSize;
2524 /* chew off 32-bit chunks */
2525 while (toDo >= 4) {
sewardj2e595852005-06-30 23:33:37 +00002526 do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
2527 NULL, /* original data */
2528 mkPCastTo( mce, Ity_I32, curr ) );
sewardj95448072004-11-22 20:19:51 +00002529 toDo -= 4;
2530 }
2531 /* chew off 16-bit chunks */
2532 while (toDo >= 2) {
sewardj2e595852005-06-30 23:33:37 +00002533 do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
2534 NULL, /* original data */
2535 mkPCastTo( mce, Ity_I16, curr ) );
sewardj95448072004-11-22 20:19:51 +00002536 toDo -= 2;
2537 }
2538 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
2539 }
2540
njn25e49d8e72002-09-23 09:36:25 +00002541}
2542
sewardj826ec492005-05-12 18:05:00 +00002543/* We have an ABI hint telling us that [base .. base+len-1] is to
2544 become undefined ("writable"). Generate code to call a helper to
2545 notify the A/V bit machinery of this fact.
2546
2547 We call
2548 void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len );
2549*/
2550static
2551void do_AbiHint ( MCEnv* mce, IRExpr* base, Int len )
2552{
2553 IRDirty* di;
2554 di = unsafeIRDirty_0_N(
2555 0/*regparms*/,
2556 "MC_(helperc_MAKE_STACK_UNINIT)",
2557 &MC_(helperc_MAKE_STACK_UNINIT),
2558 mkIRExprVec_2( base, mkIRExpr_HWord( (UInt)len) )
2559 );
2560 stmt( mce->bb, IRStmt_Dirty(di) );
2561}
2562
njn25e49d8e72002-09-23 09:36:25 +00002563
sewardj95448072004-11-22 20:19:51 +00002564/*------------------------------------------------------------*/
2565/*--- Memcheck main ---*/
2566/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00002567
sewardj95448072004-11-22 20:19:51 +00002568static Bool isBogusAtom ( IRAtom* at )
njn25e49d8e72002-09-23 09:36:25 +00002569{
sewardj95448072004-11-22 20:19:51 +00002570 ULong n = 0;
2571 IRConst* con;
sewardj710d6c22005-03-20 18:55:15 +00002572 tl_assert(isIRAtom(at));
sewardj95448072004-11-22 20:19:51 +00002573 if (at->tag == Iex_Tmp)
2574 return False;
2575 tl_assert(at->tag == Iex_Const);
2576 con = at->Iex.Const.con;
2577 switch (con->tag) {
sewardjd5204dc2004-12-31 01:16:11 +00002578 case Ico_U1: return False;
2579 case Ico_U8: n = (ULong)con->Ico.U8; break;
2580 case Ico_U16: n = (ULong)con->Ico.U16; break;
2581 case Ico_U32: n = (ULong)con->Ico.U32; break;
2582 case Ico_U64: n = (ULong)con->Ico.U64; break;
2583 case Ico_F64: return False;
2584 case Ico_F64i: return False;
2585 case Ico_V128: return False;
sewardj95448072004-11-22 20:19:51 +00002586 default: ppIRExpr(at); tl_assert(0);
2587 }
2588 /* VG_(printf)("%llx\n", n); */
sewardj96a922e2005-04-23 23:26:29 +00002589 return (/*32*/ n == 0xFEFEFEFFULL
2590 /*32*/ || n == 0x80808080ULL
tomd9774d72005-06-27 08:11:01 +00002591 /*64*/ || n == 0xFFFFFFFFFEFEFEFFULL
sewardj96a922e2005-04-23 23:26:29 +00002592 /*64*/ || n == 0xFEFEFEFEFEFEFEFFULL
tomd9774d72005-06-27 08:11:01 +00002593 /*64*/ || n == 0x0000000000008080ULL
sewardj96a922e2005-04-23 23:26:29 +00002594 /*64*/ || n == 0x8080808080808080ULL
2595 /*64*/ || n == 0x0101010101010101ULL
2596 );
sewardj95448072004-11-22 20:19:51 +00002597}
njn25e49d8e72002-09-23 09:36:25 +00002598
sewardj95448072004-11-22 20:19:51 +00002599static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2600{
sewardjd5204dc2004-12-31 01:16:11 +00002601 Int i;
2602 IRExpr* e;
2603 IRDirty* d;
sewardj95448072004-11-22 20:19:51 +00002604 switch (st->tag) {
2605 case Ist_Tmp:
2606 e = st->Ist.Tmp.data;
2607 switch (e->tag) {
2608 case Iex_Get:
2609 case Iex_Tmp:
2610 return False;
sewardjd5204dc2004-12-31 01:16:11 +00002611 case Iex_Const:
2612 return isBogusAtom(e);
sewardj95448072004-11-22 20:19:51 +00002613 case Iex_Unop:
2614 return isBogusAtom(e->Iex.Unop.arg);
sewardjd5204dc2004-12-31 01:16:11 +00002615 case Iex_GetI:
2616 return isBogusAtom(e->Iex.GetI.ix);
sewardj95448072004-11-22 20:19:51 +00002617 case Iex_Binop:
2618 return isBogusAtom(e->Iex.Binop.arg1)
2619 || isBogusAtom(e->Iex.Binop.arg2);
2620 case Iex_Mux0X:
2621 return isBogusAtom(e->Iex.Mux0X.cond)
2622 || isBogusAtom(e->Iex.Mux0X.expr0)
2623 || isBogusAtom(e->Iex.Mux0X.exprX);
sewardj2e595852005-06-30 23:33:37 +00002624 case Iex_Load:
2625 return isBogusAtom(e->Iex.Load.addr);
sewardj95448072004-11-22 20:19:51 +00002626 case Iex_CCall:
2627 for (i = 0; e->Iex.CCall.args[i]; i++)
2628 if (isBogusAtom(e->Iex.CCall.args[i]))
2629 return True;
2630 return False;
2631 default:
2632 goto unhandled;
2633 }
sewardjd5204dc2004-12-31 01:16:11 +00002634 case Ist_Dirty:
2635 d = st->Ist.Dirty.details;
2636 for (i = 0; d->args[i]; i++)
2637 if (isBogusAtom(d->args[i]))
2638 return True;
2639 if (d->guard && isBogusAtom(d->guard))
2640 return True;
2641 if (d->mAddr && isBogusAtom(d->mAddr))
2642 return True;
2643 return False;
sewardj95448072004-11-22 20:19:51 +00002644 case Ist_Put:
2645 return isBogusAtom(st->Ist.Put.data);
sewardjd5204dc2004-12-31 01:16:11 +00002646 case Ist_PutI:
2647 return isBogusAtom(st->Ist.PutI.ix)
2648 || isBogusAtom(st->Ist.PutI.data);
sewardj2e595852005-06-30 23:33:37 +00002649 case Ist_Store:
2650 return isBogusAtom(st->Ist.Store.addr)
2651 || isBogusAtom(st->Ist.Store.data);
sewardj95448072004-11-22 20:19:51 +00002652 case Ist_Exit:
sewardjd5204dc2004-12-31 01:16:11 +00002653 return isBogusAtom(st->Ist.Exit.guard);
sewardj826ec492005-05-12 18:05:00 +00002654 case Ist_AbiHint:
2655 return isBogusAtom(st->Ist.AbiHint.base);
sewardj21dc3452005-03-21 00:27:41 +00002656 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00002657 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00002658 case Ist_MFence:
2659 return False;
sewardj95448072004-11-22 20:19:51 +00002660 default:
2661 unhandled:
2662 ppIRStmt(st);
2663 VG_(tool_panic)("hasBogusLiterals");
2664 }
2665}
njn25e49d8e72002-09-23 09:36:25 +00002666
njn25e49d8e72002-09-23 09:36:25 +00002667
njn51d827b2005-05-09 01:02:08 +00002668IRBB* MC_(instrument) ( IRBB* bb_in, VexGuestLayout* layout,
sewardjd54babf2005-03-21 00:55:49 +00002669 IRType gWordTy, IRType hWordTy )
sewardj95448072004-11-22 20:19:51 +00002670{
sewardj151b90d2005-07-06 19:42:23 +00002671 Bool verboze = False; //True;
2672 Bool bogus;
sewardjd5204dc2004-12-31 01:16:11 +00002673 Int i, j, first_stmt;
sewardj95448072004-11-22 20:19:51 +00002674 IRStmt* st;
sewardjd5204dc2004-12-31 01:16:11 +00002675 MCEnv mce;
sewardjd54babf2005-03-21 00:55:49 +00002676 IRBB* bb;
2677
2678 if (gWordTy != hWordTy) {
2679 /* We don't currently support this case. */
2680 VG_(tool_panic)("host/guest word size mismatch");
2681 }
njn25e49d8e72002-09-23 09:36:25 +00002682
sewardj6cf40ff2005-04-20 22:31:26 +00002683 /* Check we're not completely nuts */
2684 tl_assert(sizeof(UWord) == sizeof(void*));
2685 tl_assert(sizeof(Word) == sizeof(void*));
2686 tl_assert(sizeof(ULong) == 8);
2687 tl_assert(sizeof(Long) == 8);
2688 tl_assert(sizeof(UInt) == 4);
2689 tl_assert(sizeof(Int) == 4);
2690
sewardj95448072004-11-22 20:19:51 +00002691 /* Set up BB */
sewardjd54babf2005-03-21 00:55:49 +00002692 bb = emptyIRBB();
sewardj95448072004-11-22 20:19:51 +00002693 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
2694 bb->next = dopyIRExpr(bb_in->next);
2695 bb->jumpkind = bb_in->jumpkind;
njn25e49d8e72002-09-23 09:36:25 +00002696
sewardj95448072004-11-22 20:19:51 +00002697 /* Set up the running environment. Only .bb is modified as we go
2698 along. */
2699 mce.bb = bb;
2700 mce.layout = layout;
2701 mce.n_originalTmps = bb->tyenv->types_used;
2702 mce.hWordTy = hWordTy;
sewardjd5204dc2004-12-31 01:16:11 +00002703 mce.bogusLiterals = False;
sewardj95448072004-11-22 20:19:51 +00002704 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2705 for (i = 0; i < mce.n_originalTmps; i++)
2706 mce.tmpMap[i] = IRTemp_INVALID;
2707
sewardj151b90d2005-07-06 19:42:23 +00002708 /* Make a preliminary inspection of the statements, to see if there
2709 are any dodgy-looking literals. If there are, we generate
2710 extra-detailed (hence extra-expensive) instrumentation in
2711 places. Scan the whole bb even if dodgyness is found earlier,
2712 so that the flatness assertion is applied to all stmts. */
2713
2714 bogus = False;
sewardj95448072004-11-22 20:19:51 +00002715
2716 for (i = 0; i < bb_in->stmts_used; i++) {
sewardj151b90d2005-07-06 19:42:23 +00002717
sewardj95448072004-11-22 20:19:51 +00002718 st = bb_in->stmts[i];
sewardj21dc3452005-03-21 00:27:41 +00002719 tl_assert(st);
sewardj95448072004-11-22 20:19:51 +00002720 tl_assert(isFlatIRStmt(st));
2721
sewardj151b90d2005-07-06 19:42:23 +00002722 if (!bogus) {
2723 bogus = checkForBogusLiterals(st);
2724 if (0 && bogus) {
sewardj95448072004-11-22 20:19:51 +00002725 VG_(printf)("bogus: ");
2726 ppIRStmt(st);
2727 VG_(printf)("\n");
2728 }
2729 }
sewardjd5204dc2004-12-31 01:16:11 +00002730
sewardj151b90d2005-07-06 19:42:23 +00002731 }
2732
2733 mce.bogusLiterals = bogus;
2734
2735 /* Iterate over the stmts to generate instrumentation. */
2736
2737 for (i = 0; i < bb_in->stmts_used; i++) {
2738
2739 st = bb_in->stmts[i];
sewardj95448072004-11-22 20:19:51 +00002740 first_stmt = bb->stmts_used;
2741
2742 if (verboze) {
2743 ppIRStmt(st);
2744 VG_(printf)("\n\n");
2745 }
2746
sewardj29faa502005-03-16 18:20:21 +00002747 /* Generate instrumentation code for each stmt ... */
2748
sewardj95448072004-11-22 20:19:51 +00002749 switch (st->tag) {
2750
2751 case Ist_Tmp:
2752 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
2753 expr2vbits( &mce, st->Ist.Tmp.data) );
njn25e49d8e72002-09-23 09:36:25 +00002754 break;
2755
sewardj95448072004-11-22 20:19:51 +00002756 case Ist_Put:
2757 do_shadow_PUT( &mce,
2758 st->Ist.Put.offset,
2759 st->Ist.Put.data,
2760 NULL /* shadow atom */ );
njn25e49d8e72002-09-23 09:36:25 +00002761 break;
2762
sewardj95448072004-11-22 20:19:51 +00002763 case Ist_PutI:
2764 do_shadow_PUTI( &mce,
2765 st->Ist.PutI.descr,
2766 st->Ist.PutI.ix,
2767 st->Ist.PutI.bias,
2768 st->Ist.PutI.data );
njn25e49d8e72002-09-23 09:36:25 +00002769 break;
2770
sewardj2e595852005-06-30 23:33:37 +00002771 case Ist_Store:
2772 do_shadow_Store( &mce, st->Ist.Store.end,
2773 st->Ist.Store.addr, 0/* addr bias */,
2774 st->Ist.Store.data,
2775 NULL /* shadow data */ );
njn25e49d8e72002-09-23 09:36:25 +00002776 break;
2777
sewardj95448072004-11-22 20:19:51 +00002778 case Ist_Exit:
sewardjd5204dc2004-12-31 01:16:11 +00002779 complainIfUndefined( &mce, st->Ist.Exit.guard );
njn25e49d8e72002-09-23 09:36:25 +00002780 break;
2781
sewardj21dc3452005-03-21 00:27:41 +00002782 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00002783 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00002784 case Ist_MFence:
2785 break;
2786
sewardj95448072004-11-22 20:19:51 +00002787 case Ist_Dirty:
2788 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
njn25e49d8e72002-09-23 09:36:25 +00002789 break;
2790
sewardj826ec492005-05-12 18:05:00 +00002791 case Ist_AbiHint:
2792 do_AbiHint( &mce, st->Ist.AbiHint.base, st->Ist.AbiHint.len );
2793 break;
2794
njn25e49d8e72002-09-23 09:36:25 +00002795 default:
sewardj95448072004-11-22 20:19:51 +00002796 VG_(printf)("\n");
2797 ppIRStmt(st);
2798 VG_(printf)("\n");
2799 VG_(tool_panic)("memcheck: unhandled IRStmt");
2800
2801 } /* switch (st->tag) */
2802
2803 if (verboze) {
2804 for (j = first_stmt; j < bb->stmts_used; j++) {
2805 VG_(printf)(" ");
2806 ppIRStmt(bb->stmts[j]);
2807 VG_(printf)("\n");
2808 }
2809 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00002810 }
sewardj95448072004-11-22 20:19:51 +00002811
sewardj29faa502005-03-16 18:20:21 +00002812 /* ... and finally copy the stmt itself to the output. */
sewardj95448072004-11-22 20:19:51 +00002813 addStmtToIRBB(bb, st);
2814
njn25e49d8e72002-09-23 09:36:25 +00002815 }
njn25e49d8e72002-09-23 09:36:25 +00002816
sewardj95448072004-11-22 20:19:51 +00002817 /* Now we need to complain if the jump target is undefined. */
2818 first_stmt = bb->stmts_used;
njn25e49d8e72002-09-23 09:36:25 +00002819
sewardj95448072004-11-22 20:19:51 +00002820 if (verboze) {
2821 VG_(printf)("bb->next = ");
2822 ppIRExpr(bb->next);
2823 VG_(printf)("\n\n");
2824 }
njn25e49d8e72002-09-23 09:36:25 +00002825
sewardj95448072004-11-22 20:19:51 +00002826 complainIfUndefined( &mce, bb->next );
njn25e49d8e72002-09-23 09:36:25 +00002827
sewardj95448072004-11-22 20:19:51 +00002828 if (verboze) {
2829 for (j = first_stmt; j < bb->stmts_used; j++) {
2830 VG_(printf)(" ");
2831 ppIRStmt(bb->stmts[j]);
2832 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00002833 }
sewardj95448072004-11-22 20:19:51 +00002834 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00002835 }
njn25e49d8e72002-09-23 09:36:25 +00002836
sewardj95448072004-11-22 20:19:51 +00002837 return bb;
2838}
njn25e49d8e72002-09-23 09:36:25 +00002839
2840/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00002841/*--- end mc_translate.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00002842/*--------------------------------------------------------------------*/