blob: 2fb8d4478c6750173d2a2cda3fbf8b8b1a444050 [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
sewardj992dff92005-10-07 11:08:55 +000041/* This file implements the Memcheck instrumentation, and in
42 particular contains the core of its undefined value detection
43 machinery. For a comprehensive background of the terminology,
44 algorithms and rationale used herein, read:
45
46 Using Valgrind to detect undefined value errors with
47 bit-precision
48
49 Julian Seward and Nicholas Nethercote
50
51 2005 USENIX Annual Technical Conference (General Track),
52 Anaheim, CA, USA, April 10-15, 2005.
53*/
54
sewardj95448072004-11-22 20:19:51 +000055/*------------------------------------------------------------*/
56/*--- Forward decls ---*/
57/*------------------------------------------------------------*/
58
59struct _MCEnv;
60
61static IRType shadowType ( IRType ty );
62static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
63
64
65/*------------------------------------------------------------*/
66/*--- Memcheck running state, and tmp management. ---*/
67/*------------------------------------------------------------*/
68
69/* Carries around state during memcheck instrumentation. */
70typedef
71 struct _MCEnv {
72 /* MODIFIED: the bb being constructed. IRStmts are added. */
73 IRBB* bb;
74
75 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
76 original temps to their current their current shadow temp.
77 Initially all entries are IRTemp_INVALID. Entries are added
78 lazily since many original temps are not used due to
79 optimisation prior to instrumentation. Note that floating
80 point original tmps are shadowed by integer tmps of the same
81 size, and Bit-typed original tmps are shadowed by the type
82 Ity_I8. See comment below. */
83 IRTemp* tmpMap;
84 Int n_originalTmps; /* for range checking */
85
sewardjd5204dc2004-12-31 01:16:11 +000086 /* MODIFIED: indicates whether "bogus" literals have so far been
87 found. Starts off False, and may change to True. */
88 Bool bogusLiterals;
89
sewardj95448072004-11-22 20:19:51 +000090 /* READONLY: the guest layout. This indicates which parts of
91 the guest state should be regarded as 'always defined'. */
92 VexGuestLayout* layout;
93 /* READONLY: the host word type. Needed for constructing
94 arguments of type 'HWord' to be passed to helper functions.
95 Ity_I32 or Ity_I64 only. */
96 IRType hWordTy;
97 }
98 MCEnv;
99
100/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
101 demand), as they are encountered. This is for two reasons.
102
103 (1) (less important reason): Many original tmps are unused due to
104 initial IR optimisation, and we do not want to spaces in tables
105 tracking them.
106
107 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
108 table indexed [0 .. n_types-1], which gives the current shadow for
109 each original tmp, or INVALID_IRTEMP if none is so far assigned.
110 It is necessary to support making multiple assignments to a shadow
111 -- specifically, after testing a shadow for definedness, it needs
112 to be made defined. But IR's SSA property disallows this.
113
114 (2) (more important reason): Therefore, when a shadow needs to get
115 a new value, a new temporary is created, the value is assigned to
116 that, and the tmpMap is updated to reflect the new binding.
117
118 A corollary is that if the tmpMap maps a given tmp to
119 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
120 there's a read-before-write error in the original tmps. The IR
121 sanity checker should catch all such anomalies, however.
njn25e49d8e72002-09-23 09:36:25 +0000122*/
sewardj95448072004-11-22 20:19:51 +0000123
124/* Find the tmp currently shadowing the given original tmp. If none
125 so far exists, allocate one. */
126static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
njn25e49d8e72002-09-23 09:36:25 +0000127{
sewardj95448072004-11-22 20:19:51 +0000128 tl_assert(orig < mce->n_originalTmps);
129 if (mce->tmpMap[orig] == IRTemp_INVALID) {
130 mce->tmpMap[orig]
131 = newIRTemp(mce->bb->tyenv,
132 shadowType(mce->bb->tyenv->types[orig]));
njn25e49d8e72002-09-23 09:36:25 +0000133 }
sewardj95448072004-11-22 20:19:51 +0000134 return mce->tmpMap[orig];
njn25e49d8e72002-09-23 09:36:25 +0000135}
136
sewardj95448072004-11-22 20:19:51 +0000137/* Allocate a new shadow for the given original tmp. This means any
138 previous shadow is abandoned. This is needed because it is
139 necessary to give a new value to a shadow once it has been tested
140 for undefinedness, but unfortunately IR's SSA property disallows
141 this. Instead we must abandon the old shadow, allocate a new one
142 and use that instead. */
143static void newShadowTmp ( MCEnv* mce, IRTemp orig )
njn25e49d8e72002-09-23 09:36:25 +0000144{
sewardj95448072004-11-22 20:19:51 +0000145 tl_assert(orig < mce->n_originalTmps);
146 mce->tmpMap[orig]
147 = newIRTemp(mce->bb->tyenv,
148 shadowType(mce->bb->tyenv->types[orig]));
149}
150
151
152/*------------------------------------------------------------*/
153/*--- IRAtoms -- a subset of IRExprs ---*/
154/*------------------------------------------------------------*/
155
156/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj710d6c22005-03-20 18:55:15 +0000157 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardj95448072004-11-22 20:19:51 +0000158 input, most of this code deals in atoms. Usefully, a value atom
159 always has a V-value which is also an atom: constants are shadowed
160 by constants, and temps are shadowed by the corresponding shadow
161 temporary. */
162
163typedef IRExpr IRAtom;
164
165/* (used for sanity checks only): is this an atom which looks
166 like it's from original code? */
167static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
168{
169 if (a1->tag == Iex_Const)
170 return True;
171 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
172 return True;
173 return False;
174}
175
176/* (used for sanity checks only): is this an atom which looks
177 like it's from shadow code? */
178static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
179{
180 if (a1->tag == Iex_Const)
181 return True;
182 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
183 return True;
184 return False;
185}
186
187/* (used for sanity checks only): check that both args are atoms and
188 are identically-kinded. */
189static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
190{
sewardjbef552a2005-08-30 12:54:36 +0000191 if (a1->tag == Iex_Tmp && a2->tag == Iex_Tmp)
sewardj95448072004-11-22 20:19:51 +0000192 return True;
sewardjbef552a2005-08-30 12:54:36 +0000193 if (a1->tag == Iex_Const && a2->tag == Iex_Const)
sewardj95448072004-11-22 20:19:51 +0000194 return True;
195 return False;
196}
197
198
199/*------------------------------------------------------------*/
200/*--- Type management ---*/
201/*------------------------------------------------------------*/
202
203/* Shadow state is always accessed using integer types. This returns
204 an integer type with the same size (as per sizeofIRType) as the
205 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj3245c912004-12-10 14:58:26 +0000206 I64, V128. */
sewardj95448072004-11-22 20:19:51 +0000207
208static IRType shadowType ( IRType ty )
209{
210 switch (ty) {
211 case Ity_I1:
212 case Ity_I8:
213 case Ity_I16:
214 case Ity_I32:
sewardj6cf40ff2005-04-20 22:31:26 +0000215 case Ity_I64:
216 case Ity_I128: return ty;
sewardj3245c912004-12-10 14:58:26 +0000217 case Ity_F32: return Ity_I32;
218 case Ity_F64: return Ity_I64;
219 case Ity_V128: return Ity_V128;
sewardj95448072004-11-22 20:19:51 +0000220 default: ppIRType(ty);
221 VG_(tool_panic)("memcheck:shadowType");
222 }
223}
224
225/* Produce a 'defined' value of the given shadow type. Should only be
226 supplied shadow types (Bit/I8/I16/I32/UI64). */
227static IRExpr* definedOfType ( IRType ty ) {
228 switch (ty) {
sewardj170ee212004-12-10 18:57:51 +0000229 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
230 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
231 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
232 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
233 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
234 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
sewardj95448072004-11-22 20:19:51 +0000235 default: VG_(tool_panic)("memcheck:definedOfType");
njn25e49d8e72002-09-23 09:36:25 +0000236 }
237}
238
239
sewardj95448072004-11-22 20:19:51 +0000240/*------------------------------------------------------------*/
241/*--- Constructing IR fragments ---*/
242/*------------------------------------------------------------*/
243
244/* assign value to tmp */
245#define assign(_bb,_tmp,_expr) \
246 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
247
248/* add stmt to a bb */
249#define stmt(_bb,_stmt) \
250 addStmtToIRBB((_bb), (_stmt))
251
252/* build various kinds of expressions */
253#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
254#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
255#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
256#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
257#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
258#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj170ee212004-12-10 18:57:51 +0000259#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardj95448072004-11-22 20:19:51 +0000260#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
261
262/* bind the given expression to a new temporary, and return the
263 temporary. This effectively converts an arbitrary expression into
264 an atom. */
265static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
266 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
267 assign(mce->bb, t, e);
268 return mkexpr(t);
269}
270
271
272/*------------------------------------------------------------*/
273/*--- Constructing definedness primitive ops ---*/
274/*------------------------------------------------------------*/
275
276/* --------- Defined-if-either-defined --------- */
277
278static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
279 tl_assert(isShadowAtom(mce,a1));
280 tl_assert(isShadowAtom(mce,a2));
281 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
282}
283
284static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
285 tl_assert(isShadowAtom(mce,a1));
286 tl_assert(isShadowAtom(mce,a2));
287 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
288}
289
290static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
291 tl_assert(isShadowAtom(mce,a1));
292 tl_assert(isShadowAtom(mce,a2));
293 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
294}
295
sewardj7010f6e2004-12-10 13:35:22 +0000296static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
297 tl_assert(isShadowAtom(mce,a1));
298 tl_assert(isShadowAtom(mce,a2));
299 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
300}
301
sewardj20d38f22005-02-07 23:50:18 +0000302static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj170ee212004-12-10 18:57:51 +0000303 tl_assert(isShadowAtom(mce,a1));
304 tl_assert(isShadowAtom(mce,a2));
sewardj20d38f22005-02-07 23:50:18 +0000305 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj170ee212004-12-10 18:57:51 +0000306}
307
sewardj95448072004-11-22 20:19:51 +0000308/* --------- Undefined-if-either-undefined --------- */
309
310static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
311 tl_assert(isShadowAtom(mce,a1));
312 tl_assert(isShadowAtom(mce,a2));
313 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
314}
315
316static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
317 tl_assert(isShadowAtom(mce,a1));
318 tl_assert(isShadowAtom(mce,a2));
319 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
320}
321
322static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
323 tl_assert(isShadowAtom(mce,a1));
324 tl_assert(isShadowAtom(mce,a2));
325 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
326}
327
328static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
329 tl_assert(isShadowAtom(mce,a1));
330 tl_assert(isShadowAtom(mce,a2));
331 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
332}
333
sewardj20d38f22005-02-07 23:50:18 +0000334static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj3245c912004-12-10 14:58:26 +0000335 tl_assert(isShadowAtom(mce,a1));
336 tl_assert(isShadowAtom(mce,a2));
sewardj20d38f22005-02-07 23:50:18 +0000337 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj3245c912004-12-10 14:58:26 +0000338}
339
sewardje50a1b12004-12-17 01:24:54 +0000340static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardj95448072004-11-22 20:19:51 +0000341 switch (vty) {
sewardje50a1b12004-12-17 01:24:54 +0000342 case Ity_I8: return mkUifU8(mce, a1, a2);
sewardja1d93302004-12-12 16:45:06 +0000343 case Ity_I16: return mkUifU16(mce, a1, a2);
344 case Ity_I32: return mkUifU32(mce, a1, a2);
345 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardj20d38f22005-02-07 23:50:18 +0000346 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardj95448072004-11-22 20:19:51 +0000347 default:
348 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
349 VG_(tool_panic)("memcheck:mkUifU");
njn25e49d8e72002-09-23 09:36:25 +0000350 }
351}
352
sewardj95448072004-11-22 20:19:51 +0000353/* --------- The Left-family of operations. --------- */
njn25e49d8e72002-09-23 09:36:25 +0000354
sewardj95448072004-11-22 20:19:51 +0000355static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
356 tl_assert(isShadowAtom(mce,a1));
357 /* It's safe to duplicate a1 since it's only an atom */
358 return assignNew(mce, Ity_I8,
359 binop(Iop_Or8, a1,
360 assignNew(mce, Ity_I8,
sewardj37c31cc2005-04-26 23:49:24 +0000361 unop(Iop_Neg8, a1))));
sewardj95448072004-11-22 20:19:51 +0000362}
363
364static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
365 tl_assert(isShadowAtom(mce,a1));
366 /* It's safe to duplicate a1 since it's only an atom */
367 return assignNew(mce, Ity_I16,
368 binop(Iop_Or16, a1,
369 assignNew(mce, Ity_I16,
sewardj37c31cc2005-04-26 23:49:24 +0000370 unop(Iop_Neg16, a1))));
sewardj95448072004-11-22 20:19:51 +0000371}
372
373static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
374 tl_assert(isShadowAtom(mce,a1));
375 /* It's safe to duplicate a1 since it's only an atom */
376 return assignNew(mce, Ity_I32,
377 binop(Iop_Or32, a1,
378 assignNew(mce, Ity_I32,
sewardj37c31cc2005-04-26 23:49:24 +0000379 unop(Iop_Neg32, a1))));
sewardj95448072004-11-22 20:19:51 +0000380}
381
sewardj681be302005-01-15 20:43:58 +0000382static IRAtom* mkLeft64 ( MCEnv* mce, IRAtom* a1 ) {
383 tl_assert(isShadowAtom(mce,a1));
384 /* It's safe to duplicate a1 since it's only an atom */
385 return assignNew(mce, Ity_I64,
386 binop(Iop_Or64, a1,
387 assignNew(mce, Ity_I64,
sewardj37c31cc2005-04-26 23:49:24 +0000388 unop(Iop_Neg64, a1))));
sewardj681be302005-01-15 20:43:58 +0000389}
390
sewardj95448072004-11-22 20:19:51 +0000391/* --------- 'Improvement' functions for AND/OR. --------- */
392
393/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
394 defined (0); all other -> undefined (1).
395*/
396static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
njn25e49d8e72002-09-23 09:36:25 +0000397{
sewardj95448072004-11-22 20:19:51 +0000398 tl_assert(isOriginalAtom(mce, data));
399 tl_assert(isShadowAtom(mce, vbits));
400 tl_assert(sameKindedAtoms(data, vbits));
401 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
402}
njn25e49d8e72002-09-23 09:36:25 +0000403
sewardj95448072004-11-22 20:19:51 +0000404static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
405{
406 tl_assert(isOriginalAtom(mce, data));
407 tl_assert(isShadowAtom(mce, vbits));
408 tl_assert(sameKindedAtoms(data, vbits));
409 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
410}
njn25e49d8e72002-09-23 09:36:25 +0000411
sewardj95448072004-11-22 20:19:51 +0000412static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
413{
414 tl_assert(isOriginalAtom(mce, data));
415 tl_assert(isShadowAtom(mce, vbits));
416 tl_assert(sameKindedAtoms(data, vbits));
417 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
418}
njn25e49d8e72002-09-23 09:36:25 +0000419
sewardj7010f6e2004-12-10 13:35:22 +0000420static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
421{
422 tl_assert(isOriginalAtom(mce, data));
423 tl_assert(isShadowAtom(mce, vbits));
424 tl_assert(sameKindedAtoms(data, vbits));
425 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
426}
427
sewardj20d38f22005-02-07 23:50:18 +0000428static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj170ee212004-12-10 18:57:51 +0000429{
430 tl_assert(isOriginalAtom(mce, data));
431 tl_assert(isShadowAtom(mce, vbits));
432 tl_assert(sameKindedAtoms(data, vbits));
sewardj20d38f22005-02-07 23:50:18 +0000433 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj170ee212004-12-10 18:57:51 +0000434}
435
sewardj95448072004-11-22 20:19:51 +0000436/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
437 defined (0); all other -> undefined (1).
438*/
439static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
440{
441 tl_assert(isOriginalAtom(mce, data));
442 tl_assert(isShadowAtom(mce, vbits));
443 tl_assert(sameKindedAtoms(data, vbits));
444 return assignNew(
445 mce, Ity_I8,
446 binop(Iop_Or8,
447 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
448 vbits) );
449}
njn25e49d8e72002-09-23 09:36:25 +0000450
sewardj95448072004-11-22 20:19:51 +0000451static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
452{
453 tl_assert(isOriginalAtom(mce, data));
454 tl_assert(isShadowAtom(mce, vbits));
455 tl_assert(sameKindedAtoms(data, vbits));
456 return assignNew(
457 mce, Ity_I16,
458 binop(Iop_Or16,
459 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
460 vbits) );
461}
njn25e49d8e72002-09-23 09:36:25 +0000462
sewardj95448072004-11-22 20:19:51 +0000463static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
464{
465 tl_assert(isOriginalAtom(mce, data));
466 tl_assert(isShadowAtom(mce, vbits));
467 tl_assert(sameKindedAtoms(data, vbits));
468 return assignNew(
469 mce, Ity_I32,
470 binop(Iop_Or32,
471 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
472 vbits) );
473}
474
sewardj7010f6e2004-12-10 13:35:22 +0000475static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
476{
477 tl_assert(isOriginalAtom(mce, data));
478 tl_assert(isShadowAtom(mce, vbits));
479 tl_assert(sameKindedAtoms(data, vbits));
480 return assignNew(
481 mce, Ity_I64,
482 binop(Iop_Or64,
483 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
484 vbits) );
485}
486
sewardj20d38f22005-02-07 23:50:18 +0000487static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj170ee212004-12-10 18:57:51 +0000488{
489 tl_assert(isOriginalAtom(mce, data));
490 tl_assert(isShadowAtom(mce, vbits));
491 tl_assert(sameKindedAtoms(data, vbits));
492 return assignNew(
493 mce, Ity_V128,
sewardj20d38f22005-02-07 23:50:18 +0000494 binop(Iop_OrV128,
495 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj170ee212004-12-10 18:57:51 +0000496 vbits) );
497}
498
sewardj95448072004-11-22 20:19:51 +0000499/* --------- Pessimising casts. --------- */
500
501static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
502{
sewardj7cf97ee2004-11-28 14:25:01 +0000503 IRType ty;
504 IRAtom* tmp1;
sewardj95448072004-11-22 20:19:51 +0000505 /* Note, dst_ty is a shadow type, not an original type. */
506 /* First of all, collapse vbits down to a single bit. */
507 tl_assert(isShadowAtom(mce,vbits));
sewardj7cf97ee2004-11-28 14:25:01 +0000508 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
509 tmp1 = NULL;
sewardj95448072004-11-22 20:19:51 +0000510 switch (ty) {
511 case Ity_I1:
512 tmp1 = vbits;
njn25e49d8e72002-09-23 09:36:25 +0000513 break;
sewardj95448072004-11-22 20:19:51 +0000514 case Ity_I8:
sewardj37c31cc2005-04-26 23:49:24 +0000515 tmp1 = assignNew(mce, Ity_I1, unop(Iop_CmpNEZ8, vbits));
sewardj95448072004-11-22 20:19:51 +0000516 break;
517 case Ity_I16:
sewardj37c31cc2005-04-26 23:49:24 +0000518 tmp1 = assignNew(mce, Ity_I1, unop(Iop_CmpNEZ16, vbits));
sewardj95448072004-11-22 20:19:51 +0000519 break;
520 case Ity_I32:
sewardj37c31cc2005-04-26 23:49:24 +0000521 tmp1 = assignNew(mce, Ity_I1, unop(Iop_CmpNEZ32, vbits));
sewardj95448072004-11-22 20:19:51 +0000522 break;
523 case Ity_I64:
sewardj37c31cc2005-04-26 23:49:24 +0000524 tmp1 = assignNew(mce, Ity_I1, unop(Iop_CmpNEZ64, vbits));
sewardj95448072004-11-22 20:19:51 +0000525 break;
sewardj69a13322005-04-23 01:14:51 +0000526 case Ity_I128: {
527 /* Gah. Chop it in half, OR the halves together, and compare
528 that with zero. */
529 IRAtom* tmp2 = assignNew(mce, Ity_I64, unop(Iop_128HIto64, vbits));
530 IRAtom* tmp3 = assignNew(mce, Ity_I64, unop(Iop_128to64, vbits));
531 IRAtom* tmp4 = assignNew(mce, Ity_I64, binop(Iop_Or64, tmp2, tmp3));
532 tmp1 = assignNew(mce, Ity_I1,
sewardj37c31cc2005-04-26 23:49:24 +0000533 unop(Iop_CmpNEZ64, tmp4));
sewardj69a13322005-04-23 01:14:51 +0000534 break;
535 }
sewardj95448072004-11-22 20:19:51 +0000536 default:
sewardj69a13322005-04-23 01:14:51 +0000537 ppIRType(ty);
sewardj95448072004-11-22 20:19:51 +0000538 VG_(tool_panic)("mkPCastTo(1)");
539 }
540 tl_assert(tmp1);
541 /* Now widen up to the dst type. */
542 switch (dst_ty) {
543 case Ity_I1:
544 return tmp1;
545 case Ity_I8:
546 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
547 case Ity_I16:
548 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
549 case Ity_I32:
550 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
551 case Ity_I64:
552 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardja1d93302004-12-12 16:45:06 +0000553 case Ity_V128:
554 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj20d38f22005-02-07 23:50:18 +0000555 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardja1d93302004-12-12 16:45:06 +0000556 return tmp1;
sewardj69a13322005-04-23 01:14:51 +0000557 case Ity_I128:
558 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
559 tmp1 = assignNew(mce, Ity_I128, binop(Iop_64HLto128, tmp1, tmp1));
560 return tmp1;
sewardj95448072004-11-22 20:19:51 +0000561 default:
562 ppIRType(dst_ty);
563 VG_(tool_panic)("mkPCastTo(2)");
564 }
565}
566
sewardjd5204dc2004-12-31 01:16:11 +0000567/* --------- Accurate interpretation of CmpEQ/CmpNE. --------- */
568/*
569 Normally, we can do CmpEQ/CmpNE by doing UifU on the arguments, and
570 PCasting to Ity_U1. However, sometimes it is necessary to be more
571 accurate. The insight is that the result is defined if two
572 corresponding bits can be found, one from each argument, so that
573 both bits are defined but are different -- that makes EQ say "No"
574 and NE say "Yes". Hence, we compute an improvement term and DifD
575 it onto the "normal" (UifU) result.
576
577 The result is:
578
579 PCastTo<1> (
sewardje6f8af42005-07-06 18:48:59 +0000580 -- naive version
581 PCastTo<sz>( UifU<sz>(vxx, vyy) )
582
sewardjd5204dc2004-12-31 01:16:11 +0000583 `DifD<sz>`
sewardje6f8af42005-07-06 18:48:59 +0000584
585 -- improvement term
586 PCastTo<sz>( PCast<sz>( CmpEQ<sz> ( vec, 1...1 ) ) )
sewardjd5204dc2004-12-31 01:16:11 +0000587 )
sewardje6f8af42005-07-06 18:48:59 +0000588
sewardjd5204dc2004-12-31 01:16:11 +0000589 where
590 vec contains 0 (defined) bits where the corresponding arg bits
sewardje6f8af42005-07-06 18:48:59 +0000591 are defined but different, and 1 bits otherwise.
sewardjd5204dc2004-12-31 01:16:11 +0000592
sewardje6f8af42005-07-06 18:48:59 +0000593 vec = Or<sz>( vxx, // 0 iff bit defined
594 vyy, // 0 iff bit defined
595 Not<sz>(Xor<sz>( xx, yy )) // 0 iff bits different
596 )
597
598 If any bit of vec is 0, the result is defined and so the
599 improvement term should produce 0...0, else it should produce
600 1...1.
601
602 Hence require for the improvement term:
603
604 if vec == 1...1 then 1...1 else 0...0
605 ->
606 PCast<sz>( CmpEQ<sz> ( vec, 1...1 ) )
607
608 This was extensively re-analysed and checked on 6 July 05.
sewardjd5204dc2004-12-31 01:16:11 +0000609*/
610static IRAtom* expensiveCmpEQorNE ( MCEnv* mce,
611 IRType ty,
612 IRAtom* vxx, IRAtom* vyy,
613 IRAtom* xx, IRAtom* yy )
614{
sewardje6f8af42005-07-06 18:48:59 +0000615 IRAtom *naive, *vec, *improvement_term;
616 IRAtom *improved, *final_cast, *top;
617 IROp opDIFD, opUIFU, opXOR, opNOT, opCMP, opOR;
sewardjd5204dc2004-12-31 01:16:11 +0000618
619 tl_assert(isShadowAtom(mce,vxx));
620 tl_assert(isShadowAtom(mce,vyy));
621 tl_assert(isOriginalAtom(mce,xx));
622 tl_assert(isOriginalAtom(mce,yy));
623 tl_assert(sameKindedAtoms(vxx,xx));
624 tl_assert(sameKindedAtoms(vyy,yy));
625
626 switch (ty) {
627 case Ity_I32:
sewardje6f8af42005-07-06 18:48:59 +0000628 opOR = Iop_Or32;
sewardjd5204dc2004-12-31 01:16:11 +0000629 opDIFD = Iop_And32;
630 opUIFU = Iop_Or32;
631 opNOT = Iop_Not32;
632 opXOR = Iop_Xor32;
633 opCMP = Iop_CmpEQ32;
634 top = mkU32(0xFFFFFFFF);
635 break;
tomcd986332005-04-26 07:44:48 +0000636 case Ity_I64:
sewardje6f8af42005-07-06 18:48:59 +0000637 opOR = Iop_Or64;
tomcd986332005-04-26 07:44:48 +0000638 opDIFD = Iop_And64;
639 opUIFU = Iop_Or64;
640 opNOT = Iop_Not64;
641 opXOR = Iop_Xor64;
642 opCMP = Iop_CmpEQ64;
sewardj37c31cc2005-04-26 23:49:24 +0000643 top = mkU64(0xFFFFFFFFFFFFFFFFULL);
tomcd986332005-04-26 07:44:48 +0000644 break;
sewardjd5204dc2004-12-31 01:16:11 +0000645 default:
646 VG_(tool_panic)("expensiveCmpEQorNE");
647 }
648
649 naive
650 = mkPCastTo(mce,ty, assignNew(mce, ty, binop(opUIFU, vxx, vyy)));
651
652 vec
653 = assignNew(
654 mce,ty,
sewardje6f8af42005-07-06 18:48:59 +0000655 binop( opOR,
656 assignNew(mce,ty, binop(opOR, vxx, vyy)),
sewardjd5204dc2004-12-31 01:16:11 +0000657 assignNew(
658 mce,ty,
659 unop( opNOT,
660 assignNew(mce,ty, binop(opXOR, xx, yy))))));
661
sewardje6f8af42005-07-06 18:48:59 +0000662 improvement_term
sewardjd5204dc2004-12-31 01:16:11 +0000663 = mkPCastTo( mce,ty, assignNew(mce,Ity_I1, binop(opCMP, vec, top)));
664
665 improved
sewardje6f8af42005-07-06 18:48:59 +0000666 = assignNew( mce,ty, binop(opDIFD, naive, improvement_term) );
sewardjd5204dc2004-12-31 01:16:11 +0000667
668 final_cast
669 = mkPCastTo( mce, Ity_I1, improved );
670
671 return final_cast;
672}
673
sewardj95448072004-11-22 20:19:51 +0000674
sewardj992dff92005-10-07 11:08:55 +0000675/* --------- Semi-accurate interpretation of CmpORD. --------- */
676
677/* CmpORD32{S,U} does PowerPC-style 3-way comparisons:
678
679 CmpORD32S(x,y) = 1<<3 if x <s y
680 = 1<<2 if x >s y
681 = 1<<1 if x == y
682
683 and similarly the unsigned variant. The default interpretation is:
684
685 CmpORD32{S,U}#(x,y,x#,y#) = PCast(x# `UifU` y#)
686 & (7<<1)
687
688 The "& (7<<1)" reflects the fact that all result bits except 3,2,1
689 are zero and therefore defined (viz, zero).
690*/
691static IRAtom* doCmpORD32 ( MCEnv* mce,
692 IROp cmp_op,
693 IRAtom* xxhash, IRAtom* yyhash,
694 IRAtom* xx, IRAtom* yy )
695{
696 tl_assert(isShadowAtom(mce,xxhash));
697 tl_assert(isShadowAtom(mce,yyhash));
698 tl_assert(isOriginalAtom(mce,xx));
699 tl_assert(isOriginalAtom(mce,yy));
700 tl_assert(sameKindedAtoms(xxhash,xx));
701 tl_assert(sameKindedAtoms(yyhash,yy));
702 tl_assert(cmp_op == Iop_CmpORD32S || cmp_op == Iop_CmpORD32U);
703
704 return
705 binop(
706 Iop_And32,
707 assignNew(
708 mce,Ity_I32,
709 mkPCastTo( mce,Ity_I32,
710 assignNew( mce,Ity_I32,
711 mkUifU32(mce, xxhash,yyhash))) ),
712 mkU32(7<<1)
713 );
714}
715
716
sewardj95448072004-11-22 20:19:51 +0000717/*------------------------------------------------------------*/
718/*--- Emit a test and complaint if something is undefined. ---*/
719/*------------------------------------------------------------*/
720
721/* Set the annotations on a dirty helper to indicate that the stack
722 pointer and instruction pointers might be read. This is the
723 behaviour of all 'emit-a-complaint' style functions we might
724 call. */
725
726static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
727 di->nFxState = 2;
728 di->fxState[0].fx = Ifx_Read;
729 di->fxState[0].offset = mce->layout->offset_SP;
730 di->fxState[0].size = mce->layout->sizeof_SP;
731 di->fxState[1].fx = Ifx_Read;
732 di->fxState[1].offset = mce->layout->offset_IP;
733 di->fxState[1].size = mce->layout->sizeof_IP;
734}
735
736
737/* Check the supplied **original** atom for undefinedness, and emit a
738 complaint if so. Once that happens, mark it as defined. This is
739 possible because the atom is either a tmp or literal. If it's a
740 tmp, it will be shadowed by a tmp, and so we can set the shadow to
741 be defined. In fact as mentioned above, we will have to allocate a
742 new tmp to carry the new 'defined' shadow value, and update the
743 original->tmp mapping accordingly; we cannot simply assign a new
744 value to an existing shadow tmp as this breaks SSAness -- resulting
745 in the post-instrumentation sanity checker spluttering in disapproval.
746*/
747static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
748{
sewardj7cf97ee2004-11-28 14:25:01 +0000749 IRAtom* vatom;
750 IRType ty;
751 Int sz;
752 IRDirty* di;
753 IRAtom* cond;
754
sewardj95448072004-11-22 20:19:51 +0000755 /* Since the original expression is atomic, there's no duplicated
756 work generated by making multiple V-expressions for it. So we
757 don't really care about the possibility that someone else may
758 also create a V-interpretion for it. */
759 tl_assert(isOriginalAtom(mce, atom));
sewardj7cf97ee2004-11-28 14:25:01 +0000760 vatom = expr2vbits( mce, atom );
sewardj95448072004-11-22 20:19:51 +0000761 tl_assert(isShadowAtom(mce, vatom));
762 tl_assert(sameKindedAtoms(atom, vatom));
763
sewardj7cf97ee2004-11-28 14:25:01 +0000764 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj95448072004-11-22 20:19:51 +0000765
766 /* sz is only used for constructing the error message */
sewardj7cf97ee2004-11-28 14:25:01 +0000767 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardj95448072004-11-22 20:19:51 +0000768
sewardj7cf97ee2004-11-28 14:25:01 +0000769 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardj95448072004-11-22 20:19:51 +0000770 /* cond will be 0 if all defined, and 1 if any not defined. */
771
sewardj95448072004-11-22 20:19:51 +0000772 switch (sz) {
773 case 0:
774 di = unsafeIRDirty_0_N( 0/*regparms*/,
775 "MC_(helperc_value_check0_fail)",
776 &MC_(helperc_value_check0_fail),
777 mkIRExprVec_0()
778 );
779 break;
780 case 1:
781 di = unsafeIRDirty_0_N( 0/*regparms*/,
782 "MC_(helperc_value_check1_fail)",
783 &MC_(helperc_value_check1_fail),
784 mkIRExprVec_0()
785 );
786 break;
787 case 4:
788 di = unsafeIRDirty_0_N( 0/*regparms*/,
789 "MC_(helperc_value_check4_fail)",
790 &MC_(helperc_value_check4_fail),
791 mkIRExprVec_0()
792 );
793 break;
sewardj11bcc4e2005-04-23 22:38:38 +0000794 case 8:
795 di = unsafeIRDirty_0_N( 0/*regparms*/,
796 "MC_(helperc_value_check8_fail)",
797 &MC_(helperc_value_check8_fail),
798 mkIRExprVec_0()
799 );
800 break;
sewardj95448072004-11-22 20:19:51 +0000801 default:
802 di = unsafeIRDirty_0_N( 1/*regparms*/,
803 "MC_(helperc_complain_undef)",
804 &MC_(helperc_complain_undef),
805 mkIRExprVec_1( mkIRExpr_HWord( sz ))
806 );
807 break;
808 }
809 di->guard = cond;
810 setHelperAnns( mce, di );
811 stmt( mce->bb, IRStmt_Dirty(di));
812
813 /* Set the shadow tmp to be defined. First, update the
814 orig->shadow tmp mapping to reflect the fact that this shadow is
815 getting a new value. */
sewardj710d6c22005-03-20 18:55:15 +0000816 tl_assert(isIRAtom(vatom));
sewardj95448072004-11-22 20:19:51 +0000817 /* sameKindedAtoms ... */
818 if (vatom->tag == Iex_Tmp) {
819 tl_assert(atom->tag == Iex_Tmp);
820 newShadowTmp(mce, atom->Iex.Tmp.tmp);
821 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
822 definedOfType(ty));
823 }
824}
825
826
827/*------------------------------------------------------------*/
828/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
829/*------------------------------------------------------------*/
830
831/* Examine the always-defined sections declared in layout to see if
832 the (offset,size) section is within one. Note, is is an error to
833 partially fall into such a region: (offset,size) should either be
834 completely in such a region or completely not-in such a region.
835*/
836static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
837{
838 Int minoffD, maxoffD, i;
839 Int minoff = offset;
840 Int maxoff = minoff + size - 1;
841 tl_assert((minoff & ~0xFFFF) == 0);
842 tl_assert((maxoff & ~0xFFFF) == 0);
843
844 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
845 minoffD = mce->layout->alwaysDefd[i].offset;
846 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
847 tl_assert((minoffD & ~0xFFFF) == 0);
848 tl_assert((maxoffD & ~0xFFFF) == 0);
849
850 if (maxoff < minoffD || maxoffD < minoff)
851 continue; /* no overlap */
852 if (minoff >= minoffD && maxoff <= maxoffD)
853 return True; /* completely contained in an always-defd section */
854
855 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
856 }
857 return False; /* could not find any containing section */
858}
859
860
861/* Generate into bb suitable actions to shadow this Put. If the state
862 slice is marked 'always defined', do nothing. Otherwise, write the
863 supplied V bits to the shadow state. We can pass in either an
864 original atom or a V-atom, but not both. In the former case the
865 relevant V-bits are then generated from the original.
866*/
867static
868void do_shadow_PUT ( MCEnv* mce, Int offset,
869 IRAtom* atom, IRAtom* vatom )
870{
sewardj7cf97ee2004-11-28 14:25:01 +0000871 IRType ty;
sewardj95448072004-11-22 20:19:51 +0000872 if (atom) {
873 tl_assert(!vatom);
874 tl_assert(isOriginalAtom(mce, atom));
875 vatom = expr2vbits( mce, atom );
876 } else {
877 tl_assert(vatom);
878 tl_assert(isShadowAtom(mce, vatom));
879 }
880
sewardj7cf97ee2004-11-28 14:25:01 +0000881 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj95448072004-11-22 20:19:51 +0000882 tl_assert(ty != Ity_I1);
883 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
884 /* later: no ... */
885 /* emit code to emit a complaint if any of the vbits are 1. */
886 /* complainIfUndefined(mce, atom); */
887 } else {
888 /* Do a plain shadow Put. */
889 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
890 }
891}
892
893
894/* Return an expression which contains the V bits corresponding to the
895 given GETI (passed in in pieces).
896*/
897static
898void do_shadow_PUTI ( MCEnv* mce,
899 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
900{
sewardj7cf97ee2004-11-28 14:25:01 +0000901 IRAtom* vatom;
902 IRType ty, tyS;
903 Int arrSize;;
904
sewardj95448072004-11-22 20:19:51 +0000905 tl_assert(isOriginalAtom(mce,atom));
sewardj7cf97ee2004-11-28 14:25:01 +0000906 vatom = expr2vbits( mce, atom );
sewardj95448072004-11-22 20:19:51 +0000907 tl_assert(sameKindedAtoms(atom, vatom));
sewardj7cf97ee2004-11-28 14:25:01 +0000908 ty = descr->elemTy;
909 tyS = shadowType(ty);
910 arrSize = descr->nElems * sizeofIRType(ty);
sewardj95448072004-11-22 20:19:51 +0000911 tl_assert(ty != Ity_I1);
912 tl_assert(isOriginalAtom(mce,ix));
913 complainIfUndefined(mce,ix);
914 if (isAlwaysDefd(mce, descr->base, arrSize)) {
915 /* later: no ... */
916 /* emit code to emit a complaint if any of the vbits are 1. */
917 /* complainIfUndefined(mce, atom); */
918 } else {
919 /* Do a cloned version of the Put that refers to the shadow
920 area. */
921 IRArray* new_descr
922 = mkIRArray( descr->base + mce->layout->total_sizeB,
923 tyS, descr->nElems);
924 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
925 }
926}
927
928
929/* Return an expression which contains the V bits corresponding to the
930 given GET (passed in in pieces).
931*/
932static
933IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
934{
935 IRType tyS = shadowType(ty);
936 tl_assert(ty != Ity_I1);
937 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
938 /* Always defined, return all zeroes of the relevant type */
939 return definedOfType(tyS);
940 } else {
941 /* return a cloned version of the Get that refers to the shadow
942 area. */
943 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
944 }
945}
946
947
948/* Return an expression which contains the V bits corresponding to the
949 given GETI (passed in in pieces).
950*/
951static
952IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
953{
954 IRType ty = descr->elemTy;
955 IRType tyS = shadowType(ty);
956 Int arrSize = descr->nElems * sizeofIRType(ty);
957 tl_assert(ty != Ity_I1);
958 tl_assert(isOriginalAtom(mce,ix));
959 complainIfUndefined(mce,ix);
960 if (isAlwaysDefd(mce, descr->base, arrSize)) {
961 /* Always defined, return all zeroes of the relevant type */
962 return definedOfType(tyS);
963 } else {
964 /* return a cloned version of the Get that refers to the shadow
965 area. */
966 IRArray* new_descr
967 = mkIRArray( descr->base + mce->layout->total_sizeB,
968 tyS, descr->nElems);
969 return IRExpr_GetI( new_descr, ix, bias );
970 }
971}
972
973
974/*------------------------------------------------------------*/
975/*--- Generating approximations for unknown operations, ---*/
976/*--- using lazy-propagate semantics ---*/
977/*------------------------------------------------------------*/
978
979/* Lazy propagation of undefinedness from two values, resulting in the
980 specified shadow type.
981*/
982static
983IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
984{
sewardj95448072004-11-22 20:19:51 +0000985 IRAtom* at;
sewardj37c31cc2005-04-26 23:49:24 +0000986 IRType t1 = typeOfIRExpr(mce->bb->tyenv, va1);
987 IRType t2 = typeOfIRExpr(mce->bb->tyenv, va2);
sewardj95448072004-11-22 20:19:51 +0000988 tl_assert(isShadowAtom(mce,va1));
989 tl_assert(isShadowAtom(mce,va2));
sewardj37c31cc2005-04-26 23:49:24 +0000990
991 /* The general case is inefficient because PCast is an expensive
992 operation. Here are some special cases which use PCast only
993 once rather than twice. */
994
995 /* I64 x I64 -> I64 */
996 if (t1 == Ity_I64 && t2 == Ity_I64 && finalVty == Ity_I64) {
997 if (0) VG_(printf)("mkLazy2: I64 x I64 -> I64\n");
998 at = mkUifU(mce, Ity_I64, va1, va2);
999 at = mkPCastTo(mce, Ity_I64, at);
1000 return at;
1001 }
1002
1003 /* I64 x I64 -> I32 */
1004 if (t1 == Ity_I64 && t2 == Ity_I64 && finalVty == Ity_I32) {
1005 if (0) VG_(printf)("mkLazy2: I64 x I64 -> I32\n");
1006 at = mkUifU(mce, Ity_I64, va1, va2);
1007 at = mkPCastTo(mce, Ity_I32, at);
1008 return at;
1009 }
1010
1011 if (0) {
1012 VG_(printf)("mkLazy2 ");
1013 ppIRType(t1);
1014 VG_(printf)("_");
1015 ppIRType(t2);
1016 VG_(printf)("_");
1017 ppIRType(finalVty);
1018 VG_(printf)("\n");
1019 }
1020
1021 /* General case: force everything via 32-bit intermediaries. */
sewardj95448072004-11-22 20:19:51 +00001022 at = mkPCastTo(mce, Ity_I32, va1);
1023 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1024 at = mkPCastTo(mce, finalVty, at);
1025 return at;
1026}
1027
1028
1029/* Do the lazy propagation game from a null-terminated vector of
1030 atoms. This is presumably the arguments to a helper call, so the
1031 IRCallee info is also supplied in order that we can know which
1032 arguments should be ignored (via the .mcx_mask field).
1033*/
1034static
1035IRAtom* mkLazyN ( MCEnv* mce,
1036 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1037{
1038 Int i;
1039 IRAtom* here;
1040 IRAtom* curr = definedOfType(Ity_I32);
1041 for (i = 0; exprvec[i]; i++) {
1042 tl_assert(i < 32);
1043 tl_assert(isOriginalAtom(mce, exprvec[i]));
1044 /* Only take notice of this arg if the callee's mc-exclusion
1045 mask does not say it is to be excluded. */
1046 if (cee->mcx_mask & (1<<i)) {
1047 /* the arg is to be excluded from definedness checking. Do
1048 nothing. */
1049 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1050 } else {
1051 /* calculate the arg's definedness, and pessimistically merge
1052 it in. */
1053 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1054 curr = mkUifU32(mce, here, curr);
1055 }
1056 }
1057 return mkPCastTo(mce, finalVtype, curr );
1058}
1059
1060
1061/*------------------------------------------------------------*/
1062/*--- Generating expensive sequences for exact carry-chain ---*/
1063/*--- propagation in add/sub and related operations. ---*/
1064/*------------------------------------------------------------*/
1065
1066static
sewardjd5204dc2004-12-31 01:16:11 +00001067IRAtom* expensiveAddSub ( MCEnv* mce,
1068 Bool add,
1069 IRType ty,
1070 IRAtom* qaa, IRAtom* qbb,
1071 IRAtom* aa, IRAtom* bb )
sewardj95448072004-11-22 20:19:51 +00001072{
sewardj7cf97ee2004-11-28 14:25:01 +00001073 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardjd5204dc2004-12-31 01:16:11 +00001074 IROp opAND, opOR, opXOR, opNOT, opADD, opSUB;
sewardj7cf97ee2004-11-28 14:25:01 +00001075
sewardj95448072004-11-22 20:19:51 +00001076 tl_assert(isShadowAtom(mce,qaa));
1077 tl_assert(isShadowAtom(mce,qbb));
1078 tl_assert(isOriginalAtom(mce,aa));
1079 tl_assert(isOriginalAtom(mce,bb));
1080 tl_assert(sameKindedAtoms(qaa,aa));
1081 tl_assert(sameKindedAtoms(qbb,bb));
1082
sewardjd5204dc2004-12-31 01:16:11 +00001083 switch (ty) {
1084 case Ity_I32:
1085 opAND = Iop_And32;
1086 opOR = Iop_Or32;
1087 opXOR = Iop_Xor32;
1088 opNOT = Iop_Not32;
1089 opADD = Iop_Add32;
1090 opSUB = Iop_Sub32;
1091 break;
tomd9774d72005-06-27 08:11:01 +00001092 case Ity_I64:
1093 opAND = Iop_And64;
1094 opOR = Iop_Or64;
1095 opXOR = Iop_Xor64;
1096 opNOT = Iop_Not64;
1097 opADD = Iop_Add64;
1098 opSUB = Iop_Sub64;
1099 break;
sewardjd5204dc2004-12-31 01:16:11 +00001100 default:
1101 VG_(tool_panic)("expensiveAddSub");
1102 }
sewardj95448072004-11-22 20:19:51 +00001103
1104 // a_min = aa & ~qaa
1105 a_min = assignNew(mce,ty,
1106 binop(opAND, aa,
1107 assignNew(mce,ty, unop(opNOT, qaa))));
1108
1109 // b_min = bb & ~qbb
1110 b_min = assignNew(mce,ty,
1111 binop(opAND, bb,
1112 assignNew(mce,ty, unop(opNOT, qbb))));
1113
1114 // a_max = aa | qaa
1115 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1116
1117 // b_max = bb | qbb
1118 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1119
sewardjd5204dc2004-12-31 01:16:11 +00001120 if (add) {
1121 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1122 return
1123 assignNew(mce,ty,
1124 binop( opOR,
1125 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1126 assignNew(mce,ty,
1127 binop( opXOR,
1128 assignNew(mce,ty, binop(opADD, a_min, b_min)),
1129 assignNew(mce,ty, binop(opADD, a_max, b_max))
1130 )
sewardj95448072004-11-22 20:19:51 +00001131 )
sewardjd5204dc2004-12-31 01:16:11 +00001132 )
1133 );
1134 } else {
1135 // result = (qaa | qbb) | ((a_min - b_max) ^ (a_max + b_min))
1136 return
1137 assignNew(mce,ty,
1138 binop( opOR,
1139 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1140 assignNew(mce,ty,
1141 binop( opXOR,
1142 assignNew(mce,ty, binop(opSUB, a_min, b_max)),
1143 assignNew(mce,ty, binop(opSUB, a_max, b_min))
1144 )
1145 )
1146 )
1147 );
1148 }
1149
sewardj95448072004-11-22 20:19:51 +00001150}
1151
1152
1153/*------------------------------------------------------------*/
sewardjaaddbc22005-10-07 09:49:53 +00001154/*--- Scalar shifts. ---*/
1155/*------------------------------------------------------------*/
1156
1157/* Produce an interpretation for (aa << bb) (or >>s, >>u). The basic
1158 idea is to shift the definedness bits by the original shift amount.
1159 This introduces 0s ("defined") in new positions for left shifts and
1160 unsigned right shifts, and copies the top definedness bit for
1161 signed right shifts. So, conveniently, applying the original shift
1162 operator to the definedness bits for the left arg is exactly the
1163 right thing to do:
1164
1165 (qaa << bb)
1166
1167 However if the shift amount is undefined then the whole result
1168 is undefined. Hence need:
1169
1170 (qaa << bb) `UifU` PCast(qbb)
1171
1172 If the shift amount bb is a literal than qbb will say 'all defined'
1173 and the UifU and PCast will get folded out by post-instrumentation
1174 optimisation.
1175*/
1176static IRAtom* scalarShift ( MCEnv* mce,
1177 IRType ty,
1178 IROp original_op,
1179 IRAtom* qaa, IRAtom* qbb,
1180 IRAtom* aa, IRAtom* bb )
1181{
1182 tl_assert(isShadowAtom(mce,qaa));
1183 tl_assert(isShadowAtom(mce,qbb));
1184 tl_assert(isOriginalAtom(mce,aa));
1185 tl_assert(isOriginalAtom(mce,bb));
1186 tl_assert(sameKindedAtoms(qaa,aa));
1187 tl_assert(sameKindedAtoms(qbb,bb));
1188 return
1189 assignNew(
1190 mce, ty,
1191 mkUifU( mce, ty,
1192 assignNew(mce, ty, binop(original_op, qaa, bb)),
1193 mkPCastTo(mce, ty, qbb)
1194 )
1195 );
1196}
1197
1198
1199/*------------------------------------------------------------*/
1200/*--- Helpers for dealing with vector primops. ---*/
sewardj3245c912004-12-10 14:58:26 +00001201/*------------------------------------------------------------*/
1202
sewardja1d93302004-12-12 16:45:06 +00001203/* Vector pessimisation -- pessimise within each lane individually. */
1204
1205static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1206{
1207 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1208}
1209
1210static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1211{
1212 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1213}
1214
1215static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1216{
1217 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1218}
1219
1220static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1221{
1222 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1223}
1224
sewardjacd2e912005-01-13 19:17:06 +00001225static IRAtom* mkPCast32x2 ( MCEnv* mce, IRAtom* at )
1226{
1227 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ32x2, at));
1228}
1229
1230static IRAtom* mkPCast16x4 ( MCEnv* mce, IRAtom* at )
1231{
1232 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ16x4, at));
1233}
1234
1235static IRAtom* mkPCast8x8 ( MCEnv* mce, IRAtom* at )
1236{
1237 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ8x8, at));
1238}
1239
sewardja1d93302004-12-12 16:45:06 +00001240
sewardj3245c912004-12-10 14:58:26 +00001241/* Here's a simple scheme capable of handling ops derived from SSE1
1242 code and while only generating ops that can be efficiently
1243 implemented in SSE1. */
1244
1245/* All-lanes versions are straightforward:
1246
sewardj20d38f22005-02-07 23:50:18 +00001247 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj3245c912004-12-10 14:58:26 +00001248
1249 unary32Fx4(x,y) ==> PCast32x4(x#)
1250
1251 Lowest-lane-only versions are more complex:
1252
sewardj20d38f22005-02-07 23:50:18 +00001253 binary32F0x4(x,y) ==> SetV128lo32(
sewardj3245c912004-12-10 14:58:26 +00001254 x#,
sewardj20d38f22005-02-07 23:50:18 +00001255 PCast32(V128to32(UifUV128(x#,y#)))
sewardj3245c912004-12-10 14:58:26 +00001256 )
1257
1258 This is perhaps not so obvious. In particular, it's faster to
sewardj20d38f22005-02-07 23:50:18 +00001259 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj3245c912004-12-10 14:58:26 +00001260 obvious scheme of taking the bottom 32 bits of each operand
1261 and doing a 32-bit UifU. Basically since UifU is fast and
1262 chopping lanes off vector values is slow.
1263
1264 Finally:
1265
sewardj20d38f22005-02-07 23:50:18 +00001266 unary32F0x4(x) ==> SetV128lo32(
sewardj3245c912004-12-10 14:58:26 +00001267 x#,
sewardj20d38f22005-02-07 23:50:18 +00001268 PCast32(V128to32(x#))
sewardj3245c912004-12-10 14:58:26 +00001269 )
1270
1271 Where:
1272
1273 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1274 PCast32x4(v#) = CmpNEZ32x4(v#)
1275*/
1276
1277static
1278IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1279{
1280 IRAtom* at;
1281 tl_assert(isShadowAtom(mce, vatomX));
1282 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001283 at = mkUifUV128(mce, vatomX, vatomY);
sewardja1d93302004-12-12 16:45:06 +00001284 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
sewardj3245c912004-12-10 14:58:26 +00001285 return at;
1286}
1287
1288static
1289IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1290{
1291 IRAtom* at;
1292 tl_assert(isShadowAtom(mce, vatomX));
sewardja1d93302004-12-12 16:45:06 +00001293 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
sewardj3245c912004-12-10 14:58:26 +00001294 return at;
1295}
1296
1297static
1298IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1299{
1300 IRAtom* at;
1301 tl_assert(isShadowAtom(mce, vatomX));
1302 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001303 at = mkUifUV128(mce, vatomX, vatomY);
1304 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj3245c912004-12-10 14:58:26 +00001305 at = mkPCastTo(mce, Ity_I32, at);
sewardj20d38f22005-02-07 23:50:18 +00001306 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj3245c912004-12-10 14:58:26 +00001307 return at;
1308}
1309
1310static
1311IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1312{
1313 IRAtom* at;
1314 tl_assert(isShadowAtom(mce, vatomX));
sewardj20d38f22005-02-07 23:50:18 +00001315 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj3245c912004-12-10 14:58:26 +00001316 at = mkPCastTo(mce, Ity_I32, at);
sewardj20d38f22005-02-07 23:50:18 +00001317 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj3245c912004-12-10 14:58:26 +00001318 return at;
1319}
1320
sewardj0b070592004-12-10 21:44:22 +00001321/* --- ... and ... 64Fx2 versions of the same ... --- */
1322
1323static
1324IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1325{
1326 IRAtom* at;
1327 tl_assert(isShadowAtom(mce, vatomX));
1328 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001329 at = mkUifUV128(mce, vatomX, vatomY);
sewardja1d93302004-12-12 16:45:06 +00001330 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
sewardj0b070592004-12-10 21:44:22 +00001331 return at;
1332}
1333
1334static
1335IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1336{
1337 IRAtom* at;
1338 tl_assert(isShadowAtom(mce, vatomX));
sewardja1d93302004-12-12 16:45:06 +00001339 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
sewardj0b070592004-12-10 21:44:22 +00001340 return at;
1341}
1342
1343static
1344IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1345{
1346 IRAtom* at;
1347 tl_assert(isShadowAtom(mce, vatomX));
1348 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001349 at = mkUifUV128(mce, vatomX, vatomY);
1350 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj0b070592004-12-10 21:44:22 +00001351 at = mkPCastTo(mce, Ity_I64, at);
sewardj20d38f22005-02-07 23:50:18 +00001352 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj0b070592004-12-10 21:44:22 +00001353 return at;
1354}
1355
1356static
1357IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1358{
1359 IRAtom* at;
1360 tl_assert(isShadowAtom(mce, vatomX));
sewardj20d38f22005-02-07 23:50:18 +00001361 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj0b070592004-12-10 21:44:22 +00001362 at = mkPCastTo(mce, Ity_I64, at);
sewardj20d38f22005-02-07 23:50:18 +00001363 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj0b070592004-12-10 21:44:22 +00001364 return at;
1365}
1366
sewardja1d93302004-12-12 16:45:06 +00001367/* --- --- Vector saturated narrowing --- --- */
1368
1369/* This is quite subtle. What to do is simple:
1370
1371 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1372
1373 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1374
1375 Why this is right is not so simple. Consider a lane in the args,
1376 vatom1 or 2, doesn't matter.
1377
1378 After the PCast, that lane is all 0s (defined) or all
1379 1s(undefined).
1380
1381 Both signed and unsigned saturating narrowing of all 0s produces
1382 all 0s, which is what we want.
1383
1384 The all-1s case is more complex. Unsigned narrowing interprets an
1385 all-1s input as the largest unsigned integer, and so produces all
1386 1s as a result since that is the largest unsigned value at the
1387 smaller width.
1388
1389 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1390 to -1, so we still wind up with all 1s at the smaller width.
1391
1392 So: In short, pessimise the args, then apply the original narrowing
1393 op.
1394*/
1395static
sewardj20d38f22005-02-07 23:50:18 +00001396IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardja1d93302004-12-12 16:45:06 +00001397 IRAtom* vatom1, IRAtom* vatom2)
1398{
1399 IRAtom *at1, *at2, *at3;
1400 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1401 switch (narrow_op) {
1402 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1403 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1404 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardj20d38f22005-02-07 23:50:18 +00001405 default: VG_(tool_panic)("vectorNarrowV128");
sewardja1d93302004-12-12 16:45:06 +00001406 }
1407 tl_assert(isShadowAtom(mce,vatom1));
1408 tl_assert(isShadowAtom(mce,vatom2));
1409 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1410 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1411 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1412 return at3;
1413}
1414
sewardjacd2e912005-01-13 19:17:06 +00001415static
1416IRAtom* vectorNarrow64 ( MCEnv* mce, IROp narrow_op,
1417 IRAtom* vatom1, IRAtom* vatom2)
1418{
1419 IRAtom *at1, *at2, *at3;
1420 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1421 switch (narrow_op) {
1422 case Iop_QNarrow32Sx2: pcast = mkPCast32x2; break;
1423 case Iop_QNarrow16Sx4: pcast = mkPCast16x4; break;
1424 case Iop_QNarrow16Ux4: pcast = mkPCast16x4; break;
1425 default: VG_(tool_panic)("vectorNarrow64");
1426 }
1427 tl_assert(isShadowAtom(mce,vatom1));
1428 tl_assert(isShadowAtom(mce,vatom2));
1429 at1 = assignNew(mce, Ity_I64, pcast(mce, vatom1));
1430 at2 = assignNew(mce, Ity_I64, pcast(mce, vatom2));
1431 at3 = assignNew(mce, Ity_I64, binop(narrow_op, at1, at2));
1432 return at3;
1433}
1434
sewardja1d93302004-12-12 16:45:06 +00001435
1436/* --- --- Vector integer arithmetic --- --- */
1437
1438/* Simple ... UifU the args and per-lane pessimise the results. */
sewardjacd2e912005-01-13 19:17:06 +00001439
sewardj20d38f22005-02-07 23:50:18 +00001440/* --- V128-bit versions --- */
sewardjacd2e912005-01-13 19:17:06 +00001441
sewardja1d93302004-12-12 16:45:06 +00001442static
1443IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1444{
1445 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001446 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001447 at = mkPCast8x16(mce, at);
1448 return at;
1449}
1450
1451static
1452IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1453{
1454 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001455 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001456 at = mkPCast16x8(mce, at);
1457 return at;
1458}
1459
1460static
1461IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1462{
1463 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001464 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001465 at = mkPCast32x4(mce, at);
1466 return at;
1467}
1468
1469static
1470IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1471{
1472 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001473 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001474 at = mkPCast64x2(mce, at);
1475 return at;
1476}
sewardj3245c912004-12-10 14:58:26 +00001477
sewardjacd2e912005-01-13 19:17:06 +00001478/* --- 64-bit versions --- */
1479
1480static
1481IRAtom* binary8Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1482{
1483 IRAtom* at;
1484 at = mkUifU64(mce, vatom1, vatom2);
1485 at = mkPCast8x8(mce, at);
1486 return at;
1487}
1488
1489static
1490IRAtom* binary16Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1491{
1492 IRAtom* at;
1493 at = mkUifU64(mce, vatom1, vatom2);
1494 at = mkPCast16x4(mce, at);
1495 return at;
1496}
1497
1498static
1499IRAtom* binary32Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1500{
1501 IRAtom* at;
1502 at = mkUifU64(mce, vatom1, vatom2);
1503 at = mkPCast32x2(mce, at);
1504 return at;
1505}
1506
sewardj3245c912004-12-10 14:58:26 +00001507
1508/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00001509/*--- Generate shadow values from all kinds of IRExprs. ---*/
1510/*------------------------------------------------------------*/
1511
1512static
1513IRAtom* expr2vbits_Binop ( MCEnv* mce,
1514 IROp op,
1515 IRAtom* atom1, IRAtom* atom2 )
1516{
1517 IRType and_or_ty;
1518 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1519 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1520 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1521
1522 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1523 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1524
1525 tl_assert(isOriginalAtom(mce,atom1));
1526 tl_assert(isOriginalAtom(mce,atom2));
1527 tl_assert(isShadowAtom(mce,vatom1));
1528 tl_assert(isShadowAtom(mce,vatom2));
1529 tl_assert(sameKindedAtoms(atom1,vatom1));
1530 tl_assert(sameKindedAtoms(atom2,vatom2));
1531 switch (op) {
1532
sewardjacd2e912005-01-13 19:17:06 +00001533 /* 64-bit SIMD */
1534
1535 case Iop_ShrN16x4:
1536 case Iop_ShrN32x2:
1537 case Iop_SarN16x4:
1538 case Iop_SarN32x2:
1539 case Iop_ShlN16x4:
1540 case Iop_ShlN32x2:
1541 /* Same scheme as with all other shifts. */
1542 complainIfUndefined(mce, atom2);
1543 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1544
1545 case Iop_QNarrow32Sx2:
1546 case Iop_QNarrow16Sx4:
1547 case Iop_QNarrow16Ux4:
1548 return vectorNarrow64(mce, op, vatom1, vatom2);
1549
1550 case Iop_Min8Ux8:
1551 case Iop_Max8Ux8:
1552 case Iop_Avg8Ux8:
1553 case Iop_QSub8Sx8:
1554 case Iop_QSub8Ux8:
1555 case Iop_Sub8x8:
1556 case Iop_CmpGT8Sx8:
1557 case Iop_CmpEQ8x8:
1558 case Iop_QAdd8Sx8:
1559 case Iop_QAdd8Ux8:
1560 case Iop_Add8x8:
1561 return binary8Ix8(mce, vatom1, vatom2);
1562
1563 case Iop_Min16Sx4:
1564 case Iop_Max16Sx4:
1565 case Iop_Avg16Ux4:
1566 case Iop_QSub16Ux4:
1567 case Iop_QSub16Sx4:
1568 case Iop_Sub16x4:
1569 case Iop_Mul16x4:
1570 case Iop_MulHi16Sx4:
1571 case Iop_MulHi16Ux4:
1572 case Iop_CmpGT16Sx4:
1573 case Iop_CmpEQ16x4:
1574 case Iop_QAdd16Sx4:
1575 case Iop_QAdd16Ux4:
1576 case Iop_Add16x4:
1577 return binary16Ix4(mce, vatom1, vatom2);
1578
1579 case Iop_Sub32x2:
1580 case Iop_CmpGT32Sx2:
1581 case Iop_CmpEQ32x2:
1582 case Iop_Add32x2:
1583 return binary32Ix2(mce, vatom1, vatom2);
1584
1585 /* 64-bit data-steering */
1586 case Iop_InterleaveLO32x2:
1587 case Iop_InterleaveLO16x4:
1588 case Iop_InterleaveLO8x8:
1589 case Iop_InterleaveHI32x2:
1590 case Iop_InterleaveHI16x4:
1591 case Iop_InterleaveHI8x8:
1592 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
1593
sewardj20d38f22005-02-07 23:50:18 +00001594 /* V128-bit SIMD */
sewardj0b070592004-12-10 21:44:22 +00001595
sewardja1d93302004-12-12 16:45:06 +00001596 case Iop_ShrN16x8:
1597 case Iop_ShrN32x4:
1598 case Iop_ShrN64x2:
1599 case Iop_SarN16x8:
1600 case Iop_SarN32x4:
1601 case Iop_ShlN16x8:
1602 case Iop_ShlN32x4:
1603 case Iop_ShlN64x2:
1604 /* Same scheme as with all other shifts. */
1605 complainIfUndefined(mce, atom2);
1606 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1607
1608 case Iop_QSub8Ux16:
1609 case Iop_QSub8Sx16:
1610 case Iop_Sub8x16:
1611 case Iop_Min8Ux16:
1612 case Iop_Max8Ux16:
1613 case Iop_CmpGT8Sx16:
1614 case Iop_CmpEQ8x16:
1615 case Iop_Avg8Ux16:
1616 case Iop_QAdd8Ux16:
1617 case Iop_QAdd8Sx16:
1618 case Iop_Add8x16:
1619 return binary8Ix16(mce, vatom1, vatom2);
1620
1621 case Iop_QSub16Ux8:
1622 case Iop_QSub16Sx8:
1623 case Iop_Sub16x8:
1624 case Iop_Mul16x8:
1625 case Iop_MulHi16Sx8:
1626 case Iop_MulHi16Ux8:
1627 case Iop_Min16Sx8:
1628 case Iop_Max16Sx8:
1629 case Iop_CmpGT16Sx8:
1630 case Iop_CmpEQ16x8:
1631 case Iop_Avg16Ux8:
1632 case Iop_QAdd16Ux8:
1633 case Iop_QAdd16Sx8:
1634 case Iop_Add16x8:
1635 return binary16Ix8(mce, vatom1, vatom2);
1636
1637 case Iop_Sub32x4:
1638 case Iop_CmpGT32Sx4:
1639 case Iop_CmpEQ32x4:
1640 case Iop_Add32x4:
1641 return binary32Ix4(mce, vatom1, vatom2);
1642
1643 case Iop_Sub64x2:
1644 case Iop_Add64x2:
1645 return binary64Ix2(mce, vatom1, vatom2);
1646
1647 case Iop_QNarrow32Sx4:
1648 case Iop_QNarrow16Sx8:
1649 case Iop_QNarrow16Ux8:
sewardj20d38f22005-02-07 23:50:18 +00001650 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001651
sewardj0b070592004-12-10 21:44:22 +00001652 case Iop_Sub64Fx2:
1653 case Iop_Mul64Fx2:
1654 case Iop_Min64Fx2:
1655 case Iop_Max64Fx2:
1656 case Iop_Div64Fx2:
1657 case Iop_CmpLT64Fx2:
1658 case Iop_CmpLE64Fx2:
1659 case Iop_CmpEQ64Fx2:
1660 case Iop_Add64Fx2:
1661 return binary64Fx2(mce, vatom1, vatom2);
1662
1663 case Iop_Sub64F0x2:
1664 case Iop_Mul64F0x2:
1665 case Iop_Min64F0x2:
1666 case Iop_Max64F0x2:
1667 case Iop_Div64F0x2:
1668 case Iop_CmpLT64F0x2:
1669 case Iop_CmpLE64F0x2:
1670 case Iop_CmpEQ64F0x2:
1671 case Iop_Add64F0x2:
1672 return binary64F0x2(mce, vatom1, vatom2);
1673
sewardj170ee212004-12-10 18:57:51 +00001674 case Iop_Sub32Fx4:
1675 case Iop_Mul32Fx4:
1676 case Iop_Min32Fx4:
1677 case Iop_Max32Fx4:
1678 case Iop_Div32Fx4:
1679 case Iop_CmpLT32Fx4:
1680 case Iop_CmpLE32Fx4:
1681 case Iop_CmpEQ32Fx4:
sewardj3245c912004-12-10 14:58:26 +00001682 case Iop_Add32Fx4:
1683 return binary32Fx4(mce, vatom1, vatom2);
1684
sewardj170ee212004-12-10 18:57:51 +00001685 case Iop_Sub32F0x4:
1686 case Iop_Mul32F0x4:
1687 case Iop_Min32F0x4:
1688 case Iop_Max32F0x4:
1689 case Iop_Div32F0x4:
1690 case Iop_CmpLT32F0x4:
1691 case Iop_CmpLE32F0x4:
1692 case Iop_CmpEQ32F0x4:
1693 case Iop_Add32F0x4:
1694 return binary32F0x4(mce, vatom1, vatom2);
1695
sewardj20d38f22005-02-07 23:50:18 +00001696 /* V128-bit data-steering */
1697 case Iop_SetV128lo32:
1698 case Iop_SetV128lo64:
1699 case Iop_64HLtoV128:
sewardja1d93302004-12-12 16:45:06 +00001700 case Iop_InterleaveLO64x2:
1701 case Iop_InterleaveLO32x4:
1702 case Iop_InterleaveLO16x8:
1703 case Iop_InterleaveLO8x16:
1704 case Iop_InterleaveHI64x2:
1705 case Iop_InterleaveHI32x4:
1706 case Iop_InterleaveHI16x8:
1707 case Iop_InterleaveHI8x16:
sewardj170ee212004-12-10 18:57:51 +00001708 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1709
sewardj69a13322005-04-23 01:14:51 +00001710 /* I128-bit data-steering */
1711 case Iop_64HLto128:
1712 return assignNew(mce, Ity_I128, binop(op, vatom1, vatom2));
1713
sewardj3245c912004-12-10 14:58:26 +00001714 /* Scalar floating point */
1715
sewardj95448072004-11-22 20:19:51 +00001716 case Iop_RoundF64:
1717 case Iop_F64toI64:
sewardje9e16d32004-12-10 13:17:55 +00001718 case Iop_I64toF64:
1719 /* First arg is I32 (rounding mode), second is F64 or I64
1720 (data). */
sewardj95448072004-11-22 20:19:51 +00001721 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1722
1723 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1724 /* Takes two F64 args. */
1725 case Iop_F64toI32:
sewardje9e16d32004-12-10 13:17:55 +00001726 case Iop_F64toF32:
sewardj95448072004-11-22 20:19:51 +00001727 /* First arg is I32 (rounding mode), second is F64 (data). */
1728 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1729
1730 case Iop_F64toI16:
1731 /* First arg is I32 (rounding mode), second is F64 (data). */
1732 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1733
1734 case Iop_ScaleF64:
1735 case Iop_Yl2xF64:
1736 case Iop_Yl2xp1F64:
1737 case Iop_PRemF64:
sewardj96403eb2005-04-01 20:20:12 +00001738 case Iop_PRem1F64:
sewardj95448072004-11-22 20:19:51 +00001739 case Iop_AtanF64:
1740 case Iop_AddF64:
1741 case Iop_DivF64:
1742 case Iop_SubF64:
1743 case Iop_MulF64:
1744 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1745
1746 case Iop_CmpF64:
1747 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1748
1749 /* non-FP after here */
1750
1751 case Iop_DivModU64to32:
1752 case Iop_DivModS64to32:
1753 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1754
sewardj69a13322005-04-23 01:14:51 +00001755 case Iop_DivModU128to64:
1756 case Iop_DivModS128to64:
1757 return mkLazy2(mce, Ity_I128, vatom1, vatom2);
1758
sewardj95448072004-11-22 20:19:51 +00001759 case Iop_16HLto32:
sewardj170ee212004-12-10 18:57:51 +00001760 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardj95448072004-11-22 20:19:51 +00001761 case Iop_32HLto64:
sewardj170ee212004-12-10 18:57:51 +00001762 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardj95448072004-11-22 20:19:51 +00001763
sewardj6cf40ff2005-04-20 22:31:26 +00001764 case Iop_MullS64:
1765 case Iop_MullU64: {
1766 IRAtom* vLo64 = mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
1767 IRAtom* vHi64 = mkPCastTo(mce, Ity_I64, vLo64);
1768 return assignNew(mce, Ity_I128, binop(Iop_64HLto128, vHi64, vLo64));
1769 }
1770
sewardj95448072004-11-22 20:19:51 +00001771 case Iop_MullS32:
1772 case Iop_MullU32: {
1773 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1774 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1775 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1776 }
1777
1778 case Iop_MullS16:
1779 case Iop_MullU16: {
1780 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1781 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1782 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1783 }
1784
1785 case Iop_MullS8:
1786 case Iop_MullU8: {
1787 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1788 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1789 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1790 }
1791
cerion9e591082005-06-23 15:28:34 +00001792 case Iop_DivS32:
1793 case Iop_DivU32:
1794 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1795
sewardj95448072004-11-22 20:19:51 +00001796 case Iop_Add32:
sewardjd5204dc2004-12-31 01:16:11 +00001797 if (mce->bogusLiterals)
1798 return expensiveAddSub(mce,True,Ity_I32,
1799 vatom1,vatom2, atom1,atom2);
1800 else
1801 goto cheap_AddSub32;
sewardj95448072004-11-22 20:19:51 +00001802 case Iop_Sub32:
sewardjd5204dc2004-12-31 01:16:11 +00001803 if (mce->bogusLiterals)
1804 return expensiveAddSub(mce,False,Ity_I32,
1805 vatom1,vatom2, atom1,atom2);
1806 else
1807 goto cheap_AddSub32;
1808
1809 cheap_AddSub32:
sewardj95448072004-11-22 20:19:51 +00001810 case Iop_Mul32:
sewardj992dff92005-10-07 11:08:55 +00001811 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1812
sewardj463b3d92005-07-18 11:41:15 +00001813 case Iop_CmpORD32S:
1814 case Iop_CmpORD32U:
sewardj992dff92005-10-07 11:08:55 +00001815 return doCmpORD32(mce, op, vatom1,vatom2, atom1,atom2);
sewardj95448072004-11-22 20:19:51 +00001816
sewardj681be302005-01-15 20:43:58 +00001817 case Iop_Add64:
tomd9774d72005-06-27 08:11:01 +00001818 if (mce->bogusLiterals)
1819 return expensiveAddSub(mce,True,Ity_I64,
1820 vatom1,vatom2, atom1,atom2);
1821 else
1822 goto cheap_AddSub64;
sewardj681be302005-01-15 20:43:58 +00001823 case Iop_Sub64:
tomd9774d72005-06-27 08:11:01 +00001824 if (mce->bogusLiterals)
1825 return expensiveAddSub(mce,False,Ity_I64,
1826 vatom1,vatom2, atom1,atom2);
1827 else
1828 goto cheap_AddSub64;
1829
1830 cheap_AddSub64:
1831 case Iop_Mul64:
sewardj681be302005-01-15 20:43:58 +00001832 return mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
1833
sewardj95448072004-11-22 20:19:51 +00001834 case Iop_Mul16:
1835 case Iop_Add16:
1836 case Iop_Sub16:
1837 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1838
1839 case Iop_Sub8:
1840 case Iop_Add8:
1841 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1842
sewardj69a13322005-04-23 01:14:51 +00001843 case Iop_CmpEQ64:
sewardje6f8af42005-07-06 18:48:59 +00001844 case Iop_CmpNE64:
sewardj69a13322005-04-23 01:14:51 +00001845 if (mce->bogusLiterals)
1846 return expensiveCmpEQorNE(mce,Ity_I64, vatom1,vatom2, atom1,atom2 );
1847 else
1848 goto cheap_cmp64;
1849 cheap_cmp64:
tomcd986332005-04-26 07:44:48 +00001850 case Iop_CmpLE64S: case Iop_CmpLE64U:
1851 case Iop_CmpLT64U: case Iop_CmpLT64S:
sewardj69a13322005-04-23 01:14:51 +00001852 return mkPCastTo(mce, Ity_I1, mkUifU64(mce, vatom1,vatom2));
1853
sewardjd5204dc2004-12-31 01:16:11 +00001854 case Iop_CmpEQ32:
sewardje6f8af42005-07-06 18:48:59 +00001855 case Iop_CmpNE32:
sewardjd5204dc2004-12-31 01:16:11 +00001856 if (mce->bogusLiterals)
1857 return expensiveCmpEQorNE(mce,Ity_I32, vatom1,vatom2, atom1,atom2 );
1858 else
1859 goto cheap_cmp32;
sewardjd5204dc2004-12-31 01:16:11 +00001860 cheap_cmp32:
sewardj95448072004-11-22 20:19:51 +00001861 case Iop_CmpLE32S: case Iop_CmpLE32U:
1862 case Iop_CmpLT32U: case Iop_CmpLT32S:
sewardj95448072004-11-22 20:19:51 +00001863 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
1864
1865 case Iop_CmpEQ16: case Iop_CmpNE16:
1866 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
1867
1868 case Iop_CmpEQ8: case Iop_CmpNE8:
1869 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
1870
sewardjaaddbc22005-10-07 09:49:53 +00001871 case Iop_Shl64: case Iop_Shr64: case Iop_Sar64:
1872 return scalarShift( mce, Ity_I64, op, vatom1,vatom2, atom1,atom2 );
1873
sewardj95448072004-11-22 20:19:51 +00001874 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
sewardjaaddbc22005-10-07 09:49:53 +00001875 return scalarShift( mce, Ity_I32, op, vatom1,vatom2, atom1,atom2 );
sewardj95448072004-11-22 20:19:51 +00001876
sewardjdb67f5f2004-12-14 01:15:31 +00001877 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjaaddbc22005-10-07 09:49:53 +00001878 return scalarShift( mce, Ity_I16, op, vatom1,vatom2, atom1,atom2 );
sewardj95448072004-11-22 20:19:51 +00001879
1880 case Iop_Shl8: case Iop_Shr8:
sewardjaaddbc22005-10-07 09:49:53 +00001881 return scalarShift( mce, Ity_I8, op, vatom1,vatom2, atom1,atom2 );
sewardj95448072004-11-22 20:19:51 +00001882
sewardj20d38f22005-02-07 23:50:18 +00001883 case Iop_AndV128:
1884 uifu = mkUifUV128; difd = mkDifDV128;
1885 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj7010f6e2004-12-10 13:35:22 +00001886 case Iop_And64:
1887 uifu = mkUifU64; difd = mkDifD64;
1888 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardj95448072004-11-22 20:19:51 +00001889 case Iop_And32:
1890 uifu = mkUifU32; difd = mkDifD32;
1891 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
1892 case Iop_And16:
1893 uifu = mkUifU16; difd = mkDifD16;
1894 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
1895 case Iop_And8:
1896 uifu = mkUifU8; difd = mkDifD8;
1897 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1898
sewardj20d38f22005-02-07 23:50:18 +00001899 case Iop_OrV128:
1900 uifu = mkUifUV128; difd = mkDifDV128;
1901 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj7010f6e2004-12-10 13:35:22 +00001902 case Iop_Or64:
1903 uifu = mkUifU64; difd = mkDifD64;
1904 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardj95448072004-11-22 20:19:51 +00001905 case Iop_Or32:
1906 uifu = mkUifU32; difd = mkDifD32;
1907 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1908 case Iop_Or16:
1909 uifu = mkUifU16; difd = mkDifD16;
1910 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1911 case Iop_Or8:
1912 uifu = mkUifU8; difd = mkDifD8;
1913 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1914
1915 do_And_Or:
1916 return
1917 assignNew(
1918 mce,
1919 and_or_ty,
1920 difd(mce, uifu(mce, vatom1, vatom2),
1921 difd(mce, improve(mce, atom1, vatom1),
1922 improve(mce, atom2, vatom2) ) ) );
1923
1924 case Iop_Xor8:
1925 return mkUifU8(mce, vatom1, vatom2);
1926 case Iop_Xor16:
1927 return mkUifU16(mce, vatom1, vatom2);
1928 case Iop_Xor32:
1929 return mkUifU32(mce, vatom1, vatom2);
sewardj7010f6e2004-12-10 13:35:22 +00001930 case Iop_Xor64:
1931 return mkUifU64(mce, vatom1, vatom2);
sewardj20d38f22005-02-07 23:50:18 +00001932 case Iop_XorV128:
1933 return mkUifUV128(mce, vatom1, vatom2);
njn25e49d8e72002-09-23 09:36:25 +00001934
1935 default:
sewardj95448072004-11-22 20:19:51 +00001936 ppIROp(op);
1937 VG_(tool_panic)("memcheck:expr2vbits_Binop");
njn25e49d8e72002-09-23 09:36:25 +00001938 }
njn25e49d8e72002-09-23 09:36:25 +00001939}
1940
njn25e49d8e72002-09-23 09:36:25 +00001941
sewardj95448072004-11-22 20:19:51 +00001942static
1943IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1944{
1945 IRAtom* vatom = expr2vbits( mce, atom );
1946 tl_assert(isOriginalAtom(mce,atom));
1947 switch (op) {
1948
sewardj0b070592004-12-10 21:44:22 +00001949 case Iop_Sqrt64Fx2:
1950 return unary64Fx2(mce, vatom);
1951
1952 case Iop_Sqrt64F0x2:
1953 return unary64F0x2(mce, vatom);
1954
sewardj170ee212004-12-10 18:57:51 +00001955 case Iop_Sqrt32Fx4:
1956 case Iop_RSqrt32Fx4:
1957 case Iop_Recip32Fx4:
1958 return unary32Fx4(mce, vatom);
1959
1960 case Iop_Sqrt32F0x4:
1961 case Iop_RSqrt32F0x4:
1962 case Iop_Recip32F0x4:
1963 return unary32F0x4(mce, vatom);
1964
sewardj20d38f22005-02-07 23:50:18 +00001965 case Iop_32UtoV128:
1966 case Iop_64UtoV128:
sewardj170ee212004-12-10 18:57:51 +00001967 return assignNew(mce, Ity_V128, unop(op, vatom));
1968
sewardj95448072004-11-22 20:19:51 +00001969 case Iop_F32toF64:
1970 case Iop_I32toF64:
sewardj95448072004-11-22 20:19:51 +00001971 case Iop_NegF64:
1972 case Iop_SinF64:
1973 case Iop_CosF64:
1974 case Iop_TanF64:
1975 case Iop_SqrtF64:
1976 case Iop_AbsF64:
1977 case Iop_2xm1F64:
sewardj39cc7352005-06-09 21:31:55 +00001978 case Iop_Clz64:
1979 case Iop_Ctz64:
sewardj95448072004-11-22 20:19:51 +00001980 return mkPCastTo(mce, Ity_I64, vatom);
1981
sewardj95448072004-11-22 20:19:51 +00001982 case Iop_Clz32:
1983 case Iop_Ctz32:
1984 return mkPCastTo(mce, Ity_I32, vatom);
1985
sewardjd9dbc192005-04-27 11:40:27 +00001986 case Iop_1Uto64:
1987 case Iop_8Uto64:
1988 case Iop_8Sto64:
1989 case Iop_16Uto64:
1990 case Iop_16Sto64:
sewardj95448072004-11-22 20:19:51 +00001991 case Iop_32Sto64:
1992 case Iop_32Uto64:
sewardj20d38f22005-02-07 23:50:18 +00001993 case Iop_V128to64:
1994 case Iop_V128HIto64:
sewardj6cf40ff2005-04-20 22:31:26 +00001995 case Iop_128HIto64:
1996 case Iop_128to64:
sewardj95448072004-11-22 20:19:51 +00001997 return assignNew(mce, Ity_I64, unop(op, vatom));
1998
1999 case Iop_64to32:
2000 case Iop_64HIto32:
2001 case Iop_1Uto32:
sewardj463b3d92005-07-18 11:41:15 +00002002 case Iop_1Sto32:
sewardj95448072004-11-22 20:19:51 +00002003 case Iop_8Uto32:
2004 case Iop_16Uto32:
2005 case Iop_16Sto32:
2006 case Iop_8Sto32:
cerionfafaa0d2005-09-12 22:29:38 +00002007 case Iop_V128to32:
sewardj95448072004-11-22 20:19:51 +00002008 return assignNew(mce, Ity_I32, unop(op, vatom));
2009
2010 case Iop_8Sto16:
2011 case Iop_8Uto16:
2012 case Iop_32to16:
2013 case Iop_32HIto16:
sewardjd9dbc192005-04-27 11:40:27 +00002014 case Iop_64to16:
sewardj95448072004-11-22 20:19:51 +00002015 return assignNew(mce, Ity_I16, unop(op, vatom));
2016
2017 case Iop_1Uto8:
2018 case Iop_16to8:
2019 case Iop_32to8:
sewardjd9dbc192005-04-27 11:40:27 +00002020 case Iop_64to8:
sewardj95448072004-11-22 20:19:51 +00002021 return assignNew(mce, Ity_I8, unop(op, vatom));
2022
2023 case Iop_32to1:
2024 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
2025
sewardjd9dbc192005-04-27 11:40:27 +00002026 case Iop_64to1:
2027 return assignNew(mce, Ity_I1, unop(Iop_64to1, vatom));
2028
sewardj95448072004-11-22 20:19:51 +00002029 case Iop_ReinterpF64asI64:
2030 case Iop_ReinterpI64asF64:
sewardj0b070592004-12-10 21:44:22 +00002031 case Iop_ReinterpI32asF32:
sewardj20d38f22005-02-07 23:50:18 +00002032 case Iop_NotV128:
sewardj7010f6e2004-12-10 13:35:22 +00002033 case Iop_Not64:
sewardj95448072004-11-22 20:19:51 +00002034 case Iop_Not32:
2035 case Iop_Not16:
2036 case Iop_Not8:
2037 case Iop_Not1:
2038 return vatom;
sewardj7010f6e2004-12-10 13:35:22 +00002039
sewardje53bd992005-05-03 12:22:00 +00002040 /* Neg* really fall under the Add/Sub banner, and as such you
2041 might think would qualify for the 'expensive add/sub'
2042 treatment. However, in this case since the implied literal
2043 is zero (0 - arg), we just do the cheap thing anyway. */
2044 case Iop_Neg8:
2045 return mkLeft8(mce, vatom);
2046 case Iop_Neg16:
2047 return mkLeft16(mce, vatom);
2048 case Iop_Neg32:
2049 return mkLeft32(mce, vatom);
2050
sewardj95448072004-11-22 20:19:51 +00002051 default:
2052 ppIROp(op);
2053 VG_(tool_panic)("memcheck:expr2vbits_Unop");
2054 }
2055}
2056
2057
sewardj170ee212004-12-10 18:57:51 +00002058/* Worker function; do not call directly. */
sewardj95448072004-11-22 20:19:51 +00002059static
sewardj2e595852005-06-30 23:33:37 +00002060IRAtom* expr2vbits_Load_WRK ( MCEnv* mce,
2061 IREndness end, IRType ty,
2062 IRAtom* addr, UInt bias )
sewardj95448072004-11-22 20:19:51 +00002063{
2064 void* helper;
2065 Char* hname;
2066 IRDirty* di;
2067 IRTemp datavbits;
2068 IRAtom* addrAct;
2069
2070 tl_assert(isOriginalAtom(mce,addr));
sewardj2e595852005-06-30 23:33:37 +00002071 tl_assert(end == Iend_LE || end == Iend_BE);
sewardj95448072004-11-22 20:19:51 +00002072
2073 /* First, emit a definedness test for the address. This also sets
2074 the address (shadow) to 'defined' following the test. */
2075 complainIfUndefined( mce, addr );
2076
2077 /* Now cook up a call to the relevant helper function, to read the
2078 data V bits from shadow memory. */
2079 ty = shadowType(ty);
sewardj2e595852005-06-30 23:33:37 +00002080
2081 if (end == Iend_LE) {
2082 switch (ty) {
2083 case Ity_I64: helper = &MC_(helperc_LOADV8le);
2084 hname = "MC_(helperc_LOADV8le)";
2085 break;
2086 case Ity_I32: helper = &MC_(helperc_LOADV4le);
2087 hname = "MC_(helperc_LOADV4le)";
2088 break;
2089 case Ity_I16: helper = &MC_(helperc_LOADV2le);
2090 hname = "MC_(helperc_LOADV2le)";
2091 break;
sewardj8cf88b72005-07-08 01:29:33 +00002092 case Ity_I8: helper = &MC_(helperc_LOADV1);
2093 hname = "MC_(helperc_LOADV1)";
sewardj2e595852005-06-30 23:33:37 +00002094 break;
2095 default: ppIRType(ty);
2096 VG_(tool_panic)("memcheck:do_shadow_Load(LE)");
2097 }
2098 } else {
sewardj8cf88b72005-07-08 01:29:33 +00002099 switch (ty) {
2100 case Ity_I64: helper = &MC_(helperc_LOADV8be);
2101 hname = "MC_(helperc_LOADV8be)";
2102 break;
2103 case Ity_I32: helper = &MC_(helperc_LOADV4be);
2104 hname = "MC_(helperc_LOADV4be)";
2105 break;
2106 case Ity_I16: helper = &MC_(helperc_LOADV2be);
2107 hname = "MC_(helperc_LOADV2be)";
2108 break;
2109 case Ity_I8: helper = &MC_(helperc_LOADV1);
2110 hname = "MC_(helperc_LOADV1)";
2111 break;
2112 default: ppIRType(ty);
2113 VG_(tool_panic)("memcheck:do_shadow_Load(BE)");
2114 }
sewardj95448072004-11-22 20:19:51 +00002115 }
2116
2117 /* Generate the actual address into addrAct. */
2118 if (bias == 0) {
2119 addrAct = addr;
2120 } else {
sewardj7cf97ee2004-11-28 14:25:01 +00002121 IROp mkAdd;
2122 IRAtom* eBias;
sewardj95448072004-11-22 20:19:51 +00002123 IRType tyAddr = mce->hWordTy;
2124 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj7cf97ee2004-11-28 14:25:01 +00002125 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2126 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj95448072004-11-22 20:19:51 +00002127 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2128 }
2129
2130 /* We need to have a place to park the V bits we're just about to
2131 read. */
2132 datavbits = newIRTemp(mce->bb->tyenv, ty);
2133 di = unsafeIRDirty_1_N( datavbits,
2134 1/*regparms*/, hname, helper,
2135 mkIRExprVec_1( addrAct ));
2136 setHelperAnns( mce, di );
2137 stmt( mce->bb, IRStmt_Dirty(di) );
2138
2139 return mkexpr(datavbits);
2140}
2141
2142
2143static
sewardj2e595852005-06-30 23:33:37 +00002144IRAtom* expr2vbits_Load ( MCEnv* mce,
2145 IREndness end, IRType ty,
2146 IRAtom* addr, UInt bias )
sewardj170ee212004-12-10 18:57:51 +00002147{
2148 IRAtom *v64hi, *v64lo;
sewardj2e595852005-06-30 23:33:37 +00002149 tl_assert(end == Iend_LE || end == Iend_BE);
sewardj170ee212004-12-10 18:57:51 +00002150 switch (shadowType(ty)) {
2151 case Ity_I8:
2152 case Ity_I16:
2153 case Ity_I32:
2154 case Ity_I64:
sewardj2e595852005-06-30 23:33:37 +00002155 return expr2vbits_Load_WRK(mce, end, ty, addr, bias);
sewardj170ee212004-12-10 18:57:51 +00002156 case Ity_V128:
sewardj2e595852005-06-30 23:33:37 +00002157 if (end == Iend_LE) {
2158 v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
2159 v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
2160 } else {
sewardj2e595852005-06-30 23:33:37 +00002161 v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
2162 v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
2163 }
sewardj170ee212004-12-10 18:57:51 +00002164 return assignNew( mce,
2165 Ity_V128,
sewardj20d38f22005-02-07 23:50:18 +00002166 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj170ee212004-12-10 18:57:51 +00002167 default:
sewardj2e595852005-06-30 23:33:37 +00002168 VG_(tool_panic)("expr2vbits_Load");
sewardj170ee212004-12-10 18:57:51 +00002169 }
2170}
2171
2172
2173static
sewardj95448072004-11-22 20:19:51 +00002174IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
2175 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
2176{
2177 IRAtom *vbitsC, *vbits0, *vbitsX;
2178 IRType ty;
2179 /* Given Mux0X(cond,expr0,exprX), generate
2180 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2181 That is, steer the V bits like the originals, but trash the
2182 result if the steering value is undefined. This gives
2183 lazy propagation. */
2184 tl_assert(isOriginalAtom(mce, cond));
2185 tl_assert(isOriginalAtom(mce, expr0));
2186 tl_assert(isOriginalAtom(mce, exprX));
2187
2188 vbitsC = expr2vbits(mce, cond);
2189 vbits0 = expr2vbits(mce, expr0);
2190 vbitsX = expr2vbits(mce, exprX);
2191 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2192
2193 return
2194 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2195 mkPCastTo(mce, ty, vbitsC) );
2196}
2197
2198/* --------- This is the main expression-handling function. --------- */
2199
2200static
2201IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2202{
2203 switch (e->tag) {
2204
2205 case Iex_Get:
2206 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2207
2208 case Iex_GetI:
2209 return shadow_GETI( mce, e->Iex.GetI.descr,
2210 e->Iex.GetI.ix, e->Iex.GetI.bias );
2211
2212 case Iex_Tmp:
2213 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
2214
2215 case Iex_Const:
2216 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2217
2218 case Iex_Binop:
2219 return expr2vbits_Binop(
2220 mce,
2221 e->Iex.Binop.op,
2222 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2223 );
2224
2225 case Iex_Unop:
2226 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2227
sewardj2e595852005-06-30 23:33:37 +00002228 case Iex_Load:
2229 return expr2vbits_Load( mce, e->Iex.Load.end,
2230 e->Iex.Load.ty,
2231 e->Iex.Load.addr, 0/*addr bias*/ );
sewardj95448072004-11-22 20:19:51 +00002232
2233 case Iex_CCall:
2234 return mkLazyN( mce, e->Iex.CCall.args,
2235 e->Iex.CCall.retty,
2236 e->Iex.CCall.cee );
2237
2238 case Iex_Mux0X:
2239 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2240 e->Iex.Mux0X.exprX);
njn25e49d8e72002-09-23 09:36:25 +00002241
2242 default:
sewardj95448072004-11-22 20:19:51 +00002243 VG_(printf)("\n");
2244 ppIRExpr(e);
2245 VG_(printf)("\n");
2246 VG_(tool_panic)("memcheck: expr2vbits");
njn25e49d8e72002-09-23 09:36:25 +00002247 }
njn25e49d8e72002-09-23 09:36:25 +00002248}
2249
2250/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00002251/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
njn25e49d8e72002-09-23 09:36:25 +00002252/*------------------------------------------------------------*/
2253
sewardj95448072004-11-22 20:19:51 +00002254/* Widen a value to the host word size. */
njn25e49d8e72002-09-23 09:36:25 +00002255
2256static
sewardj95448072004-11-22 20:19:51 +00002257IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
njn25e49d8e72002-09-23 09:36:25 +00002258{
sewardj7cf97ee2004-11-28 14:25:01 +00002259 IRType ty, tyH;
2260
sewardj95448072004-11-22 20:19:51 +00002261 /* vatom is vbits-value and as such can only have a shadow type. */
2262 tl_assert(isShadowAtom(mce,vatom));
njn25e49d8e72002-09-23 09:36:25 +00002263
sewardj7cf97ee2004-11-28 14:25:01 +00002264 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2265 tyH = mce->hWordTy;
njn25e49d8e72002-09-23 09:36:25 +00002266
sewardj95448072004-11-22 20:19:51 +00002267 if (tyH == Ity_I32) {
2268 switch (ty) {
2269 case Ity_I32: return vatom;
2270 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2271 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2272 default: goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00002273 }
sewardj6cf40ff2005-04-20 22:31:26 +00002274 } else
2275 if (tyH == Ity_I64) {
2276 switch (ty) {
2277 case Ity_I32: return assignNew(mce, tyH, unop(Iop_32Uto64, vatom));
sewardj69a13322005-04-23 01:14:51 +00002278 case Ity_I16: return assignNew(mce, tyH, unop(Iop_32Uto64,
2279 assignNew(mce, Ity_I32, unop(Iop_16Uto32, vatom))));
2280 case Ity_I8: return assignNew(mce, tyH, unop(Iop_32Uto64,
2281 assignNew(mce, Ity_I32, unop(Iop_8Uto32, vatom))));
sewardj6cf40ff2005-04-20 22:31:26 +00002282 default: goto unhandled;
2283 }
sewardj95448072004-11-22 20:19:51 +00002284 } else {
2285 goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00002286 }
sewardj95448072004-11-22 20:19:51 +00002287 unhandled:
2288 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
2289 VG_(tool_panic)("zwidenToHostWord");
njn25e49d8e72002-09-23 09:36:25 +00002290}
2291
njn25e49d8e72002-09-23 09:36:25 +00002292
sewardj95448072004-11-22 20:19:51 +00002293/* Generate a shadow store. addr is always the original address atom.
2294 You can pass in either originals or V-bits for the data atom, but
2295 obviously not both. */
njn25e49d8e72002-09-23 09:36:25 +00002296
sewardj95448072004-11-22 20:19:51 +00002297static
sewardj2e595852005-06-30 23:33:37 +00002298void do_shadow_Store ( MCEnv* mce,
2299 IREndness end,
2300 IRAtom* addr, UInt bias,
2301 IRAtom* data, IRAtom* vdata )
njn25e49d8e72002-09-23 09:36:25 +00002302{
sewardj170ee212004-12-10 18:57:51 +00002303 IROp mkAdd;
2304 IRType ty, tyAddr;
2305 IRDirty *di, *diLo64, *diHi64;
2306 IRAtom *addrAct, *addrLo64, *addrHi64;
2307 IRAtom *vdataLo64, *vdataHi64;
sewardj2e595852005-06-30 23:33:37 +00002308 IRAtom *eBias, *eBiasLo64, *eBiasHi64;
sewardj95448072004-11-22 20:19:51 +00002309 void* helper = NULL;
2310 Char* hname = NULL;
sewardj170ee212004-12-10 18:57:51 +00002311
2312 tyAddr = mce->hWordTy;
2313 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2314 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj2e595852005-06-30 23:33:37 +00002315 tl_assert( end == Iend_LE || end == Iend_BE );
sewardj170ee212004-12-10 18:57:51 +00002316
2317 di = diLo64 = diHi64 = NULL;
sewardj2e595852005-06-30 23:33:37 +00002318 eBias = eBiasLo64 = eBiasHi64 = NULL;
sewardj170ee212004-12-10 18:57:51 +00002319 addrAct = addrLo64 = addrHi64 = NULL;
2320 vdataLo64 = vdataHi64 = NULL;
njn25e49d8e72002-09-23 09:36:25 +00002321
sewardj95448072004-11-22 20:19:51 +00002322 if (data) {
2323 tl_assert(!vdata);
2324 tl_assert(isOriginalAtom(mce, data));
2325 tl_assert(bias == 0);
2326 vdata = expr2vbits( mce, data );
2327 } else {
2328 tl_assert(vdata);
2329 }
njn25e49d8e72002-09-23 09:36:25 +00002330
sewardj95448072004-11-22 20:19:51 +00002331 tl_assert(isOriginalAtom(mce,addr));
2332 tl_assert(isShadowAtom(mce,vdata));
njn25e49d8e72002-09-23 09:36:25 +00002333
sewardj95448072004-11-22 20:19:51 +00002334 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
njn25e49d8e72002-09-23 09:36:25 +00002335
sewardj95448072004-11-22 20:19:51 +00002336 /* First, emit a definedness test for the address. This also sets
2337 the address (shadow) to 'defined' following the test. */
2338 complainIfUndefined( mce, addr );
njn25e49d8e72002-09-23 09:36:25 +00002339
sewardj170ee212004-12-10 18:57:51 +00002340 /* Now decide which helper function to call to write the data V
2341 bits into shadow memory. */
sewardj2e595852005-06-30 23:33:37 +00002342 if (end == Iend_LE) {
2343 switch (ty) {
2344 case Ity_V128: /* we'll use the helper twice */
2345 case Ity_I64: helper = &MC_(helperc_STOREV8le);
2346 hname = "MC_(helperc_STOREV8le)";
2347 break;
2348 case Ity_I32: helper = &MC_(helperc_STOREV4le);
2349 hname = "MC_(helperc_STOREV4le)";
2350 break;
2351 case Ity_I16: helper = &MC_(helperc_STOREV2le);
2352 hname = "MC_(helperc_STOREV2le)";
2353 break;
sewardj8cf88b72005-07-08 01:29:33 +00002354 case Ity_I8: helper = &MC_(helperc_STOREV1);
2355 hname = "MC_(helperc_STOREV1)";
sewardj2e595852005-06-30 23:33:37 +00002356 break;
2357 default: VG_(tool_panic)("memcheck:do_shadow_Store(LE)");
2358 }
2359 } else {
sewardj8cf88b72005-07-08 01:29:33 +00002360 switch (ty) {
2361 case Ity_V128: /* we'll use the helper twice */
2362 case Ity_I64: helper = &MC_(helperc_STOREV8be);
2363 hname = "MC_(helperc_STOREV8be)";
2364 break;
2365 case Ity_I32: helper = &MC_(helperc_STOREV4be);
2366 hname = "MC_(helperc_STOREV4be)";
2367 break;
2368 case Ity_I16: helper = &MC_(helperc_STOREV2be);
2369 hname = "MC_(helperc_STOREV2be)";
2370 break;
2371 case Ity_I8: helper = &MC_(helperc_STOREV1);
2372 hname = "MC_(helperc_STOREV1)";
2373 break;
2374 default: VG_(tool_panic)("memcheck:do_shadow_Store(BE)");
2375 }
sewardj95448072004-11-22 20:19:51 +00002376 }
njn25e49d8e72002-09-23 09:36:25 +00002377
sewardj170ee212004-12-10 18:57:51 +00002378 if (ty == Ity_V128) {
2379
sewardj20d38f22005-02-07 23:50:18 +00002380 /* V128-bit case */
sewardj170ee212004-12-10 18:57:51 +00002381 /* See comment in next clause re 64-bit regparms */
sewardj2e595852005-06-30 23:33:37 +00002382 /* also, need to be careful about endianness */
2383
2384 Int offLo64, offHi64;
2385 if (end == Iend_LE) {
2386 offLo64 = 0;
2387 offHi64 = 8;
2388 } else {
sewardj2e595852005-06-30 23:33:37 +00002389 offLo64 = 8;
2390 offHi64 = 0;
2391 }
2392
2393 eBiasLo64 = tyAddr==Ity_I32 ? mkU32(bias+offLo64) : mkU64(bias+offLo64);
2394 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBiasLo64) );
sewardj20d38f22005-02-07 23:50:18 +00002395 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj170ee212004-12-10 18:57:51 +00002396 diLo64 = unsafeIRDirty_0_N(
2397 1/*regparms*/, hname, helper,
2398 mkIRExprVec_2( addrLo64, vdataLo64 ));
2399
sewardj2e595852005-06-30 23:33:37 +00002400 eBiasHi64 = tyAddr==Ity_I32 ? mkU32(bias+offHi64) : mkU64(bias+offHi64);
2401 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBiasHi64) );
sewardj20d38f22005-02-07 23:50:18 +00002402 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj170ee212004-12-10 18:57:51 +00002403 diHi64 = unsafeIRDirty_0_N(
2404 1/*regparms*/, hname, helper,
2405 mkIRExprVec_2( addrHi64, vdataHi64 ));
2406
2407 setHelperAnns( mce, diLo64 );
2408 setHelperAnns( mce, diHi64 );
2409 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2410 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2411
sewardj95448072004-11-22 20:19:51 +00002412 } else {
sewardj170ee212004-12-10 18:57:51 +00002413
2414 /* 8/16/32/64-bit cases */
2415 /* Generate the actual address into addrAct. */
2416 if (bias == 0) {
2417 addrAct = addr;
2418 } else {
2419 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2420 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2421 }
2422
2423 if (ty == Ity_I64) {
2424 /* We can't do this with regparm 2 on 32-bit platforms, since
2425 the back ends aren't clever enough to handle 64-bit
2426 regparm args. Therefore be different. */
2427 di = unsafeIRDirty_0_N(
2428 1/*regparms*/, hname, helper,
2429 mkIRExprVec_2( addrAct, vdata ));
2430 } else {
2431 di = unsafeIRDirty_0_N(
2432 2/*regparms*/, hname, helper,
2433 mkIRExprVec_2( addrAct,
2434 zwidenToHostWord( mce, vdata )));
2435 }
2436 setHelperAnns( mce, di );
2437 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj95448072004-11-22 20:19:51 +00002438 }
njn25e49d8e72002-09-23 09:36:25 +00002439
sewardj95448072004-11-22 20:19:51 +00002440}
njn25e49d8e72002-09-23 09:36:25 +00002441
njn25e49d8e72002-09-23 09:36:25 +00002442
sewardj95448072004-11-22 20:19:51 +00002443/* Do lazy pessimistic propagation through a dirty helper call, by
2444 looking at the annotations on it. This is the most complex part of
2445 Memcheck. */
njn25e49d8e72002-09-23 09:36:25 +00002446
sewardj95448072004-11-22 20:19:51 +00002447static IRType szToITy ( Int n )
2448{
2449 switch (n) {
2450 case 1: return Ity_I8;
2451 case 2: return Ity_I16;
2452 case 4: return Ity_I32;
2453 case 8: return Ity_I64;
2454 default: VG_(tool_panic)("szToITy(memcheck)");
2455 }
2456}
njn25e49d8e72002-09-23 09:36:25 +00002457
sewardj95448072004-11-22 20:19:51 +00002458static
2459void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2460{
sewardj2e595852005-06-30 23:33:37 +00002461 Int i, n, offset, toDo, gSz, gOff;
2462 IRAtom *src, *here, *curr;
2463 IRType tyAddr, tySrc, tyDst;
2464 IRTemp dst;
2465 IREndness end;
2466
2467 /* What's the native endianness? We need to know this. */
sewardj6e340c72005-07-10 00:53:42 +00002468# if defined(VG_BIGENDIAN)
sewardj2e595852005-06-30 23:33:37 +00002469 end = Iend_BE;
sewardj6e340c72005-07-10 00:53:42 +00002470# elif defined(VG_LITTLEENDIAN)
sewardj2e595852005-06-30 23:33:37 +00002471 end = Iend_LE;
2472# else
2473# error "Unknown endianness"
2474# endif
njn25e49d8e72002-09-23 09:36:25 +00002475
sewardj95448072004-11-22 20:19:51 +00002476 /* First check the guard. */
2477 complainIfUndefined(mce, d->guard);
2478
2479 /* Now round up all inputs and PCast over them. */
sewardj7cf97ee2004-11-28 14:25:01 +00002480 curr = definedOfType(Ity_I32);
sewardj95448072004-11-22 20:19:51 +00002481
2482 /* Inputs: unmasked args */
2483 for (i = 0; d->args[i]; i++) {
2484 if (d->cee->mcx_mask & (1<<i)) {
2485 /* ignore this arg */
njn25e49d8e72002-09-23 09:36:25 +00002486 } else {
sewardj95448072004-11-22 20:19:51 +00002487 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2488 curr = mkUifU32(mce, here, curr);
njn25e49d8e72002-09-23 09:36:25 +00002489 }
2490 }
sewardj95448072004-11-22 20:19:51 +00002491
2492 /* Inputs: guest state that we read. */
2493 for (i = 0; i < d->nFxState; i++) {
2494 tl_assert(d->fxState[i].fx != Ifx_None);
2495 if (d->fxState[i].fx == Ifx_Write)
2496 continue;
sewardja7203252004-11-26 19:17:47 +00002497
2498 /* Ignore any sections marked as 'always defined'. */
2499 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
sewardje9e16d32004-12-10 13:17:55 +00002500 if (0)
sewardja7203252004-11-26 19:17:47 +00002501 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2502 d->fxState[i].offset, d->fxState[i].size );
2503 continue;
2504 }
2505
sewardj95448072004-11-22 20:19:51 +00002506 /* This state element is read or modified. So we need to
sewardje9e16d32004-12-10 13:17:55 +00002507 consider it. If larger than 8 bytes, deal with it in 8-byte
2508 chunks. */
2509 gSz = d->fxState[i].size;
2510 gOff = d->fxState[i].offset;
2511 tl_assert(gSz > 0);
2512 while (True) {
2513 if (gSz == 0) break;
2514 n = gSz <= 8 ? gSz : 8;
2515 /* update 'curr' with UifU of the state slice
2516 gOff .. gOff+n-1 */
2517 tySrc = szToITy( n );
2518 src = assignNew( mce, tySrc,
2519 shadow_GET(mce, gOff, tySrc ) );
2520 here = mkPCastTo( mce, Ity_I32, src );
2521 curr = mkUifU32(mce, here, curr);
2522 gSz -= n;
2523 gOff += n;
2524 }
2525
sewardj95448072004-11-22 20:19:51 +00002526 }
2527
2528 /* Inputs: memory. First set up some info needed regardless of
2529 whether we're doing reads or writes. */
2530 tyAddr = Ity_INVALID;
2531
2532 if (d->mFx != Ifx_None) {
2533 /* Because we may do multiple shadow loads/stores from the same
2534 base address, it's best to do a single test of its
2535 definedness right now. Post-instrumentation optimisation
2536 should remove all but this test. */
2537 tl_assert(d->mAddr);
2538 complainIfUndefined(mce, d->mAddr);
2539
2540 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
2541 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2542 tl_assert(tyAddr == mce->hWordTy); /* not really right */
2543 }
2544
2545 /* Deal with memory inputs (reads or modifies) */
2546 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2547 offset = 0;
2548 toDo = d->mSize;
sewardj2e595852005-06-30 23:33:37 +00002549 /* chew off 32-bit chunks. We don't care about the endianness
2550 since it's all going to be condensed down to a single bit,
2551 but nevertheless choose an endianness which is hopefully
2552 native to the platform. */
sewardj95448072004-11-22 20:19:51 +00002553 while (toDo >= 4) {
2554 here = mkPCastTo(
2555 mce, Ity_I32,
sewardj2e595852005-06-30 23:33:37 +00002556 expr2vbits_Load ( mce, end, Ity_I32,
sewardj95448072004-11-22 20:19:51 +00002557 d->mAddr, d->mSize - toDo )
2558 );
2559 curr = mkUifU32(mce, here, curr);
2560 toDo -= 4;
2561 }
2562 /* chew off 16-bit chunks */
2563 while (toDo >= 2) {
2564 here = mkPCastTo(
2565 mce, Ity_I32,
sewardj2e595852005-06-30 23:33:37 +00002566 expr2vbits_Load ( mce, end, Ity_I16,
sewardj95448072004-11-22 20:19:51 +00002567 d->mAddr, d->mSize - toDo )
2568 );
2569 curr = mkUifU32(mce, here, curr);
2570 toDo -= 2;
2571 }
2572 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
2573 }
2574
2575 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2576 all the inputs to the helper. Now we need to re-distribute the
2577 results to all destinations. */
2578
2579 /* Outputs: the destination temporary, if there is one. */
2580 if (d->tmp != IRTemp_INVALID) {
2581 dst = findShadowTmp(mce, d->tmp);
2582 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2583 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2584 }
2585
2586 /* Outputs: guest state that we write or modify. */
2587 for (i = 0; i < d->nFxState; i++) {
2588 tl_assert(d->fxState[i].fx != Ifx_None);
2589 if (d->fxState[i].fx == Ifx_Read)
2590 continue;
sewardja7203252004-11-26 19:17:47 +00002591 /* Ignore any sections marked as 'always defined'. */
2592 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2593 continue;
sewardje9e16d32004-12-10 13:17:55 +00002594 /* This state element is written or modified. So we need to
2595 consider it. If larger than 8 bytes, deal with it in 8-byte
2596 chunks. */
2597 gSz = d->fxState[i].size;
2598 gOff = d->fxState[i].offset;
2599 tl_assert(gSz > 0);
2600 while (True) {
2601 if (gSz == 0) break;
2602 n = gSz <= 8 ? gSz : 8;
2603 /* Write suitably-casted 'curr' to the state slice
2604 gOff .. gOff+n-1 */
2605 tyDst = szToITy( n );
2606 do_shadow_PUT( mce, gOff,
2607 NULL, /* original atom */
2608 mkPCastTo( mce, tyDst, curr ) );
2609 gSz -= n;
2610 gOff += n;
2611 }
sewardj95448072004-11-22 20:19:51 +00002612 }
2613
sewardj2e595852005-06-30 23:33:37 +00002614 /* Outputs: memory that we write or modify. Same comments about
2615 endianness as above apply. */
sewardj95448072004-11-22 20:19:51 +00002616 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2617 offset = 0;
2618 toDo = d->mSize;
2619 /* chew off 32-bit chunks */
2620 while (toDo >= 4) {
sewardj2e595852005-06-30 23:33:37 +00002621 do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
2622 NULL, /* original data */
2623 mkPCastTo( mce, Ity_I32, curr ) );
sewardj95448072004-11-22 20:19:51 +00002624 toDo -= 4;
2625 }
2626 /* chew off 16-bit chunks */
2627 while (toDo >= 2) {
sewardj2e595852005-06-30 23:33:37 +00002628 do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
2629 NULL, /* original data */
2630 mkPCastTo( mce, Ity_I16, curr ) );
sewardj95448072004-11-22 20:19:51 +00002631 toDo -= 2;
2632 }
2633 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
2634 }
2635
njn25e49d8e72002-09-23 09:36:25 +00002636}
2637
sewardj826ec492005-05-12 18:05:00 +00002638/* We have an ABI hint telling us that [base .. base+len-1] is to
2639 become undefined ("writable"). Generate code to call a helper to
2640 notify the A/V bit machinery of this fact.
2641
2642 We call
2643 void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len );
2644*/
2645static
2646void do_AbiHint ( MCEnv* mce, IRExpr* base, Int len )
2647{
2648 IRDirty* di;
2649 di = unsafeIRDirty_0_N(
2650 0/*regparms*/,
2651 "MC_(helperc_MAKE_STACK_UNINIT)",
2652 &MC_(helperc_MAKE_STACK_UNINIT),
2653 mkIRExprVec_2( base, mkIRExpr_HWord( (UInt)len) )
2654 );
2655 stmt( mce->bb, IRStmt_Dirty(di) );
2656}
2657
njn25e49d8e72002-09-23 09:36:25 +00002658
sewardj95448072004-11-22 20:19:51 +00002659/*------------------------------------------------------------*/
2660/*--- Memcheck main ---*/
2661/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00002662
sewardj95448072004-11-22 20:19:51 +00002663static Bool isBogusAtom ( IRAtom* at )
njn25e49d8e72002-09-23 09:36:25 +00002664{
sewardj95448072004-11-22 20:19:51 +00002665 ULong n = 0;
2666 IRConst* con;
sewardj710d6c22005-03-20 18:55:15 +00002667 tl_assert(isIRAtom(at));
sewardj95448072004-11-22 20:19:51 +00002668 if (at->tag == Iex_Tmp)
2669 return False;
2670 tl_assert(at->tag == Iex_Const);
2671 con = at->Iex.Const.con;
2672 switch (con->tag) {
sewardjd5204dc2004-12-31 01:16:11 +00002673 case Ico_U1: return False;
2674 case Ico_U8: n = (ULong)con->Ico.U8; break;
2675 case Ico_U16: n = (ULong)con->Ico.U16; break;
2676 case Ico_U32: n = (ULong)con->Ico.U32; break;
2677 case Ico_U64: n = (ULong)con->Ico.U64; break;
2678 case Ico_F64: return False;
2679 case Ico_F64i: return False;
2680 case Ico_V128: return False;
sewardj95448072004-11-22 20:19:51 +00002681 default: ppIRExpr(at); tl_assert(0);
2682 }
2683 /* VG_(printf)("%llx\n", n); */
sewardj96a922e2005-04-23 23:26:29 +00002684 return (/*32*/ n == 0xFEFEFEFFULL
2685 /*32*/ || n == 0x80808080ULL
tomd9774d72005-06-27 08:11:01 +00002686 /*64*/ || n == 0xFFFFFFFFFEFEFEFFULL
sewardj96a922e2005-04-23 23:26:29 +00002687 /*64*/ || n == 0xFEFEFEFEFEFEFEFFULL
tomd9774d72005-06-27 08:11:01 +00002688 /*64*/ || n == 0x0000000000008080ULL
sewardj96a922e2005-04-23 23:26:29 +00002689 /*64*/ || n == 0x8080808080808080ULL
2690 /*64*/ || n == 0x0101010101010101ULL
2691 );
sewardj95448072004-11-22 20:19:51 +00002692}
njn25e49d8e72002-09-23 09:36:25 +00002693
sewardj95448072004-11-22 20:19:51 +00002694static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2695{
sewardjd5204dc2004-12-31 01:16:11 +00002696 Int i;
2697 IRExpr* e;
2698 IRDirty* d;
sewardj95448072004-11-22 20:19:51 +00002699 switch (st->tag) {
2700 case Ist_Tmp:
2701 e = st->Ist.Tmp.data;
2702 switch (e->tag) {
2703 case Iex_Get:
2704 case Iex_Tmp:
2705 return False;
sewardjd5204dc2004-12-31 01:16:11 +00002706 case Iex_Const:
2707 return isBogusAtom(e);
sewardj95448072004-11-22 20:19:51 +00002708 case Iex_Unop:
2709 return isBogusAtom(e->Iex.Unop.arg);
sewardjd5204dc2004-12-31 01:16:11 +00002710 case Iex_GetI:
2711 return isBogusAtom(e->Iex.GetI.ix);
sewardj95448072004-11-22 20:19:51 +00002712 case Iex_Binop:
2713 return isBogusAtom(e->Iex.Binop.arg1)
2714 || isBogusAtom(e->Iex.Binop.arg2);
2715 case Iex_Mux0X:
2716 return isBogusAtom(e->Iex.Mux0X.cond)
2717 || isBogusAtom(e->Iex.Mux0X.expr0)
2718 || isBogusAtom(e->Iex.Mux0X.exprX);
sewardj2e595852005-06-30 23:33:37 +00002719 case Iex_Load:
2720 return isBogusAtom(e->Iex.Load.addr);
sewardj95448072004-11-22 20:19:51 +00002721 case Iex_CCall:
2722 for (i = 0; e->Iex.CCall.args[i]; i++)
2723 if (isBogusAtom(e->Iex.CCall.args[i]))
2724 return True;
2725 return False;
2726 default:
2727 goto unhandled;
2728 }
sewardjd5204dc2004-12-31 01:16:11 +00002729 case Ist_Dirty:
2730 d = st->Ist.Dirty.details;
2731 for (i = 0; d->args[i]; i++)
2732 if (isBogusAtom(d->args[i]))
2733 return True;
2734 if (d->guard && isBogusAtom(d->guard))
2735 return True;
2736 if (d->mAddr && isBogusAtom(d->mAddr))
2737 return True;
2738 return False;
sewardj95448072004-11-22 20:19:51 +00002739 case Ist_Put:
2740 return isBogusAtom(st->Ist.Put.data);
sewardjd5204dc2004-12-31 01:16:11 +00002741 case Ist_PutI:
2742 return isBogusAtom(st->Ist.PutI.ix)
2743 || isBogusAtom(st->Ist.PutI.data);
sewardj2e595852005-06-30 23:33:37 +00002744 case Ist_Store:
2745 return isBogusAtom(st->Ist.Store.addr)
2746 || isBogusAtom(st->Ist.Store.data);
sewardj95448072004-11-22 20:19:51 +00002747 case Ist_Exit:
sewardjd5204dc2004-12-31 01:16:11 +00002748 return isBogusAtom(st->Ist.Exit.guard);
sewardj826ec492005-05-12 18:05:00 +00002749 case Ist_AbiHint:
2750 return isBogusAtom(st->Ist.AbiHint.base);
sewardj21dc3452005-03-21 00:27:41 +00002751 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00002752 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00002753 case Ist_MFence:
2754 return False;
sewardj95448072004-11-22 20:19:51 +00002755 default:
2756 unhandled:
2757 ppIRStmt(st);
2758 VG_(tool_panic)("hasBogusLiterals");
2759 }
2760}
njn25e49d8e72002-09-23 09:36:25 +00002761
njn25e49d8e72002-09-23 09:36:25 +00002762
njn51d827b2005-05-09 01:02:08 +00002763IRBB* MC_(instrument) ( IRBB* bb_in, VexGuestLayout* layout,
sewardjd54babf2005-03-21 00:55:49 +00002764 IRType gWordTy, IRType hWordTy )
sewardj95448072004-11-22 20:19:51 +00002765{
sewardj151b90d2005-07-06 19:42:23 +00002766 Bool verboze = False; //True;
2767 Bool bogus;
sewardjd5204dc2004-12-31 01:16:11 +00002768 Int i, j, first_stmt;
sewardj95448072004-11-22 20:19:51 +00002769 IRStmt* st;
sewardjd5204dc2004-12-31 01:16:11 +00002770 MCEnv mce;
sewardjd54babf2005-03-21 00:55:49 +00002771 IRBB* bb;
2772
2773 if (gWordTy != hWordTy) {
2774 /* We don't currently support this case. */
2775 VG_(tool_panic)("host/guest word size mismatch");
2776 }
njn25e49d8e72002-09-23 09:36:25 +00002777
sewardj6cf40ff2005-04-20 22:31:26 +00002778 /* Check we're not completely nuts */
2779 tl_assert(sizeof(UWord) == sizeof(void*));
2780 tl_assert(sizeof(Word) == sizeof(void*));
2781 tl_assert(sizeof(ULong) == 8);
2782 tl_assert(sizeof(Long) == 8);
2783 tl_assert(sizeof(UInt) == 4);
2784 tl_assert(sizeof(Int) == 4);
2785
sewardj95448072004-11-22 20:19:51 +00002786 /* Set up BB */
sewardjd54babf2005-03-21 00:55:49 +00002787 bb = emptyIRBB();
sewardj95448072004-11-22 20:19:51 +00002788 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
2789 bb->next = dopyIRExpr(bb_in->next);
2790 bb->jumpkind = bb_in->jumpkind;
njn25e49d8e72002-09-23 09:36:25 +00002791
sewardj95448072004-11-22 20:19:51 +00002792 /* Set up the running environment. Only .bb is modified as we go
2793 along. */
2794 mce.bb = bb;
2795 mce.layout = layout;
2796 mce.n_originalTmps = bb->tyenv->types_used;
2797 mce.hWordTy = hWordTy;
sewardjd5204dc2004-12-31 01:16:11 +00002798 mce.bogusLiterals = False;
sewardj95448072004-11-22 20:19:51 +00002799 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2800 for (i = 0; i < mce.n_originalTmps; i++)
2801 mce.tmpMap[i] = IRTemp_INVALID;
2802
sewardj151b90d2005-07-06 19:42:23 +00002803 /* Make a preliminary inspection of the statements, to see if there
2804 are any dodgy-looking literals. If there are, we generate
2805 extra-detailed (hence extra-expensive) instrumentation in
2806 places. Scan the whole bb even if dodgyness is found earlier,
2807 so that the flatness assertion is applied to all stmts. */
2808
2809 bogus = False;
sewardj95448072004-11-22 20:19:51 +00002810
2811 for (i = 0; i < bb_in->stmts_used; i++) {
sewardj151b90d2005-07-06 19:42:23 +00002812
sewardj95448072004-11-22 20:19:51 +00002813 st = bb_in->stmts[i];
sewardj21dc3452005-03-21 00:27:41 +00002814 tl_assert(st);
sewardj95448072004-11-22 20:19:51 +00002815 tl_assert(isFlatIRStmt(st));
2816
sewardj151b90d2005-07-06 19:42:23 +00002817 if (!bogus) {
2818 bogus = checkForBogusLiterals(st);
2819 if (0 && bogus) {
sewardj95448072004-11-22 20:19:51 +00002820 VG_(printf)("bogus: ");
2821 ppIRStmt(st);
2822 VG_(printf)("\n");
2823 }
2824 }
sewardjd5204dc2004-12-31 01:16:11 +00002825
sewardj151b90d2005-07-06 19:42:23 +00002826 }
2827
2828 mce.bogusLiterals = bogus;
2829
2830 /* Iterate over the stmts to generate instrumentation. */
2831
2832 for (i = 0; i < bb_in->stmts_used; i++) {
2833
2834 st = bb_in->stmts[i];
sewardj95448072004-11-22 20:19:51 +00002835 first_stmt = bb->stmts_used;
2836
2837 if (verboze) {
2838 ppIRStmt(st);
2839 VG_(printf)("\n\n");
2840 }
2841
sewardj29faa502005-03-16 18:20:21 +00002842 /* Generate instrumentation code for each stmt ... */
2843
sewardj95448072004-11-22 20:19:51 +00002844 switch (st->tag) {
2845
2846 case Ist_Tmp:
2847 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
2848 expr2vbits( &mce, st->Ist.Tmp.data) );
njn25e49d8e72002-09-23 09:36:25 +00002849 break;
2850
sewardj95448072004-11-22 20:19:51 +00002851 case Ist_Put:
2852 do_shadow_PUT( &mce,
2853 st->Ist.Put.offset,
2854 st->Ist.Put.data,
2855 NULL /* shadow atom */ );
njn25e49d8e72002-09-23 09:36:25 +00002856 break;
2857
sewardj95448072004-11-22 20:19:51 +00002858 case Ist_PutI:
2859 do_shadow_PUTI( &mce,
2860 st->Ist.PutI.descr,
2861 st->Ist.PutI.ix,
2862 st->Ist.PutI.bias,
2863 st->Ist.PutI.data );
njn25e49d8e72002-09-23 09:36:25 +00002864 break;
2865
sewardj2e595852005-06-30 23:33:37 +00002866 case Ist_Store:
2867 do_shadow_Store( &mce, st->Ist.Store.end,
2868 st->Ist.Store.addr, 0/* addr bias */,
2869 st->Ist.Store.data,
2870 NULL /* shadow data */ );
njn25e49d8e72002-09-23 09:36:25 +00002871 break;
2872
sewardj95448072004-11-22 20:19:51 +00002873 case Ist_Exit:
sewardjd5204dc2004-12-31 01:16:11 +00002874 complainIfUndefined( &mce, st->Ist.Exit.guard );
njn25e49d8e72002-09-23 09:36:25 +00002875 break;
2876
sewardj21dc3452005-03-21 00:27:41 +00002877 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00002878 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00002879 case Ist_MFence:
2880 break;
2881
sewardj95448072004-11-22 20:19:51 +00002882 case Ist_Dirty:
2883 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
njn25e49d8e72002-09-23 09:36:25 +00002884 break;
2885
sewardj826ec492005-05-12 18:05:00 +00002886 case Ist_AbiHint:
2887 do_AbiHint( &mce, st->Ist.AbiHint.base, st->Ist.AbiHint.len );
2888 break;
2889
njn25e49d8e72002-09-23 09:36:25 +00002890 default:
sewardj95448072004-11-22 20:19:51 +00002891 VG_(printf)("\n");
2892 ppIRStmt(st);
2893 VG_(printf)("\n");
2894 VG_(tool_panic)("memcheck: unhandled IRStmt");
2895
2896 } /* switch (st->tag) */
2897
2898 if (verboze) {
2899 for (j = first_stmt; j < bb->stmts_used; j++) {
2900 VG_(printf)(" ");
2901 ppIRStmt(bb->stmts[j]);
2902 VG_(printf)("\n");
2903 }
2904 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00002905 }
sewardj95448072004-11-22 20:19:51 +00002906
sewardj29faa502005-03-16 18:20:21 +00002907 /* ... and finally copy the stmt itself to the output. */
sewardj95448072004-11-22 20:19:51 +00002908 addStmtToIRBB(bb, st);
2909
njn25e49d8e72002-09-23 09:36:25 +00002910 }
njn25e49d8e72002-09-23 09:36:25 +00002911
sewardj95448072004-11-22 20:19:51 +00002912 /* Now we need to complain if the jump target is undefined. */
2913 first_stmt = bb->stmts_used;
njn25e49d8e72002-09-23 09:36:25 +00002914
sewardj95448072004-11-22 20:19:51 +00002915 if (verboze) {
2916 VG_(printf)("bb->next = ");
2917 ppIRExpr(bb->next);
2918 VG_(printf)("\n\n");
2919 }
njn25e49d8e72002-09-23 09:36:25 +00002920
sewardj95448072004-11-22 20:19:51 +00002921 complainIfUndefined( &mce, bb->next );
njn25e49d8e72002-09-23 09:36:25 +00002922
sewardj95448072004-11-22 20:19:51 +00002923 if (verboze) {
2924 for (j = first_stmt; j < bb->stmts_used; j++) {
2925 VG_(printf)(" ");
2926 ppIRStmt(bb->stmts[j]);
2927 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00002928 }
sewardj95448072004-11-22 20:19:51 +00002929 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00002930 }
njn25e49d8e72002-09-23 09:36:25 +00002931
sewardj95448072004-11-22 20:19:51 +00002932 return bb;
2933}
njn25e49d8e72002-09-23 09:36:25 +00002934
2935/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00002936/*--- end mc_translate.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00002937/*--------------------------------------------------------------------*/