blob: 8eee505ec9d1b39cd91b4af4e16db00c97335038 [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{
177 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
178 return True;
179 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
180 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:
1912 return assignNew(mce, Ity_I32, unop(op, vatom));
1913
1914 case Iop_8Sto16:
1915 case Iop_8Uto16:
1916 case Iop_32to16:
1917 case Iop_32HIto16:
sewardjd9dbc192005-04-27 11:40:27 +00001918 case Iop_64to16:
sewardj95448072004-11-22 20:19:51 +00001919 return assignNew(mce, Ity_I16, unop(op, vatom));
1920
1921 case Iop_1Uto8:
1922 case Iop_16to8:
1923 case Iop_32to8:
sewardjd9dbc192005-04-27 11:40:27 +00001924 case Iop_64to8:
sewardj95448072004-11-22 20:19:51 +00001925 return assignNew(mce, Ity_I8, unop(op, vatom));
1926
1927 case Iop_32to1:
1928 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
1929
sewardjd9dbc192005-04-27 11:40:27 +00001930 case Iop_64to1:
1931 return assignNew(mce, Ity_I1, unop(Iop_64to1, vatom));
1932
sewardj95448072004-11-22 20:19:51 +00001933 case Iop_ReinterpF64asI64:
1934 case Iop_ReinterpI64asF64:
sewardj0b070592004-12-10 21:44:22 +00001935 case Iop_ReinterpI32asF32:
sewardj20d38f22005-02-07 23:50:18 +00001936 case Iop_NotV128:
sewardj7010f6e2004-12-10 13:35:22 +00001937 case Iop_Not64:
sewardj95448072004-11-22 20:19:51 +00001938 case Iop_Not32:
1939 case Iop_Not16:
1940 case Iop_Not8:
1941 case Iop_Not1:
1942 return vatom;
sewardj7010f6e2004-12-10 13:35:22 +00001943
sewardje53bd992005-05-03 12:22:00 +00001944 /* Neg* really fall under the Add/Sub banner, and as such you
1945 might think would qualify for the 'expensive add/sub'
1946 treatment. However, in this case since the implied literal
1947 is zero (0 - arg), we just do the cheap thing anyway. */
1948 case Iop_Neg8:
1949 return mkLeft8(mce, vatom);
1950 case Iop_Neg16:
1951 return mkLeft16(mce, vatom);
1952 case Iop_Neg32:
1953 return mkLeft32(mce, vatom);
1954
sewardj95448072004-11-22 20:19:51 +00001955 default:
1956 ppIROp(op);
1957 VG_(tool_panic)("memcheck:expr2vbits_Unop");
1958 }
1959}
1960
1961
sewardj170ee212004-12-10 18:57:51 +00001962/* Worker function; do not call directly. */
sewardj95448072004-11-22 20:19:51 +00001963static
sewardj2e595852005-06-30 23:33:37 +00001964IRAtom* expr2vbits_Load_WRK ( MCEnv* mce,
1965 IREndness end, IRType ty,
1966 IRAtom* addr, UInt bias )
sewardj95448072004-11-22 20:19:51 +00001967{
1968 void* helper;
1969 Char* hname;
1970 IRDirty* di;
1971 IRTemp datavbits;
1972 IRAtom* addrAct;
1973
1974 tl_assert(isOriginalAtom(mce,addr));
sewardj2e595852005-06-30 23:33:37 +00001975 tl_assert(end == Iend_LE || end == Iend_BE);
sewardj95448072004-11-22 20:19:51 +00001976
1977 /* First, emit a definedness test for the address. This also sets
1978 the address (shadow) to 'defined' following the test. */
1979 complainIfUndefined( mce, addr );
1980
1981 /* Now cook up a call to the relevant helper function, to read the
1982 data V bits from shadow memory. */
1983 ty = shadowType(ty);
sewardj2e595852005-06-30 23:33:37 +00001984
1985 if (end == Iend_LE) {
1986 switch (ty) {
1987 case Ity_I64: helper = &MC_(helperc_LOADV8le);
1988 hname = "MC_(helperc_LOADV8le)";
1989 break;
1990 case Ity_I32: helper = &MC_(helperc_LOADV4le);
1991 hname = "MC_(helperc_LOADV4le)";
1992 break;
1993 case Ity_I16: helper = &MC_(helperc_LOADV2le);
1994 hname = "MC_(helperc_LOADV2le)";
1995 break;
sewardj8cf88b72005-07-08 01:29:33 +00001996 case Ity_I8: helper = &MC_(helperc_LOADV1);
1997 hname = "MC_(helperc_LOADV1)";
sewardj2e595852005-06-30 23:33:37 +00001998 break;
1999 default: ppIRType(ty);
2000 VG_(tool_panic)("memcheck:do_shadow_Load(LE)");
2001 }
2002 } else {
sewardj8cf88b72005-07-08 01:29:33 +00002003 switch (ty) {
2004 case Ity_I64: helper = &MC_(helperc_LOADV8be);
2005 hname = "MC_(helperc_LOADV8be)";
2006 break;
2007 case Ity_I32: helper = &MC_(helperc_LOADV4be);
2008 hname = "MC_(helperc_LOADV4be)";
2009 break;
2010 case Ity_I16: helper = &MC_(helperc_LOADV2be);
2011 hname = "MC_(helperc_LOADV2be)";
2012 break;
2013 case Ity_I8: helper = &MC_(helperc_LOADV1);
2014 hname = "MC_(helperc_LOADV1)";
2015 break;
2016 default: ppIRType(ty);
2017 VG_(tool_panic)("memcheck:do_shadow_Load(BE)");
2018 }
sewardj95448072004-11-22 20:19:51 +00002019 }
2020
2021 /* Generate the actual address into addrAct. */
2022 if (bias == 0) {
2023 addrAct = addr;
2024 } else {
sewardj7cf97ee2004-11-28 14:25:01 +00002025 IROp mkAdd;
2026 IRAtom* eBias;
sewardj95448072004-11-22 20:19:51 +00002027 IRType tyAddr = mce->hWordTy;
2028 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj7cf97ee2004-11-28 14:25:01 +00002029 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2030 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj95448072004-11-22 20:19:51 +00002031 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2032 }
2033
2034 /* We need to have a place to park the V bits we're just about to
2035 read. */
2036 datavbits = newIRTemp(mce->bb->tyenv, ty);
2037 di = unsafeIRDirty_1_N( datavbits,
2038 1/*regparms*/, hname, helper,
2039 mkIRExprVec_1( addrAct ));
2040 setHelperAnns( mce, di );
2041 stmt( mce->bb, IRStmt_Dirty(di) );
2042
2043 return mkexpr(datavbits);
2044}
2045
2046
2047static
sewardj2e595852005-06-30 23:33:37 +00002048IRAtom* expr2vbits_Load ( MCEnv* mce,
2049 IREndness end, IRType ty,
2050 IRAtom* addr, UInt bias )
sewardj170ee212004-12-10 18:57:51 +00002051{
2052 IRAtom *v64hi, *v64lo;
sewardj2e595852005-06-30 23:33:37 +00002053 tl_assert(end == Iend_LE || end == Iend_BE);
sewardj170ee212004-12-10 18:57:51 +00002054 switch (shadowType(ty)) {
2055 case Ity_I8:
2056 case Ity_I16:
2057 case Ity_I32:
2058 case Ity_I64:
sewardj2e595852005-06-30 23:33:37 +00002059 return expr2vbits_Load_WRK(mce, end, ty, addr, bias);
sewardj170ee212004-12-10 18:57:51 +00002060 case Ity_V128:
sewardj2e595852005-06-30 23:33:37 +00002061 if (end == Iend_LE) {
2062 v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
2063 v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
2064 } else {
sewardj2e595852005-06-30 23:33:37 +00002065 v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
2066 v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
2067 }
sewardj170ee212004-12-10 18:57:51 +00002068 return assignNew( mce,
2069 Ity_V128,
sewardj20d38f22005-02-07 23:50:18 +00002070 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj170ee212004-12-10 18:57:51 +00002071 default:
sewardj2e595852005-06-30 23:33:37 +00002072 VG_(tool_panic)("expr2vbits_Load");
sewardj170ee212004-12-10 18:57:51 +00002073 }
2074}
2075
2076
2077static
sewardj95448072004-11-22 20:19:51 +00002078IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
2079 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
2080{
2081 IRAtom *vbitsC, *vbits0, *vbitsX;
2082 IRType ty;
2083 /* Given Mux0X(cond,expr0,exprX), generate
2084 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2085 That is, steer the V bits like the originals, but trash the
2086 result if the steering value is undefined. This gives
2087 lazy propagation. */
2088 tl_assert(isOriginalAtom(mce, cond));
2089 tl_assert(isOriginalAtom(mce, expr0));
2090 tl_assert(isOriginalAtom(mce, exprX));
2091
2092 vbitsC = expr2vbits(mce, cond);
2093 vbits0 = expr2vbits(mce, expr0);
2094 vbitsX = expr2vbits(mce, exprX);
2095 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2096
2097 return
2098 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2099 mkPCastTo(mce, ty, vbitsC) );
2100}
2101
2102/* --------- This is the main expression-handling function. --------- */
2103
2104static
2105IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2106{
2107 switch (e->tag) {
2108
2109 case Iex_Get:
2110 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2111
2112 case Iex_GetI:
2113 return shadow_GETI( mce, e->Iex.GetI.descr,
2114 e->Iex.GetI.ix, e->Iex.GetI.bias );
2115
2116 case Iex_Tmp:
2117 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
2118
2119 case Iex_Const:
2120 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2121
2122 case Iex_Binop:
2123 return expr2vbits_Binop(
2124 mce,
2125 e->Iex.Binop.op,
2126 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2127 );
2128
2129 case Iex_Unop:
2130 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2131
sewardj2e595852005-06-30 23:33:37 +00002132 case Iex_Load:
2133 return expr2vbits_Load( mce, e->Iex.Load.end,
2134 e->Iex.Load.ty,
2135 e->Iex.Load.addr, 0/*addr bias*/ );
sewardj95448072004-11-22 20:19:51 +00002136
2137 case Iex_CCall:
2138 return mkLazyN( mce, e->Iex.CCall.args,
2139 e->Iex.CCall.retty,
2140 e->Iex.CCall.cee );
2141
2142 case Iex_Mux0X:
2143 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2144 e->Iex.Mux0X.exprX);
njn25e49d8e72002-09-23 09:36:25 +00002145
2146 default:
sewardj95448072004-11-22 20:19:51 +00002147 VG_(printf)("\n");
2148 ppIRExpr(e);
2149 VG_(printf)("\n");
2150 VG_(tool_panic)("memcheck: expr2vbits");
njn25e49d8e72002-09-23 09:36:25 +00002151 }
njn25e49d8e72002-09-23 09:36:25 +00002152}
2153
2154/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00002155/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
njn25e49d8e72002-09-23 09:36:25 +00002156/*------------------------------------------------------------*/
2157
sewardj95448072004-11-22 20:19:51 +00002158/* Widen a value to the host word size. */
njn25e49d8e72002-09-23 09:36:25 +00002159
2160static
sewardj95448072004-11-22 20:19:51 +00002161IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
njn25e49d8e72002-09-23 09:36:25 +00002162{
sewardj7cf97ee2004-11-28 14:25:01 +00002163 IRType ty, tyH;
2164
sewardj95448072004-11-22 20:19:51 +00002165 /* vatom is vbits-value and as such can only have a shadow type. */
2166 tl_assert(isShadowAtom(mce,vatom));
njn25e49d8e72002-09-23 09:36:25 +00002167
sewardj7cf97ee2004-11-28 14:25:01 +00002168 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2169 tyH = mce->hWordTy;
njn25e49d8e72002-09-23 09:36:25 +00002170
sewardj95448072004-11-22 20:19:51 +00002171 if (tyH == Ity_I32) {
2172 switch (ty) {
2173 case Ity_I32: return vatom;
2174 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2175 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2176 default: goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00002177 }
sewardj6cf40ff2005-04-20 22:31:26 +00002178 } else
2179 if (tyH == Ity_I64) {
2180 switch (ty) {
2181 case Ity_I32: return assignNew(mce, tyH, unop(Iop_32Uto64, vatom));
sewardj69a13322005-04-23 01:14:51 +00002182 case Ity_I16: return assignNew(mce, tyH, unop(Iop_32Uto64,
2183 assignNew(mce, Ity_I32, unop(Iop_16Uto32, vatom))));
2184 case Ity_I8: return assignNew(mce, tyH, unop(Iop_32Uto64,
2185 assignNew(mce, Ity_I32, unop(Iop_8Uto32, vatom))));
sewardj6cf40ff2005-04-20 22:31:26 +00002186 default: goto unhandled;
2187 }
sewardj95448072004-11-22 20:19:51 +00002188 } else {
2189 goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00002190 }
sewardj95448072004-11-22 20:19:51 +00002191 unhandled:
2192 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
2193 VG_(tool_panic)("zwidenToHostWord");
njn25e49d8e72002-09-23 09:36:25 +00002194}
2195
njn25e49d8e72002-09-23 09:36:25 +00002196
sewardj95448072004-11-22 20:19:51 +00002197/* Generate a shadow store. addr is always the original address atom.
2198 You can pass in either originals or V-bits for the data atom, but
2199 obviously not both. */
njn25e49d8e72002-09-23 09:36:25 +00002200
sewardj95448072004-11-22 20:19:51 +00002201static
sewardj2e595852005-06-30 23:33:37 +00002202void do_shadow_Store ( MCEnv* mce,
2203 IREndness end,
2204 IRAtom* addr, UInt bias,
2205 IRAtom* data, IRAtom* vdata )
njn25e49d8e72002-09-23 09:36:25 +00002206{
sewardj170ee212004-12-10 18:57:51 +00002207 IROp mkAdd;
2208 IRType ty, tyAddr;
2209 IRDirty *di, *diLo64, *diHi64;
2210 IRAtom *addrAct, *addrLo64, *addrHi64;
2211 IRAtom *vdataLo64, *vdataHi64;
sewardj2e595852005-06-30 23:33:37 +00002212 IRAtom *eBias, *eBiasLo64, *eBiasHi64;
sewardj95448072004-11-22 20:19:51 +00002213 void* helper = NULL;
2214 Char* hname = NULL;
sewardj170ee212004-12-10 18:57:51 +00002215
2216 tyAddr = mce->hWordTy;
2217 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2218 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj2e595852005-06-30 23:33:37 +00002219 tl_assert( end == Iend_LE || end == Iend_BE );
sewardj170ee212004-12-10 18:57:51 +00002220
2221 di = diLo64 = diHi64 = NULL;
sewardj2e595852005-06-30 23:33:37 +00002222 eBias = eBiasLo64 = eBiasHi64 = NULL;
sewardj170ee212004-12-10 18:57:51 +00002223 addrAct = addrLo64 = addrHi64 = NULL;
2224 vdataLo64 = vdataHi64 = NULL;
njn25e49d8e72002-09-23 09:36:25 +00002225
sewardj95448072004-11-22 20:19:51 +00002226 if (data) {
2227 tl_assert(!vdata);
2228 tl_assert(isOriginalAtom(mce, data));
2229 tl_assert(bias == 0);
2230 vdata = expr2vbits( mce, data );
2231 } else {
2232 tl_assert(vdata);
2233 }
njn25e49d8e72002-09-23 09:36:25 +00002234
sewardj95448072004-11-22 20:19:51 +00002235 tl_assert(isOriginalAtom(mce,addr));
2236 tl_assert(isShadowAtom(mce,vdata));
njn25e49d8e72002-09-23 09:36:25 +00002237
sewardj95448072004-11-22 20:19:51 +00002238 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
njn25e49d8e72002-09-23 09:36:25 +00002239
sewardj95448072004-11-22 20:19:51 +00002240 /* First, emit a definedness test for the address. This also sets
2241 the address (shadow) to 'defined' following the test. */
2242 complainIfUndefined( mce, addr );
njn25e49d8e72002-09-23 09:36:25 +00002243
sewardj170ee212004-12-10 18:57:51 +00002244 /* Now decide which helper function to call to write the data V
2245 bits into shadow memory. */
sewardj2e595852005-06-30 23:33:37 +00002246 if (end == Iend_LE) {
2247 switch (ty) {
2248 case Ity_V128: /* we'll use the helper twice */
2249 case Ity_I64: helper = &MC_(helperc_STOREV8le);
2250 hname = "MC_(helperc_STOREV8le)";
2251 break;
2252 case Ity_I32: helper = &MC_(helperc_STOREV4le);
2253 hname = "MC_(helperc_STOREV4le)";
2254 break;
2255 case Ity_I16: helper = &MC_(helperc_STOREV2le);
2256 hname = "MC_(helperc_STOREV2le)";
2257 break;
sewardj8cf88b72005-07-08 01:29:33 +00002258 case Ity_I8: helper = &MC_(helperc_STOREV1);
2259 hname = "MC_(helperc_STOREV1)";
sewardj2e595852005-06-30 23:33:37 +00002260 break;
2261 default: VG_(tool_panic)("memcheck:do_shadow_Store(LE)");
2262 }
2263 } else {
sewardj8cf88b72005-07-08 01:29:33 +00002264 switch (ty) {
2265 case Ity_V128: /* we'll use the helper twice */
2266 case Ity_I64: helper = &MC_(helperc_STOREV8be);
2267 hname = "MC_(helperc_STOREV8be)";
2268 break;
2269 case Ity_I32: helper = &MC_(helperc_STOREV4be);
2270 hname = "MC_(helperc_STOREV4be)";
2271 break;
2272 case Ity_I16: helper = &MC_(helperc_STOREV2be);
2273 hname = "MC_(helperc_STOREV2be)";
2274 break;
2275 case Ity_I8: helper = &MC_(helperc_STOREV1);
2276 hname = "MC_(helperc_STOREV1)";
2277 break;
2278 default: VG_(tool_panic)("memcheck:do_shadow_Store(BE)");
2279 }
sewardj95448072004-11-22 20:19:51 +00002280 }
njn25e49d8e72002-09-23 09:36:25 +00002281
sewardj170ee212004-12-10 18:57:51 +00002282 if (ty == Ity_V128) {
2283
sewardj20d38f22005-02-07 23:50:18 +00002284 /* V128-bit case */
sewardj170ee212004-12-10 18:57:51 +00002285 /* See comment in next clause re 64-bit regparms */
sewardj2e595852005-06-30 23:33:37 +00002286 /* also, need to be careful about endianness */
2287
2288 Int offLo64, offHi64;
2289 if (end == Iend_LE) {
2290 offLo64 = 0;
2291 offHi64 = 8;
2292 } else {
sewardj2e595852005-06-30 23:33:37 +00002293 offLo64 = 8;
2294 offHi64 = 0;
2295 }
2296
2297 eBiasLo64 = tyAddr==Ity_I32 ? mkU32(bias+offLo64) : mkU64(bias+offLo64);
2298 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBiasLo64) );
sewardj20d38f22005-02-07 23:50:18 +00002299 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj170ee212004-12-10 18:57:51 +00002300 diLo64 = unsafeIRDirty_0_N(
2301 1/*regparms*/, hname, helper,
2302 mkIRExprVec_2( addrLo64, vdataLo64 ));
2303
sewardj2e595852005-06-30 23:33:37 +00002304 eBiasHi64 = tyAddr==Ity_I32 ? mkU32(bias+offHi64) : mkU64(bias+offHi64);
2305 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBiasHi64) );
sewardj20d38f22005-02-07 23:50:18 +00002306 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj170ee212004-12-10 18:57:51 +00002307 diHi64 = unsafeIRDirty_0_N(
2308 1/*regparms*/, hname, helper,
2309 mkIRExprVec_2( addrHi64, vdataHi64 ));
2310
2311 setHelperAnns( mce, diLo64 );
2312 setHelperAnns( mce, diHi64 );
2313 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2314 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2315
sewardj95448072004-11-22 20:19:51 +00002316 } else {
sewardj170ee212004-12-10 18:57:51 +00002317
2318 /* 8/16/32/64-bit cases */
2319 /* Generate the actual address into addrAct. */
2320 if (bias == 0) {
2321 addrAct = addr;
2322 } else {
2323 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2324 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2325 }
2326
2327 if (ty == Ity_I64) {
2328 /* We can't do this with regparm 2 on 32-bit platforms, since
2329 the back ends aren't clever enough to handle 64-bit
2330 regparm args. Therefore be different. */
2331 di = unsafeIRDirty_0_N(
2332 1/*regparms*/, hname, helper,
2333 mkIRExprVec_2( addrAct, vdata ));
2334 } else {
2335 di = unsafeIRDirty_0_N(
2336 2/*regparms*/, hname, helper,
2337 mkIRExprVec_2( addrAct,
2338 zwidenToHostWord( mce, vdata )));
2339 }
2340 setHelperAnns( mce, di );
2341 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj95448072004-11-22 20:19:51 +00002342 }
njn25e49d8e72002-09-23 09:36:25 +00002343
sewardj95448072004-11-22 20:19:51 +00002344}
njn25e49d8e72002-09-23 09:36:25 +00002345
njn25e49d8e72002-09-23 09:36:25 +00002346
sewardj95448072004-11-22 20:19:51 +00002347/* Do lazy pessimistic propagation through a dirty helper call, by
2348 looking at the annotations on it. This is the most complex part of
2349 Memcheck. */
njn25e49d8e72002-09-23 09:36:25 +00002350
sewardj95448072004-11-22 20:19:51 +00002351static IRType szToITy ( Int n )
2352{
2353 switch (n) {
2354 case 1: return Ity_I8;
2355 case 2: return Ity_I16;
2356 case 4: return Ity_I32;
2357 case 8: return Ity_I64;
2358 default: VG_(tool_panic)("szToITy(memcheck)");
2359 }
2360}
njn25e49d8e72002-09-23 09:36:25 +00002361
sewardj95448072004-11-22 20:19:51 +00002362static
2363void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2364{
sewardj2e595852005-06-30 23:33:37 +00002365 Int i, n, offset, toDo, gSz, gOff;
2366 IRAtom *src, *here, *curr;
2367 IRType tyAddr, tySrc, tyDst;
2368 IRTemp dst;
2369 IREndness end;
2370
2371 /* What's the native endianness? We need to know this. */
sewardj6e340c72005-07-10 00:53:42 +00002372# if defined(VG_BIGENDIAN)
sewardj2e595852005-06-30 23:33:37 +00002373 end = Iend_BE;
sewardj6e340c72005-07-10 00:53:42 +00002374# elif defined(VG_LITTLEENDIAN)
sewardj2e595852005-06-30 23:33:37 +00002375 end = Iend_LE;
2376# else
2377# error "Unknown endianness"
2378# endif
njn25e49d8e72002-09-23 09:36:25 +00002379
sewardj95448072004-11-22 20:19:51 +00002380 /* First check the guard. */
2381 complainIfUndefined(mce, d->guard);
2382
2383 /* Now round up all inputs and PCast over them. */
sewardj7cf97ee2004-11-28 14:25:01 +00002384 curr = definedOfType(Ity_I32);
sewardj95448072004-11-22 20:19:51 +00002385
2386 /* Inputs: unmasked args */
2387 for (i = 0; d->args[i]; i++) {
2388 if (d->cee->mcx_mask & (1<<i)) {
2389 /* ignore this arg */
njn25e49d8e72002-09-23 09:36:25 +00002390 } else {
sewardj95448072004-11-22 20:19:51 +00002391 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2392 curr = mkUifU32(mce, here, curr);
njn25e49d8e72002-09-23 09:36:25 +00002393 }
2394 }
sewardj95448072004-11-22 20:19:51 +00002395
2396 /* Inputs: guest state that we read. */
2397 for (i = 0; i < d->nFxState; i++) {
2398 tl_assert(d->fxState[i].fx != Ifx_None);
2399 if (d->fxState[i].fx == Ifx_Write)
2400 continue;
sewardja7203252004-11-26 19:17:47 +00002401
2402 /* Ignore any sections marked as 'always defined'. */
2403 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
sewardje9e16d32004-12-10 13:17:55 +00002404 if (0)
sewardja7203252004-11-26 19:17:47 +00002405 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2406 d->fxState[i].offset, d->fxState[i].size );
2407 continue;
2408 }
2409
sewardj95448072004-11-22 20:19:51 +00002410 /* This state element is read or modified. So we need to
sewardje9e16d32004-12-10 13:17:55 +00002411 consider it. If larger than 8 bytes, deal with it in 8-byte
2412 chunks. */
2413 gSz = d->fxState[i].size;
2414 gOff = d->fxState[i].offset;
2415 tl_assert(gSz > 0);
2416 while (True) {
2417 if (gSz == 0) break;
2418 n = gSz <= 8 ? gSz : 8;
2419 /* update 'curr' with UifU of the state slice
2420 gOff .. gOff+n-1 */
2421 tySrc = szToITy( n );
2422 src = assignNew( mce, tySrc,
2423 shadow_GET(mce, gOff, tySrc ) );
2424 here = mkPCastTo( mce, Ity_I32, src );
2425 curr = mkUifU32(mce, here, curr);
2426 gSz -= n;
2427 gOff += n;
2428 }
2429
sewardj95448072004-11-22 20:19:51 +00002430 }
2431
2432 /* Inputs: memory. First set up some info needed regardless of
2433 whether we're doing reads or writes. */
2434 tyAddr = Ity_INVALID;
2435
2436 if (d->mFx != Ifx_None) {
2437 /* Because we may do multiple shadow loads/stores from the same
2438 base address, it's best to do a single test of its
2439 definedness right now. Post-instrumentation optimisation
2440 should remove all but this test. */
2441 tl_assert(d->mAddr);
2442 complainIfUndefined(mce, d->mAddr);
2443
2444 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
2445 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2446 tl_assert(tyAddr == mce->hWordTy); /* not really right */
2447 }
2448
2449 /* Deal with memory inputs (reads or modifies) */
2450 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2451 offset = 0;
2452 toDo = d->mSize;
sewardj2e595852005-06-30 23:33:37 +00002453 /* chew off 32-bit chunks. We don't care about the endianness
2454 since it's all going to be condensed down to a single bit,
2455 but nevertheless choose an endianness which is hopefully
2456 native to the platform. */
sewardj95448072004-11-22 20:19:51 +00002457 while (toDo >= 4) {
2458 here = mkPCastTo(
2459 mce, Ity_I32,
sewardj2e595852005-06-30 23:33:37 +00002460 expr2vbits_Load ( mce, end, Ity_I32,
sewardj95448072004-11-22 20:19:51 +00002461 d->mAddr, d->mSize - toDo )
2462 );
2463 curr = mkUifU32(mce, here, curr);
2464 toDo -= 4;
2465 }
2466 /* chew off 16-bit chunks */
2467 while (toDo >= 2) {
2468 here = mkPCastTo(
2469 mce, Ity_I32,
sewardj2e595852005-06-30 23:33:37 +00002470 expr2vbits_Load ( mce, end, Ity_I16,
sewardj95448072004-11-22 20:19:51 +00002471 d->mAddr, d->mSize - toDo )
2472 );
2473 curr = mkUifU32(mce, here, curr);
2474 toDo -= 2;
2475 }
2476 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
2477 }
2478
2479 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2480 all the inputs to the helper. Now we need to re-distribute the
2481 results to all destinations. */
2482
2483 /* Outputs: the destination temporary, if there is one. */
2484 if (d->tmp != IRTemp_INVALID) {
2485 dst = findShadowTmp(mce, d->tmp);
2486 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2487 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2488 }
2489
2490 /* Outputs: guest state that we write or modify. */
2491 for (i = 0; i < d->nFxState; i++) {
2492 tl_assert(d->fxState[i].fx != Ifx_None);
2493 if (d->fxState[i].fx == Ifx_Read)
2494 continue;
sewardja7203252004-11-26 19:17:47 +00002495 /* Ignore any sections marked as 'always defined'. */
2496 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2497 continue;
sewardje9e16d32004-12-10 13:17:55 +00002498 /* This state element is written or modified. So we need to
2499 consider it. If larger than 8 bytes, deal with it in 8-byte
2500 chunks. */
2501 gSz = d->fxState[i].size;
2502 gOff = d->fxState[i].offset;
2503 tl_assert(gSz > 0);
2504 while (True) {
2505 if (gSz == 0) break;
2506 n = gSz <= 8 ? gSz : 8;
2507 /* Write suitably-casted 'curr' to the state slice
2508 gOff .. gOff+n-1 */
2509 tyDst = szToITy( n );
2510 do_shadow_PUT( mce, gOff,
2511 NULL, /* original atom */
2512 mkPCastTo( mce, tyDst, curr ) );
2513 gSz -= n;
2514 gOff += n;
2515 }
sewardj95448072004-11-22 20:19:51 +00002516 }
2517
sewardj2e595852005-06-30 23:33:37 +00002518 /* Outputs: memory that we write or modify. Same comments about
2519 endianness as above apply. */
sewardj95448072004-11-22 20:19:51 +00002520 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2521 offset = 0;
2522 toDo = d->mSize;
2523 /* chew off 32-bit chunks */
2524 while (toDo >= 4) {
sewardj2e595852005-06-30 23:33:37 +00002525 do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
2526 NULL, /* original data */
2527 mkPCastTo( mce, Ity_I32, curr ) );
sewardj95448072004-11-22 20:19:51 +00002528 toDo -= 4;
2529 }
2530 /* chew off 16-bit chunks */
2531 while (toDo >= 2) {
sewardj2e595852005-06-30 23:33:37 +00002532 do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
2533 NULL, /* original data */
2534 mkPCastTo( mce, Ity_I16, curr ) );
sewardj95448072004-11-22 20:19:51 +00002535 toDo -= 2;
2536 }
2537 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
2538 }
2539
njn25e49d8e72002-09-23 09:36:25 +00002540}
2541
sewardj826ec492005-05-12 18:05:00 +00002542/* We have an ABI hint telling us that [base .. base+len-1] is to
2543 become undefined ("writable"). Generate code to call a helper to
2544 notify the A/V bit machinery of this fact.
2545
2546 We call
2547 void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len );
2548*/
2549static
2550void do_AbiHint ( MCEnv* mce, IRExpr* base, Int len )
2551{
2552 IRDirty* di;
2553 di = unsafeIRDirty_0_N(
2554 0/*regparms*/,
2555 "MC_(helperc_MAKE_STACK_UNINIT)",
2556 &MC_(helperc_MAKE_STACK_UNINIT),
2557 mkIRExprVec_2( base, mkIRExpr_HWord( (UInt)len) )
2558 );
2559 stmt( mce->bb, IRStmt_Dirty(di) );
2560}
2561
njn25e49d8e72002-09-23 09:36:25 +00002562
sewardj95448072004-11-22 20:19:51 +00002563/*------------------------------------------------------------*/
2564/*--- Memcheck main ---*/
2565/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00002566
sewardj95448072004-11-22 20:19:51 +00002567static Bool isBogusAtom ( IRAtom* at )
njn25e49d8e72002-09-23 09:36:25 +00002568{
sewardj95448072004-11-22 20:19:51 +00002569 ULong n = 0;
2570 IRConst* con;
sewardj710d6c22005-03-20 18:55:15 +00002571 tl_assert(isIRAtom(at));
sewardj95448072004-11-22 20:19:51 +00002572 if (at->tag == Iex_Tmp)
2573 return False;
2574 tl_assert(at->tag == Iex_Const);
2575 con = at->Iex.Const.con;
2576 switch (con->tag) {
sewardjd5204dc2004-12-31 01:16:11 +00002577 case Ico_U1: return False;
2578 case Ico_U8: n = (ULong)con->Ico.U8; break;
2579 case Ico_U16: n = (ULong)con->Ico.U16; break;
2580 case Ico_U32: n = (ULong)con->Ico.U32; break;
2581 case Ico_U64: n = (ULong)con->Ico.U64; break;
2582 case Ico_F64: return False;
2583 case Ico_F64i: return False;
2584 case Ico_V128: return False;
sewardj95448072004-11-22 20:19:51 +00002585 default: ppIRExpr(at); tl_assert(0);
2586 }
2587 /* VG_(printf)("%llx\n", n); */
sewardj96a922e2005-04-23 23:26:29 +00002588 return (/*32*/ n == 0xFEFEFEFFULL
2589 /*32*/ || n == 0x80808080ULL
tomd9774d72005-06-27 08:11:01 +00002590 /*64*/ || n == 0xFFFFFFFFFEFEFEFFULL
sewardj96a922e2005-04-23 23:26:29 +00002591 /*64*/ || n == 0xFEFEFEFEFEFEFEFFULL
tomd9774d72005-06-27 08:11:01 +00002592 /*64*/ || n == 0x0000000000008080ULL
sewardj96a922e2005-04-23 23:26:29 +00002593 /*64*/ || n == 0x8080808080808080ULL
2594 /*64*/ || n == 0x0101010101010101ULL
2595 );
sewardj95448072004-11-22 20:19:51 +00002596}
njn25e49d8e72002-09-23 09:36:25 +00002597
sewardj95448072004-11-22 20:19:51 +00002598static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2599{
sewardjd5204dc2004-12-31 01:16:11 +00002600 Int i;
2601 IRExpr* e;
2602 IRDirty* d;
sewardj95448072004-11-22 20:19:51 +00002603 switch (st->tag) {
2604 case Ist_Tmp:
2605 e = st->Ist.Tmp.data;
2606 switch (e->tag) {
2607 case Iex_Get:
2608 case Iex_Tmp:
2609 return False;
sewardjd5204dc2004-12-31 01:16:11 +00002610 case Iex_Const:
2611 return isBogusAtom(e);
sewardj95448072004-11-22 20:19:51 +00002612 case Iex_Unop:
2613 return isBogusAtom(e->Iex.Unop.arg);
sewardjd5204dc2004-12-31 01:16:11 +00002614 case Iex_GetI:
2615 return isBogusAtom(e->Iex.GetI.ix);
sewardj95448072004-11-22 20:19:51 +00002616 case Iex_Binop:
2617 return isBogusAtom(e->Iex.Binop.arg1)
2618 || isBogusAtom(e->Iex.Binop.arg2);
2619 case Iex_Mux0X:
2620 return isBogusAtom(e->Iex.Mux0X.cond)
2621 || isBogusAtom(e->Iex.Mux0X.expr0)
2622 || isBogusAtom(e->Iex.Mux0X.exprX);
sewardj2e595852005-06-30 23:33:37 +00002623 case Iex_Load:
2624 return isBogusAtom(e->Iex.Load.addr);
sewardj95448072004-11-22 20:19:51 +00002625 case Iex_CCall:
2626 for (i = 0; e->Iex.CCall.args[i]; i++)
2627 if (isBogusAtom(e->Iex.CCall.args[i]))
2628 return True;
2629 return False;
2630 default:
2631 goto unhandled;
2632 }
sewardjd5204dc2004-12-31 01:16:11 +00002633 case Ist_Dirty:
2634 d = st->Ist.Dirty.details;
2635 for (i = 0; d->args[i]; i++)
2636 if (isBogusAtom(d->args[i]))
2637 return True;
2638 if (d->guard && isBogusAtom(d->guard))
2639 return True;
2640 if (d->mAddr && isBogusAtom(d->mAddr))
2641 return True;
2642 return False;
sewardj95448072004-11-22 20:19:51 +00002643 case Ist_Put:
2644 return isBogusAtom(st->Ist.Put.data);
sewardjd5204dc2004-12-31 01:16:11 +00002645 case Ist_PutI:
2646 return isBogusAtom(st->Ist.PutI.ix)
2647 || isBogusAtom(st->Ist.PutI.data);
sewardj2e595852005-06-30 23:33:37 +00002648 case Ist_Store:
2649 return isBogusAtom(st->Ist.Store.addr)
2650 || isBogusAtom(st->Ist.Store.data);
sewardj95448072004-11-22 20:19:51 +00002651 case Ist_Exit:
sewardjd5204dc2004-12-31 01:16:11 +00002652 return isBogusAtom(st->Ist.Exit.guard);
sewardj826ec492005-05-12 18:05:00 +00002653 case Ist_AbiHint:
2654 return isBogusAtom(st->Ist.AbiHint.base);
sewardj21dc3452005-03-21 00:27:41 +00002655 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00002656 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00002657 case Ist_MFence:
2658 return False;
sewardj95448072004-11-22 20:19:51 +00002659 default:
2660 unhandled:
2661 ppIRStmt(st);
2662 VG_(tool_panic)("hasBogusLiterals");
2663 }
2664}
njn25e49d8e72002-09-23 09:36:25 +00002665
njn25e49d8e72002-09-23 09:36:25 +00002666
njn51d827b2005-05-09 01:02:08 +00002667IRBB* MC_(instrument) ( IRBB* bb_in, VexGuestLayout* layout,
sewardjd54babf2005-03-21 00:55:49 +00002668 IRType gWordTy, IRType hWordTy )
sewardj95448072004-11-22 20:19:51 +00002669{
sewardj151b90d2005-07-06 19:42:23 +00002670 Bool verboze = False; //True;
2671 Bool bogus;
sewardjd5204dc2004-12-31 01:16:11 +00002672 Int i, j, first_stmt;
sewardj95448072004-11-22 20:19:51 +00002673 IRStmt* st;
sewardjd5204dc2004-12-31 01:16:11 +00002674 MCEnv mce;
sewardjd54babf2005-03-21 00:55:49 +00002675 IRBB* bb;
2676
2677 if (gWordTy != hWordTy) {
2678 /* We don't currently support this case. */
2679 VG_(tool_panic)("host/guest word size mismatch");
2680 }
njn25e49d8e72002-09-23 09:36:25 +00002681
sewardj6cf40ff2005-04-20 22:31:26 +00002682 /* Check we're not completely nuts */
2683 tl_assert(sizeof(UWord) == sizeof(void*));
2684 tl_assert(sizeof(Word) == sizeof(void*));
2685 tl_assert(sizeof(ULong) == 8);
2686 tl_assert(sizeof(Long) == 8);
2687 tl_assert(sizeof(UInt) == 4);
2688 tl_assert(sizeof(Int) == 4);
2689
sewardj95448072004-11-22 20:19:51 +00002690 /* Set up BB */
sewardjd54babf2005-03-21 00:55:49 +00002691 bb = emptyIRBB();
sewardj95448072004-11-22 20:19:51 +00002692 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
2693 bb->next = dopyIRExpr(bb_in->next);
2694 bb->jumpkind = bb_in->jumpkind;
njn25e49d8e72002-09-23 09:36:25 +00002695
sewardj95448072004-11-22 20:19:51 +00002696 /* Set up the running environment. Only .bb is modified as we go
2697 along. */
2698 mce.bb = bb;
2699 mce.layout = layout;
2700 mce.n_originalTmps = bb->tyenv->types_used;
2701 mce.hWordTy = hWordTy;
sewardjd5204dc2004-12-31 01:16:11 +00002702 mce.bogusLiterals = False;
sewardj95448072004-11-22 20:19:51 +00002703 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2704 for (i = 0; i < mce.n_originalTmps; i++)
2705 mce.tmpMap[i] = IRTemp_INVALID;
2706
sewardj151b90d2005-07-06 19:42:23 +00002707 /* Make a preliminary inspection of the statements, to see if there
2708 are any dodgy-looking literals. If there are, we generate
2709 extra-detailed (hence extra-expensive) instrumentation in
2710 places. Scan the whole bb even if dodgyness is found earlier,
2711 so that the flatness assertion is applied to all stmts. */
2712
2713 bogus = False;
sewardj95448072004-11-22 20:19:51 +00002714
2715 for (i = 0; i < bb_in->stmts_used; i++) {
sewardj151b90d2005-07-06 19:42:23 +00002716
sewardj95448072004-11-22 20:19:51 +00002717 st = bb_in->stmts[i];
sewardj21dc3452005-03-21 00:27:41 +00002718 tl_assert(st);
sewardj95448072004-11-22 20:19:51 +00002719 tl_assert(isFlatIRStmt(st));
2720
sewardj151b90d2005-07-06 19:42:23 +00002721 if (!bogus) {
2722 bogus = checkForBogusLiterals(st);
2723 if (0 && bogus) {
sewardj95448072004-11-22 20:19:51 +00002724 VG_(printf)("bogus: ");
2725 ppIRStmt(st);
2726 VG_(printf)("\n");
2727 }
2728 }
sewardjd5204dc2004-12-31 01:16:11 +00002729
sewardj151b90d2005-07-06 19:42:23 +00002730 }
2731
2732 mce.bogusLiterals = bogus;
2733
2734 /* Iterate over the stmts to generate instrumentation. */
2735
2736 for (i = 0; i < bb_in->stmts_used; i++) {
2737
2738 st = bb_in->stmts[i];
sewardj95448072004-11-22 20:19:51 +00002739 first_stmt = bb->stmts_used;
2740
2741 if (verboze) {
2742 ppIRStmt(st);
2743 VG_(printf)("\n\n");
2744 }
2745
sewardj29faa502005-03-16 18:20:21 +00002746 /* Generate instrumentation code for each stmt ... */
2747
sewardj95448072004-11-22 20:19:51 +00002748 switch (st->tag) {
2749
2750 case Ist_Tmp:
2751 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
2752 expr2vbits( &mce, st->Ist.Tmp.data) );
njn25e49d8e72002-09-23 09:36:25 +00002753 break;
2754
sewardj95448072004-11-22 20:19:51 +00002755 case Ist_Put:
2756 do_shadow_PUT( &mce,
2757 st->Ist.Put.offset,
2758 st->Ist.Put.data,
2759 NULL /* shadow atom */ );
njn25e49d8e72002-09-23 09:36:25 +00002760 break;
2761
sewardj95448072004-11-22 20:19:51 +00002762 case Ist_PutI:
2763 do_shadow_PUTI( &mce,
2764 st->Ist.PutI.descr,
2765 st->Ist.PutI.ix,
2766 st->Ist.PutI.bias,
2767 st->Ist.PutI.data );
njn25e49d8e72002-09-23 09:36:25 +00002768 break;
2769
sewardj2e595852005-06-30 23:33:37 +00002770 case Ist_Store:
2771 do_shadow_Store( &mce, st->Ist.Store.end,
2772 st->Ist.Store.addr, 0/* addr bias */,
2773 st->Ist.Store.data,
2774 NULL /* shadow data */ );
njn25e49d8e72002-09-23 09:36:25 +00002775 break;
2776
sewardj95448072004-11-22 20:19:51 +00002777 case Ist_Exit:
sewardjd5204dc2004-12-31 01:16:11 +00002778 complainIfUndefined( &mce, st->Ist.Exit.guard );
njn25e49d8e72002-09-23 09:36:25 +00002779 break;
2780
sewardj21dc3452005-03-21 00:27:41 +00002781 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00002782 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00002783 case Ist_MFence:
2784 break;
2785
sewardj95448072004-11-22 20:19:51 +00002786 case Ist_Dirty:
2787 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
njn25e49d8e72002-09-23 09:36:25 +00002788 break;
2789
sewardj826ec492005-05-12 18:05:00 +00002790 case Ist_AbiHint:
2791 do_AbiHint( &mce, st->Ist.AbiHint.base, st->Ist.AbiHint.len );
2792 break;
2793
njn25e49d8e72002-09-23 09:36:25 +00002794 default:
sewardj95448072004-11-22 20:19:51 +00002795 VG_(printf)("\n");
2796 ppIRStmt(st);
2797 VG_(printf)("\n");
2798 VG_(tool_panic)("memcheck: unhandled IRStmt");
2799
2800 } /* switch (st->tag) */
2801
2802 if (verboze) {
2803 for (j = first_stmt; j < bb->stmts_used; j++) {
2804 VG_(printf)(" ");
2805 ppIRStmt(bb->stmts[j]);
2806 VG_(printf)("\n");
2807 }
2808 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00002809 }
sewardj95448072004-11-22 20:19:51 +00002810
sewardj29faa502005-03-16 18:20:21 +00002811 /* ... and finally copy the stmt itself to the output. */
sewardj95448072004-11-22 20:19:51 +00002812 addStmtToIRBB(bb, st);
2813
njn25e49d8e72002-09-23 09:36:25 +00002814 }
njn25e49d8e72002-09-23 09:36:25 +00002815
sewardj95448072004-11-22 20:19:51 +00002816 /* Now we need to complain if the jump target is undefined. */
2817 first_stmt = bb->stmts_used;
njn25e49d8e72002-09-23 09:36:25 +00002818
sewardj95448072004-11-22 20:19:51 +00002819 if (verboze) {
2820 VG_(printf)("bb->next = ");
2821 ppIRExpr(bb->next);
2822 VG_(printf)("\n\n");
2823 }
njn25e49d8e72002-09-23 09:36:25 +00002824
sewardj95448072004-11-22 20:19:51 +00002825 complainIfUndefined( &mce, bb->next );
njn25e49d8e72002-09-23 09:36:25 +00002826
sewardj95448072004-11-22 20:19:51 +00002827 if (verboze) {
2828 for (j = first_stmt; j < bb->stmts_used; j++) {
2829 VG_(printf)(" ");
2830 ppIRStmt(bb->stmts[j]);
2831 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00002832 }
sewardj95448072004-11-22 20:19:51 +00002833 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00002834 }
njn25e49d8e72002-09-23 09:36:25 +00002835
sewardj95448072004-11-22 20:19:51 +00002836 return bb;
2837}
njn25e49d8e72002-09-23 09:36:25 +00002838
2839/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00002840/*--- end mc_translate.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00002841/*--------------------------------------------------------------------*/