blob: bf0ca3f1cbdccbd95492241b1187d10489200e5f [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"
sewardj53ee1fc2005-12-23 02:29:58 +000033#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_tooliface.h"
sewardj53ee1fc2005-12-23 02:29:58 +000037#include "pub_tool_machine.h" // VG_(fnptr_to_fnentry)
njnc7561b92005-06-19 01:24:32 +000038#include "mc_include.h"
njn25e49d8e72002-09-23 09:36:25 +000039
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#)
sewardj1bc82102005-12-23 00:16:24 +0000686 & (7<<1)
sewardj992dff92005-10-07 11:08:55 +0000687
688 The "& (7<<1)" reflects the fact that all result bits except 3,2,1
689 are zero and therefore defined (viz, zero).
sewardja9e62a92005-10-07 12:13:21 +0000690
691 Also deal with a special case better:
692
693 CmpORD32S(x,0)
694
695 Here, bit 3 (LT) of the result is a copy of the top bit of x and
696 will be defined even if the rest of x isn't. In which case we do:
697
698 CmpORD32S#(x,x#,0,{impliedly 0}#)
sewardj1bc82102005-12-23 00:16:24 +0000699 = PCast(x#) & (3<<1) -- standard interp for GT#,EQ#
700 | (x# >>u 31) << 3 -- LT# = x#[31]
sewardja9e62a92005-10-07 12:13:21 +0000701
sewardj1bc82102005-12-23 00:16:24 +0000702 Analogous handling for CmpORD64{S,U}.
sewardj992dff92005-10-07 11:08:55 +0000703*/
sewardja9e62a92005-10-07 12:13:21 +0000704static Bool isZeroU32 ( IRAtom* e )
705{
706 return
707 toBool( e->tag == Iex_Const
708 && e->Iex.Const.con->tag == Ico_U32
709 && e->Iex.Const.con->Ico.U32 == 0 );
710}
711
sewardj1bc82102005-12-23 00:16:24 +0000712static Bool isZeroU64 ( IRAtom* e )
sewardj992dff92005-10-07 11:08:55 +0000713{
sewardj1bc82102005-12-23 00:16:24 +0000714 return
715 toBool( e->tag == Iex_Const
716 && e->Iex.Const.con->tag == Ico_U64
717 && e->Iex.Const.con->Ico.U64 == 0 );
718}
719
720static IRAtom* doCmpORD ( MCEnv* mce,
721 IROp cmp_op,
722 IRAtom* xxhash, IRAtom* yyhash,
723 IRAtom* xx, IRAtom* yy )
724{
725 Bool m64 = cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD64U;
726 Bool syned = cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD32S;
727 IROp opOR = m64 ? Iop_Or64 : Iop_Or32;
728 IROp opAND = m64 ? Iop_And64 : Iop_And32;
729 IROp opSHL = m64 ? Iop_Shl64 : Iop_Shl32;
730 IROp opSHR = m64 ? Iop_Shr64 : Iop_Shr32;
731 IRType ty = m64 ? Ity_I64 : Ity_I32;
732 Int width = m64 ? 64 : 32;
733
734 Bool (*isZero)(IRAtom*) = m64 ? isZeroU64 : isZeroU32;
735
736 IRAtom* threeLeft1 = NULL;
737 IRAtom* sevenLeft1 = NULL;
738
sewardj992dff92005-10-07 11:08:55 +0000739 tl_assert(isShadowAtom(mce,xxhash));
740 tl_assert(isShadowAtom(mce,yyhash));
741 tl_assert(isOriginalAtom(mce,xx));
742 tl_assert(isOriginalAtom(mce,yy));
743 tl_assert(sameKindedAtoms(xxhash,xx));
744 tl_assert(sameKindedAtoms(yyhash,yy));
sewardj1bc82102005-12-23 00:16:24 +0000745 tl_assert(cmp_op == Iop_CmpORD32S || cmp_op == Iop_CmpORD32U
746 || cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD64U);
sewardj992dff92005-10-07 11:08:55 +0000747
sewardja9e62a92005-10-07 12:13:21 +0000748 if (0) {
749 ppIROp(cmp_op); VG_(printf)(" ");
750 ppIRExpr(xx); VG_(printf)(" "); ppIRExpr( yy ); VG_(printf)("\n");
751 }
752
sewardj1bc82102005-12-23 00:16:24 +0000753 if (syned && isZero(yy)) {
sewardja9e62a92005-10-07 12:13:21 +0000754 /* fancy interpretation */
755 /* if yy is zero, then it must be fully defined (zero#). */
sewardj1bc82102005-12-23 00:16:24 +0000756 tl_assert(isZero(yyhash));
757 threeLeft1 = m64 ? mkU64(3<<1) : mkU32(3<<1);
sewardja9e62a92005-10-07 12:13:21 +0000758 return
759 binop(
sewardj1bc82102005-12-23 00:16:24 +0000760 opOR,
sewardja9e62a92005-10-07 12:13:21 +0000761 assignNew(
sewardj1bc82102005-12-23 00:16:24 +0000762 mce,ty,
sewardja9e62a92005-10-07 12:13:21 +0000763 binop(
sewardj1bc82102005-12-23 00:16:24 +0000764 opAND,
765 mkPCastTo(mce,ty, xxhash),
766 threeLeft1
sewardja9e62a92005-10-07 12:13:21 +0000767 )),
768 assignNew(
sewardj1bc82102005-12-23 00:16:24 +0000769 mce,ty,
sewardja9e62a92005-10-07 12:13:21 +0000770 binop(
sewardj1bc82102005-12-23 00:16:24 +0000771 opSHL,
sewardja9e62a92005-10-07 12:13:21 +0000772 assignNew(
sewardj1bc82102005-12-23 00:16:24 +0000773 mce,ty,
774 binop(opSHR, xxhash, mkU8(width-1))),
sewardja9e62a92005-10-07 12:13:21 +0000775 mkU8(3)
776 ))
777 );
778 } else {
779 /* standard interpretation */
sewardj1bc82102005-12-23 00:16:24 +0000780 sevenLeft1 = m64 ? mkU64(7<<1) : mkU32(7<<1);
sewardja9e62a92005-10-07 12:13:21 +0000781 return
782 binop(
sewardj1bc82102005-12-23 00:16:24 +0000783 opAND,
784 mkPCastTo( mce,ty,
785 mkUifU(mce,ty, xxhash,yyhash)),
786 sevenLeft1
sewardja9e62a92005-10-07 12:13:21 +0000787 );
788 }
sewardj992dff92005-10-07 11:08:55 +0000789}
790
791
sewardj95448072004-11-22 20:19:51 +0000792/*------------------------------------------------------------*/
793/*--- Emit a test and complaint if something is undefined. ---*/
794/*------------------------------------------------------------*/
795
796/* Set the annotations on a dirty helper to indicate that the stack
797 pointer and instruction pointers might be read. This is the
798 behaviour of all 'emit-a-complaint' style functions we might
799 call. */
800
801static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
802 di->nFxState = 2;
803 di->fxState[0].fx = Ifx_Read;
804 di->fxState[0].offset = mce->layout->offset_SP;
805 di->fxState[0].size = mce->layout->sizeof_SP;
806 di->fxState[1].fx = Ifx_Read;
807 di->fxState[1].offset = mce->layout->offset_IP;
808 di->fxState[1].size = mce->layout->sizeof_IP;
809}
810
811
812/* Check the supplied **original** atom for undefinedness, and emit a
813 complaint if so. Once that happens, mark it as defined. This is
814 possible because the atom is either a tmp or literal. If it's a
815 tmp, it will be shadowed by a tmp, and so we can set the shadow to
816 be defined. In fact as mentioned above, we will have to allocate a
817 new tmp to carry the new 'defined' shadow value, and update the
818 original->tmp mapping accordingly; we cannot simply assign a new
819 value to an existing shadow tmp as this breaks SSAness -- resulting
820 in the post-instrumentation sanity checker spluttering in disapproval.
821*/
822static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
823{
sewardj7cf97ee2004-11-28 14:25:01 +0000824 IRAtom* vatom;
825 IRType ty;
826 Int sz;
827 IRDirty* di;
828 IRAtom* cond;
829
sewardj95448072004-11-22 20:19:51 +0000830 /* Since the original expression is atomic, there's no duplicated
831 work generated by making multiple V-expressions for it. So we
832 don't really care about the possibility that someone else may
833 also create a V-interpretion for it. */
834 tl_assert(isOriginalAtom(mce, atom));
sewardj7cf97ee2004-11-28 14:25:01 +0000835 vatom = expr2vbits( mce, atom );
sewardj95448072004-11-22 20:19:51 +0000836 tl_assert(isShadowAtom(mce, vatom));
837 tl_assert(sameKindedAtoms(atom, vatom));
838
sewardj7cf97ee2004-11-28 14:25:01 +0000839 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj95448072004-11-22 20:19:51 +0000840
841 /* sz is only used for constructing the error message */
sewardj7cf97ee2004-11-28 14:25:01 +0000842 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardj95448072004-11-22 20:19:51 +0000843
sewardj7cf97ee2004-11-28 14:25:01 +0000844 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardj95448072004-11-22 20:19:51 +0000845 /* cond will be 0 if all defined, and 1 if any not defined. */
846
sewardj95448072004-11-22 20:19:51 +0000847 switch (sz) {
848 case 0:
sewardj53ee1fc2005-12-23 02:29:58 +0000849 di = unsafeIRDirty_0_N(
850 0/*regparms*/,
851 "MC_(helperc_value_check0_fail)",
852 VG_(fnptr_to_fnentry)( &MC_(helperc_value_check0_fail) ),
853 mkIRExprVec_0()
854 );
sewardj95448072004-11-22 20:19:51 +0000855 break;
856 case 1:
sewardj53ee1fc2005-12-23 02:29:58 +0000857 di = unsafeIRDirty_0_N(
858 0/*regparms*/,
859 "MC_(helperc_value_check1_fail)",
860 VG_(fnptr_to_fnentry)( &MC_(helperc_value_check1_fail) ),
861 mkIRExprVec_0()
862 );
sewardj95448072004-11-22 20:19:51 +0000863 break;
864 case 4:
sewardj53ee1fc2005-12-23 02:29:58 +0000865 di = unsafeIRDirty_0_N(
866 0/*regparms*/,
867 "MC_(helperc_value_check4_fail)",
868 VG_(fnptr_to_fnentry)( &MC_(helperc_value_check4_fail) ),
869 mkIRExprVec_0()
870 );
sewardj95448072004-11-22 20:19:51 +0000871 break;
sewardj11bcc4e2005-04-23 22:38:38 +0000872 case 8:
sewardj53ee1fc2005-12-23 02:29:58 +0000873 di = unsafeIRDirty_0_N(
874 0/*regparms*/,
875 "MC_(helperc_value_check8_fail)",
876 VG_(fnptr_to_fnentry)( &MC_(helperc_value_check8_fail) ),
877 mkIRExprVec_0()
878 );
sewardj11bcc4e2005-04-23 22:38:38 +0000879 break;
sewardj95448072004-11-22 20:19:51 +0000880 default:
sewardj53ee1fc2005-12-23 02:29:58 +0000881 di = unsafeIRDirty_0_N(
882 1/*regparms*/,
883 "MC_(helperc_complain_undef)",
884 VG_(fnptr_to_fnentry)( &MC_(helperc_complain_undef) ),
885 mkIRExprVec_1( mkIRExpr_HWord( sz ))
886 );
sewardj95448072004-11-22 20:19:51 +0000887 break;
888 }
889 di->guard = cond;
890 setHelperAnns( mce, di );
891 stmt( mce->bb, IRStmt_Dirty(di));
892
893 /* Set the shadow tmp to be defined. First, update the
894 orig->shadow tmp mapping to reflect the fact that this shadow is
895 getting a new value. */
sewardj710d6c22005-03-20 18:55:15 +0000896 tl_assert(isIRAtom(vatom));
sewardj95448072004-11-22 20:19:51 +0000897 /* sameKindedAtoms ... */
898 if (vatom->tag == Iex_Tmp) {
899 tl_assert(atom->tag == Iex_Tmp);
900 newShadowTmp(mce, atom->Iex.Tmp.tmp);
901 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
902 definedOfType(ty));
903 }
904}
905
906
907/*------------------------------------------------------------*/
908/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
909/*------------------------------------------------------------*/
910
911/* Examine the always-defined sections declared in layout to see if
912 the (offset,size) section is within one. Note, is is an error to
913 partially fall into such a region: (offset,size) should either be
914 completely in such a region or completely not-in such a region.
915*/
916static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
917{
918 Int minoffD, maxoffD, i;
919 Int minoff = offset;
920 Int maxoff = minoff + size - 1;
921 tl_assert((minoff & ~0xFFFF) == 0);
922 tl_assert((maxoff & ~0xFFFF) == 0);
923
924 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
925 minoffD = mce->layout->alwaysDefd[i].offset;
926 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
927 tl_assert((minoffD & ~0xFFFF) == 0);
928 tl_assert((maxoffD & ~0xFFFF) == 0);
929
930 if (maxoff < minoffD || maxoffD < minoff)
931 continue; /* no overlap */
932 if (minoff >= minoffD && maxoff <= maxoffD)
933 return True; /* completely contained in an always-defd section */
934
935 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
936 }
937 return False; /* could not find any containing section */
938}
939
940
941/* Generate into bb suitable actions to shadow this Put. If the state
942 slice is marked 'always defined', do nothing. Otherwise, write the
943 supplied V bits to the shadow state. We can pass in either an
944 original atom or a V-atom, but not both. In the former case the
945 relevant V-bits are then generated from the original.
946*/
947static
948void do_shadow_PUT ( MCEnv* mce, Int offset,
949 IRAtom* atom, IRAtom* vatom )
950{
sewardj7cf97ee2004-11-28 14:25:01 +0000951 IRType ty;
sewardj95448072004-11-22 20:19:51 +0000952 if (atom) {
953 tl_assert(!vatom);
954 tl_assert(isOriginalAtom(mce, atom));
955 vatom = expr2vbits( mce, atom );
956 } else {
957 tl_assert(vatom);
958 tl_assert(isShadowAtom(mce, vatom));
959 }
960
sewardj7cf97ee2004-11-28 14:25:01 +0000961 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj95448072004-11-22 20:19:51 +0000962 tl_assert(ty != Ity_I1);
963 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
964 /* later: no ... */
965 /* emit code to emit a complaint if any of the vbits are 1. */
966 /* complainIfUndefined(mce, atom); */
967 } else {
968 /* Do a plain shadow Put. */
969 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
970 }
971}
972
973
974/* Return an expression which contains the V bits corresponding to the
975 given GETI (passed in in pieces).
976*/
977static
978void do_shadow_PUTI ( MCEnv* mce,
979 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
980{
sewardj7cf97ee2004-11-28 14:25:01 +0000981 IRAtom* vatom;
982 IRType ty, tyS;
983 Int arrSize;;
984
sewardj95448072004-11-22 20:19:51 +0000985 tl_assert(isOriginalAtom(mce,atom));
sewardj7cf97ee2004-11-28 14:25:01 +0000986 vatom = expr2vbits( mce, atom );
sewardj95448072004-11-22 20:19:51 +0000987 tl_assert(sameKindedAtoms(atom, vatom));
sewardj7cf97ee2004-11-28 14:25:01 +0000988 ty = descr->elemTy;
989 tyS = shadowType(ty);
990 arrSize = descr->nElems * sizeofIRType(ty);
sewardj95448072004-11-22 20:19:51 +0000991 tl_assert(ty != Ity_I1);
992 tl_assert(isOriginalAtom(mce,ix));
993 complainIfUndefined(mce,ix);
994 if (isAlwaysDefd(mce, descr->base, arrSize)) {
995 /* later: no ... */
996 /* emit code to emit a complaint if any of the vbits are 1. */
997 /* complainIfUndefined(mce, atom); */
998 } else {
999 /* Do a cloned version of the Put that refers to the shadow
1000 area. */
1001 IRArray* new_descr
1002 = mkIRArray( descr->base + mce->layout->total_sizeB,
1003 tyS, descr->nElems);
1004 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1005 }
1006}
1007
1008
1009/* Return an expression which contains the V bits corresponding to the
1010 given GET (passed in in pieces).
1011*/
1012static
1013IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1014{
1015 IRType tyS = shadowType(ty);
1016 tl_assert(ty != Ity_I1);
1017 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1018 /* Always defined, return all zeroes of the relevant type */
1019 return definedOfType(tyS);
1020 } else {
1021 /* return a cloned version of the Get that refers to the shadow
1022 area. */
1023 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1024 }
1025}
1026
1027
1028/* Return an expression which contains the V bits corresponding to the
1029 given GETI (passed in in pieces).
1030*/
1031static
1032IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
1033{
1034 IRType ty = descr->elemTy;
1035 IRType tyS = shadowType(ty);
1036 Int arrSize = descr->nElems * sizeofIRType(ty);
1037 tl_assert(ty != Ity_I1);
1038 tl_assert(isOriginalAtom(mce,ix));
1039 complainIfUndefined(mce,ix);
1040 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1041 /* Always defined, return all zeroes of the relevant type */
1042 return definedOfType(tyS);
1043 } else {
1044 /* return a cloned version of the Get that refers to the shadow
1045 area. */
1046 IRArray* new_descr
1047 = mkIRArray( descr->base + mce->layout->total_sizeB,
1048 tyS, descr->nElems);
1049 return IRExpr_GetI( new_descr, ix, bias );
1050 }
1051}
1052
1053
1054/*------------------------------------------------------------*/
1055/*--- Generating approximations for unknown operations, ---*/
1056/*--- using lazy-propagate semantics ---*/
1057/*------------------------------------------------------------*/
1058
1059/* Lazy propagation of undefinedness from two values, resulting in the
1060 specified shadow type.
1061*/
1062static
1063IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1064{
sewardj95448072004-11-22 20:19:51 +00001065 IRAtom* at;
sewardj37c31cc2005-04-26 23:49:24 +00001066 IRType t1 = typeOfIRExpr(mce->bb->tyenv, va1);
1067 IRType t2 = typeOfIRExpr(mce->bb->tyenv, va2);
sewardj95448072004-11-22 20:19:51 +00001068 tl_assert(isShadowAtom(mce,va1));
1069 tl_assert(isShadowAtom(mce,va2));
sewardj37c31cc2005-04-26 23:49:24 +00001070
1071 /* The general case is inefficient because PCast is an expensive
1072 operation. Here are some special cases which use PCast only
1073 once rather than twice. */
1074
1075 /* I64 x I64 -> I64 */
1076 if (t1 == Ity_I64 && t2 == Ity_I64 && finalVty == Ity_I64) {
1077 if (0) VG_(printf)("mkLazy2: I64 x I64 -> I64\n");
1078 at = mkUifU(mce, Ity_I64, va1, va2);
1079 at = mkPCastTo(mce, Ity_I64, at);
1080 return at;
1081 }
1082
1083 /* I64 x I64 -> I32 */
1084 if (t1 == Ity_I64 && t2 == Ity_I64 && finalVty == Ity_I32) {
1085 if (0) VG_(printf)("mkLazy2: I64 x I64 -> I32\n");
1086 at = mkUifU(mce, Ity_I64, va1, va2);
1087 at = mkPCastTo(mce, Ity_I32, at);
1088 return at;
1089 }
1090
1091 if (0) {
1092 VG_(printf)("mkLazy2 ");
1093 ppIRType(t1);
1094 VG_(printf)("_");
1095 ppIRType(t2);
1096 VG_(printf)("_");
1097 ppIRType(finalVty);
1098 VG_(printf)("\n");
1099 }
1100
1101 /* General case: force everything via 32-bit intermediaries. */
sewardj95448072004-11-22 20:19:51 +00001102 at = mkPCastTo(mce, Ity_I32, va1);
1103 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1104 at = mkPCastTo(mce, finalVty, at);
1105 return at;
1106}
1107
1108
sewardjed69fdb2006-02-03 16:12:27 +00001109/* 3-arg version of the above. */
1110static
1111IRAtom* mkLazy3 ( MCEnv* mce, IRType finalVty,
1112 IRAtom* va1, IRAtom* va2, IRAtom* va3 )
1113{
1114 IRAtom* at;
1115 IRType t1 = typeOfIRExpr(mce->bb->tyenv, va1);
1116 IRType t2 = typeOfIRExpr(mce->bb->tyenv, va2);
1117 IRType t3 = typeOfIRExpr(mce->bb->tyenv, va3);
1118 tl_assert(isShadowAtom(mce,va1));
1119 tl_assert(isShadowAtom(mce,va2));
1120 tl_assert(isShadowAtom(mce,va3));
1121
1122 /* The general case is inefficient because PCast is an expensive
1123 operation. Here are some special cases which use PCast only
1124 twice rather than three times. */
1125
1126 /* I32 x I64 x I64 -> I64 */
1127 /* Standard FP idiom: rm x FParg1 x FParg2 -> FPresult */
1128 if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64
1129 && finalVty == Ity_I64) {
1130 if (0) VG_(printf)("mkLazy3: I32 x I64 x I64 -> I64\n");
1131 /* Widen 1st arg to I64. Since 1st arg is typically a rounding
1132 mode indication which is fully defined, this should get
1133 folded out later. */
1134 at = mkPCastTo(mce, Ity_I64, va1);
1135 /* Now fold in 2nd and 3rd args. */
1136 at = mkUifU(mce, Ity_I64, at, va2);
1137 at = mkUifU(mce, Ity_I64, at, va3);
1138 /* and PCast once again. */
1139 at = mkPCastTo(mce, Ity_I64, at);
1140 return at;
1141 }
1142
1143 if (0) {
1144 VG_(printf)("mkLazy3 ");
1145 ppIRType(t1);
1146 VG_(printf)("_");
1147 ppIRType(t2);
1148 VG_(printf)("_");
1149 ppIRType(t3);
1150 VG_(printf)("_");
1151 ppIRType(finalVty);
1152 VG_(printf)("\n");
1153 }
1154
1155 /* General case: force everything via 32-bit intermediaries. */
1156 at = mkPCastTo(mce, Ity_I32, va1);
1157 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1158 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va3));
1159 at = mkPCastTo(mce, finalVty, at);
1160 return at;
1161}
1162
1163
sewardj95448072004-11-22 20:19:51 +00001164/* Do the lazy propagation game from a null-terminated vector of
1165 atoms. This is presumably the arguments to a helper call, so the
1166 IRCallee info is also supplied in order that we can know which
1167 arguments should be ignored (via the .mcx_mask field).
1168*/
1169static
1170IRAtom* mkLazyN ( MCEnv* mce,
1171 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1172{
1173 Int i;
1174 IRAtom* here;
1175 IRAtom* curr = definedOfType(Ity_I32);
1176 for (i = 0; exprvec[i]; i++) {
1177 tl_assert(i < 32);
1178 tl_assert(isOriginalAtom(mce, exprvec[i]));
1179 /* Only take notice of this arg if the callee's mc-exclusion
1180 mask does not say it is to be excluded. */
1181 if (cee->mcx_mask & (1<<i)) {
1182 /* the arg is to be excluded from definedness checking. Do
1183 nothing. */
1184 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1185 } else {
1186 /* calculate the arg's definedness, and pessimistically merge
1187 it in. */
1188 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1189 curr = mkUifU32(mce, here, curr);
1190 }
1191 }
1192 return mkPCastTo(mce, finalVtype, curr );
1193}
1194
1195
1196/*------------------------------------------------------------*/
1197/*--- Generating expensive sequences for exact carry-chain ---*/
1198/*--- propagation in add/sub and related operations. ---*/
1199/*------------------------------------------------------------*/
1200
1201static
sewardjd5204dc2004-12-31 01:16:11 +00001202IRAtom* expensiveAddSub ( MCEnv* mce,
1203 Bool add,
1204 IRType ty,
1205 IRAtom* qaa, IRAtom* qbb,
1206 IRAtom* aa, IRAtom* bb )
sewardj95448072004-11-22 20:19:51 +00001207{
sewardj7cf97ee2004-11-28 14:25:01 +00001208 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardjd5204dc2004-12-31 01:16:11 +00001209 IROp opAND, opOR, opXOR, opNOT, opADD, opSUB;
sewardj7cf97ee2004-11-28 14:25:01 +00001210
sewardj95448072004-11-22 20:19:51 +00001211 tl_assert(isShadowAtom(mce,qaa));
1212 tl_assert(isShadowAtom(mce,qbb));
1213 tl_assert(isOriginalAtom(mce,aa));
1214 tl_assert(isOriginalAtom(mce,bb));
1215 tl_assert(sameKindedAtoms(qaa,aa));
1216 tl_assert(sameKindedAtoms(qbb,bb));
1217
sewardjd5204dc2004-12-31 01:16:11 +00001218 switch (ty) {
1219 case Ity_I32:
1220 opAND = Iop_And32;
1221 opOR = Iop_Or32;
1222 opXOR = Iop_Xor32;
1223 opNOT = Iop_Not32;
1224 opADD = Iop_Add32;
1225 opSUB = Iop_Sub32;
1226 break;
tomd9774d72005-06-27 08:11:01 +00001227 case Ity_I64:
1228 opAND = Iop_And64;
1229 opOR = Iop_Or64;
1230 opXOR = Iop_Xor64;
1231 opNOT = Iop_Not64;
1232 opADD = Iop_Add64;
1233 opSUB = Iop_Sub64;
1234 break;
sewardjd5204dc2004-12-31 01:16:11 +00001235 default:
1236 VG_(tool_panic)("expensiveAddSub");
1237 }
sewardj95448072004-11-22 20:19:51 +00001238
1239 // a_min = aa & ~qaa
1240 a_min = assignNew(mce,ty,
1241 binop(opAND, aa,
1242 assignNew(mce,ty, unop(opNOT, qaa))));
1243
1244 // b_min = bb & ~qbb
1245 b_min = assignNew(mce,ty,
1246 binop(opAND, bb,
1247 assignNew(mce,ty, unop(opNOT, qbb))));
1248
1249 // a_max = aa | qaa
1250 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1251
1252 // b_max = bb | qbb
1253 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1254
sewardjd5204dc2004-12-31 01:16:11 +00001255 if (add) {
1256 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1257 return
1258 assignNew(mce,ty,
1259 binop( opOR,
1260 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1261 assignNew(mce,ty,
1262 binop( opXOR,
1263 assignNew(mce,ty, binop(opADD, a_min, b_min)),
1264 assignNew(mce,ty, binop(opADD, a_max, b_max))
1265 )
sewardj95448072004-11-22 20:19:51 +00001266 )
sewardjd5204dc2004-12-31 01:16:11 +00001267 )
1268 );
1269 } else {
1270 // result = (qaa | qbb) | ((a_min - b_max) ^ (a_max + b_min))
1271 return
1272 assignNew(mce,ty,
1273 binop( opOR,
1274 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1275 assignNew(mce,ty,
1276 binop( opXOR,
1277 assignNew(mce,ty, binop(opSUB, a_min, b_max)),
1278 assignNew(mce,ty, binop(opSUB, a_max, b_min))
1279 )
1280 )
1281 )
1282 );
1283 }
1284
sewardj95448072004-11-22 20:19:51 +00001285}
1286
1287
1288/*------------------------------------------------------------*/
sewardjaaddbc22005-10-07 09:49:53 +00001289/*--- Scalar shifts. ---*/
1290/*------------------------------------------------------------*/
1291
1292/* Produce an interpretation for (aa << bb) (or >>s, >>u). The basic
1293 idea is to shift the definedness bits by the original shift amount.
1294 This introduces 0s ("defined") in new positions for left shifts and
1295 unsigned right shifts, and copies the top definedness bit for
1296 signed right shifts. So, conveniently, applying the original shift
1297 operator to the definedness bits for the left arg is exactly the
1298 right thing to do:
1299
1300 (qaa << bb)
1301
1302 However if the shift amount is undefined then the whole result
1303 is undefined. Hence need:
1304
1305 (qaa << bb) `UifU` PCast(qbb)
1306
1307 If the shift amount bb is a literal than qbb will say 'all defined'
1308 and the UifU and PCast will get folded out by post-instrumentation
1309 optimisation.
1310*/
1311static IRAtom* scalarShift ( MCEnv* mce,
1312 IRType ty,
1313 IROp original_op,
1314 IRAtom* qaa, IRAtom* qbb,
1315 IRAtom* aa, IRAtom* bb )
1316{
1317 tl_assert(isShadowAtom(mce,qaa));
1318 tl_assert(isShadowAtom(mce,qbb));
1319 tl_assert(isOriginalAtom(mce,aa));
1320 tl_assert(isOriginalAtom(mce,bb));
1321 tl_assert(sameKindedAtoms(qaa,aa));
1322 tl_assert(sameKindedAtoms(qbb,bb));
1323 return
1324 assignNew(
1325 mce, ty,
1326 mkUifU( mce, ty,
1327 assignNew(mce, ty, binop(original_op, qaa, bb)),
1328 mkPCastTo(mce, ty, qbb)
1329 )
1330 );
1331}
1332
1333
1334/*------------------------------------------------------------*/
1335/*--- Helpers for dealing with vector primops. ---*/
sewardj3245c912004-12-10 14:58:26 +00001336/*------------------------------------------------------------*/
1337
sewardja1d93302004-12-12 16:45:06 +00001338/* Vector pessimisation -- pessimise within each lane individually. */
1339
1340static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1341{
1342 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1343}
1344
1345static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1346{
1347 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1348}
1349
1350static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1351{
1352 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1353}
1354
1355static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1356{
1357 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1358}
1359
sewardjacd2e912005-01-13 19:17:06 +00001360static IRAtom* mkPCast32x2 ( MCEnv* mce, IRAtom* at )
1361{
1362 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ32x2, at));
1363}
1364
1365static IRAtom* mkPCast16x4 ( MCEnv* mce, IRAtom* at )
1366{
1367 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ16x4, at));
1368}
1369
1370static IRAtom* mkPCast8x8 ( MCEnv* mce, IRAtom* at )
1371{
1372 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ8x8, at));
1373}
1374
sewardja1d93302004-12-12 16:45:06 +00001375
sewardj3245c912004-12-10 14:58:26 +00001376/* Here's a simple scheme capable of handling ops derived from SSE1
1377 code and while only generating ops that can be efficiently
1378 implemented in SSE1. */
1379
1380/* All-lanes versions are straightforward:
1381
sewardj20d38f22005-02-07 23:50:18 +00001382 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj3245c912004-12-10 14:58:26 +00001383
1384 unary32Fx4(x,y) ==> PCast32x4(x#)
1385
1386 Lowest-lane-only versions are more complex:
1387
sewardj20d38f22005-02-07 23:50:18 +00001388 binary32F0x4(x,y) ==> SetV128lo32(
sewardj3245c912004-12-10 14:58:26 +00001389 x#,
sewardj20d38f22005-02-07 23:50:18 +00001390 PCast32(V128to32(UifUV128(x#,y#)))
sewardj3245c912004-12-10 14:58:26 +00001391 )
1392
1393 This is perhaps not so obvious. In particular, it's faster to
sewardj20d38f22005-02-07 23:50:18 +00001394 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj3245c912004-12-10 14:58:26 +00001395 obvious scheme of taking the bottom 32 bits of each operand
1396 and doing a 32-bit UifU. Basically since UifU is fast and
1397 chopping lanes off vector values is slow.
1398
1399 Finally:
1400
sewardj20d38f22005-02-07 23:50:18 +00001401 unary32F0x4(x) ==> SetV128lo32(
sewardj3245c912004-12-10 14:58:26 +00001402 x#,
sewardj20d38f22005-02-07 23:50:18 +00001403 PCast32(V128to32(x#))
sewardj3245c912004-12-10 14:58:26 +00001404 )
1405
1406 Where:
1407
1408 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1409 PCast32x4(v#) = CmpNEZ32x4(v#)
1410*/
1411
1412static
1413IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1414{
1415 IRAtom* at;
1416 tl_assert(isShadowAtom(mce, vatomX));
1417 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001418 at = mkUifUV128(mce, vatomX, vatomY);
sewardja1d93302004-12-12 16:45:06 +00001419 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
sewardj3245c912004-12-10 14:58:26 +00001420 return at;
1421}
1422
1423static
1424IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1425{
1426 IRAtom* at;
1427 tl_assert(isShadowAtom(mce, vatomX));
sewardja1d93302004-12-12 16:45:06 +00001428 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
sewardj3245c912004-12-10 14:58:26 +00001429 return at;
1430}
1431
1432static
1433IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1434{
1435 IRAtom* at;
1436 tl_assert(isShadowAtom(mce, vatomX));
1437 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001438 at = mkUifUV128(mce, vatomX, vatomY);
1439 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj3245c912004-12-10 14:58:26 +00001440 at = mkPCastTo(mce, Ity_I32, at);
sewardj20d38f22005-02-07 23:50:18 +00001441 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj3245c912004-12-10 14:58:26 +00001442 return at;
1443}
1444
1445static
1446IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1447{
1448 IRAtom* at;
1449 tl_assert(isShadowAtom(mce, vatomX));
sewardj20d38f22005-02-07 23:50:18 +00001450 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj3245c912004-12-10 14:58:26 +00001451 at = mkPCastTo(mce, Ity_I32, at);
sewardj20d38f22005-02-07 23:50:18 +00001452 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj3245c912004-12-10 14:58:26 +00001453 return at;
1454}
1455
sewardj0b070592004-12-10 21:44:22 +00001456/* --- ... and ... 64Fx2 versions of the same ... --- */
1457
1458static
1459IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1460{
1461 IRAtom* at;
1462 tl_assert(isShadowAtom(mce, vatomX));
1463 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001464 at = mkUifUV128(mce, vatomX, vatomY);
sewardja1d93302004-12-12 16:45:06 +00001465 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
sewardj0b070592004-12-10 21:44:22 +00001466 return at;
1467}
1468
1469static
1470IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1471{
1472 IRAtom* at;
1473 tl_assert(isShadowAtom(mce, vatomX));
sewardja1d93302004-12-12 16:45:06 +00001474 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
sewardj0b070592004-12-10 21:44:22 +00001475 return at;
1476}
1477
1478static
1479IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1480{
1481 IRAtom* at;
1482 tl_assert(isShadowAtom(mce, vatomX));
1483 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001484 at = mkUifUV128(mce, vatomX, vatomY);
1485 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj0b070592004-12-10 21:44:22 +00001486 at = mkPCastTo(mce, Ity_I64, at);
sewardj20d38f22005-02-07 23:50:18 +00001487 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj0b070592004-12-10 21:44:22 +00001488 return at;
1489}
1490
1491static
1492IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1493{
1494 IRAtom* at;
1495 tl_assert(isShadowAtom(mce, vatomX));
sewardj20d38f22005-02-07 23:50:18 +00001496 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj0b070592004-12-10 21:44:22 +00001497 at = mkPCastTo(mce, Ity_I64, at);
sewardj20d38f22005-02-07 23:50:18 +00001498 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj0b070592004-12-10 21:44:22 +00001499 return at;
1500}
1501
sewardja1d93302004-12-12 16:45:06 +00001502/* --- --- Vector saturated narrowing --- --- */
1503
1504/* This is quite subtle. What to do is simple:
1505
1506 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1507
1508 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1509
1510 Why this is right is not so simple. Consider a lane in the args,
1511 vatom1 or 2, doesn't matter.
1512
1513 After the PCast, that lane is all 0s (defined) or all
1514 1s(undefined).
1515
1516 Both signed and unsigned saturating narrowing of all 0s produces
1517 all 0s, which is what we want.
1518
1519 The all-1s case is more complex. Unsigned narrowing interprets an
1520 all-1s input as the largest unsigned integer, and so produces all
1521 1s as a result since that is the largest unsigned value at the
1522 smaller width.
1523
1524 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1525 to -1, so we still wind up with all 1s at the smaller width.
1526
1527 So: In short, pessimise the args, then apply the original narrowing
1528 op.
1529*/
1530static
sewardj20d38f22005-02-07 23:50:18 +00001531IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardja1d93302004-12-12 16:45:06 +00001532 IRAtom* vatom1, IRAtom* vatom2)
1533{
1534 IRAtom *at1, *at2, *at3;
1535 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1536 switch (narrow_op) {
1537 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
sewardj43d60752005-11-10 18:13:01 +00001538 case Iop_QNarrow32Ux4: pcast = mkPCast32x4; break;
sewardja1d93302004-12-12 16:45:06 +00001539 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1540 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardj20d38f22005-02-07 23:50:18 +00001541 default: VG_(tool_panic)("vectorNarrowV128");
sewardja1d93302004-12-12 16:45:06 +00001542 }
1543 tl_assert(isShadowAtom(mce,vatom1));
1544 tl_assert(isShadowAtom(mce,vatom2));
1545 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1546 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1547 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1548 return at3;
1549}
1550
sewardjacd2e912005-01-13 19:17:06 +00001551static
1552IRAtom* vectorNarrow64 ( MCEnv* mce, IROp narrow_op,
1553 IRAtom* vatom1, IRAtom* vatom2)
1554{
1555 IRAtom *at1, *at2, *at3;
1556 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1557 switch (narrow_op) {
1558 case Iop_QNarrow32Sx2: pcast = mkPCast32x2; break;
1559 case Iop_QNarrow16Sx4: pcast = mkPCast16x4; break;
1560 case Iop_QNarrow16Ux4: pcast = mkPCast16x4; break;
1561 default: VG_(tool_panic)("vectorNarrow64");
1562 }
1563 tl_assert(isShadowAtom(mce,vatom1));
1564 tl_assert(isShadowAtom(mce,vatom2));
1565 at1 = assignNew(mce, Ity_I64, pcast(mce, vatom1));
1566 at2 = assignNew(mce, Ity_I64, pcast(mce, vatom2));
1567 at3 = assignNew(mce, Ity_I64, binop(narrow_op, at1, at2));
1568 return at3;
1569}
1570
sewardja1d93302004-12-12 16:45:06 +00001571
1572/* --- --- Vector integer arithmetic --- --- */
1573
1574/* Simple ... UifU the args and per-lane pessimise the results. */
sewardjacd2e912005-01-13 19:17:06 +00001575
sewardj20d38f22005-02-07 23:50:18 +00001576/* --- V128-bit versions --- */
sewardjacd2e912005-01-13 19:17:06 +00001577
sewardja1d93302004-12-12 16:45:06 +00001578static
1579IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1580{
1581 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001582 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001583 at = mkPCast8x16(mce, at);
1584 return at;
1585}
1586
1587static
1588IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1589{
1590 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001591 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001592 at = mkPCast16x8(mce, at);
1593 return at;
1594}
1595
1596static
1597IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1598{
1599 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001600 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001601 at = mkPCast32x4(mce, at);
1602 return at;
1603}
1604
1605static
1606IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1607{
1608 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001609 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001610 at = mkPCast64x2(mce, at);
1611 return at;
1612}
sewardj3245c912004-12-10 14:58:26 +00001613
sewardjacd2e912005-01-13 19:17:06 +00001614/* --- 64-bit versions --- */
1615
1616static
1617IRAtom* binary8Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1618{
1619 IRAtom* at;
1620 at = mkUifU64(mce, vatom1, vatom2);
1621 at = mkPCast8x8(mce, at);
1622 return at;
1623}
1624
1625static
1626IRAtom* binary16Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1627{
1628 IRAtom* at;
1629 at = mkUifU64(mce, vatom1, vatom2);
1630 at = mkPCast16x4(mce, at);
1631 return at;
1632}
1633
1634static
1635IRAtom* binary32Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1636{
1637 IRAtom* at;
1638 at = mkUifU64(mce, vatom1, vatom2);
1639 at = mkPCast32x2(mce, at);
1640 return at;
1641}
1642
sewardj3245c912004-12-10 14:58:26 +00001643
1644/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00001645/*--- Generate shadow values from all kinds of IRExprs. ---*/
1646/*------------------------------------------------------------*/
1647
1648static
sewardjed69fdb2006-02-03 16:12:27 +00001649IRAtom* expr2vbits_Triop ( MCEnv* mce,
1650 IROp op,
1651 IRAtom* atom1, IRAtom* atom2, IRAtom* atom3 )
1652{
1653 IRType and_or_ty;
1654 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1655 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1656 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1657
1658 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1659 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1660 IRAtom* vatom3 = expr2vbits( mce, atom3 );
1661
1662 tl_assert(isOriginalAtom(mce,atom1));
1663 tl_assert(isOriginalAtom(mce,atom2));
1664 tl_assert(isOriginalAtom(mce,atom3));
1665 tl_assert(isShadowAtom(mce,vatom1));
1666 tl_assert(isShadowAtom(mce,vatom2));
1667 tl_assert(isShadowAtom(mce,vatom3));
1668 tl_assert(sameKindedAtoms(atom1,vatom1));
1669 tl_assert(sameKindedAtoms(atom2,vatom2));
1670 tl_assert(sameKindedAtoms(atom3,vatom3));
1671 switch (op) {
1672 case Iop_AddF64:
1673 case Iop_AddF64r32:
1674 case Iop_SubF64:
1675 case Iop_SubF64r32:
1676 case Iop_MulF64:
1677 case Iop_MulF64r32:
1678 case Iop_DivF64:
1679 case Iop_DivF64r32:
1680 return mkLazy3(mce, Ity_I64, vatom1, vatom2, vatom3);
1681 default:
1682 ppIROp(op);
1683 VG_(tool_panic)("memcheck:expr2vbits_Triop");
1684 }
1685}
1686
1687
1688static
sewardj95448072004-11-22 20:19:51 +00001689IRAtom* expr2vbits_Binop ( MCEnv* mce,
1690 IROp op,
1691 IRAtom* atom1, IRAtom* atom2 )
1692{
1693 IRType and_or_ty;
1694 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1695 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1696 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1697
1698 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1699 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1700
1701 tl_assert(isOriginalAtom(mce,atom1));
1702 tl_assert(isOriginalAtom(mce,atom2));
1703 tl_assert(isShadowAtom(mce,vatom1));
1704 tl_assert(isShadowAtom(mce,vatom2));
1705 tl_assert(sameKindedAtoms(atom1,vatom1));
1706 tl_assert(sameKindedAtoms(atom2,vatom2));
1707 switch (op) {
1708
sewardjacd2e912005-01-13 19:17:06 +00001709 /* 64-bit SIMD */
1710
1711 case Iop_ShrN16x4:
1712 case Iop_ShrN32x2:
1713 case Iop_SarN16x4:
1714 case Iop_SarN32x2:
1715 case Iop_ShlN16x4:
1716 case Iop_ShlN32x2:
1717 /* Same scheme as with all other shifts. */
1718 complainIfUndefined(mce, atom2);
1719 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1720
1721 case Iop_QNarrow32Sx2:
1722 case Iop_QNarrow16Sx4:
1723 case Iop_QNarrow16Ux4:
1724 return vectorNarrow64(mce, op, vatom1, vatom2);
1725
1726 case Iop_Min8Ux8:
1727 case Iop_Max8Ux8:
1728 case Iop_Avg8Ux8:
1729 case Iop_QSub8Sx8:
1730 case Iop_QSub8Ux8:
1731 case Iop_Sub8x8:
1732 case Iop_CmpGT8Sx8:
1733 case Iop_CmpEQ8x8:
1734 case Iop_QAdd8Sx8:
1735 case Iop_QAdd8Ux8:
1736 case Iop_Add8x8:
1737 return binary8Ix8(mce, vatom1, vatom2);
1738
1739 case Iop_Min16Sx4:
1740 case Iop_Max16Sx4:
1741 case Iop_Avg16Ux4:
1742 case Iop_QSub16Ux4:
1743 case Iop_QSub16Sx4:
1744 case Iop_Sub16x4:
1745 case Iop_Mul16x4:
1746 case Iop_MulHi16Sx4:
1747 case Iop_MulHi16Ux4:
1748 case Iop_CmpGT16Sx4:
1749 case Iop_CmpEQ16x4:
1750 case Iop_QAdd16Sx4:
1751 case Iop_QAdd16Ux4:
1752 case Iop_Add16x4:
1753 return binary16Ix4(mce, vatom1, vatom2);
1754
1755 case Iop_Sub32x2:
1756 case Iop_CmpGT32Sx2:
1757 case Iop_CmpEQ32x2:
1758 case Iop_Add32x2:
1759 return binary32Ix2(mce, vatom1, vatom2);
1760
1761 /* 64-bit data-steering */
1762 case Iop_InterleaveLO32x2:
1763 case Iop_InterleaveLO16x4:
1764 case Iop_InterleaveLO8x8:
1765 case Iop_InterleaveHI32x2:
1766 case Iop_InterleaveHI16x4:
1767 case Iop_InterleaveHI8x8:
1768 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
1769
sewardj20d38f22005-02-07 23:50:18 +00001770 /* V128-bit SIMD */
sewardj0b070592004-12-10 21:44:22 +00001771
sewardja1d93302004-12-12 16:45:06 +00001772 case Iop_ShrN16x8:
1773 case Iop_ShrN32x4:
1774 case Iop_ShrN64x2:
1775 case Iop_SarN16x8:
1776 case Iop_SarN32x4:
1777 case Iop_ShlN16x8:
1778 case Iop_ShlN32x4:
1779 case Iop_ShlN64x2:
sewardj620eb5b2005-10-22 12:50:43 +00001780 case Iop_ShlN8x16:
1781 case Iop_SarN8x16:
1782 /* Same scheme as with all other shifts. Note: 22 Oct 05:
1783 this is wrong now, scalar shifts are done properly lazily.
1784 Vector shifts should be fixed too. */
sewardja1d93302004-12-12 16:45:06 +00001785 complainIfUndefined(mce, atom2);
1786 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1787
sewardjcbf8be72005-11-10 18:34:41 +00001788 /* V x V shifts/rotates are done using the standard lazy scheme. */
sewardj43d60752005-11-10 18:13:01 +00001789 case Iop_Shl8x16:
1790 case Iop_Shr8x16:
1791 case Iop_Sar8x16:
sewardjcbf8be72005-11-10 18:34:41 +00001792 case Iop_Rol8x16:
sewardj43d60752005-11-10 18:13:01 +00001793 return mkUifUV128(mce,
1794 assignNew(mce, Ity_V128, binop(op, vatom1, atom2)),
1795 mkPCast8x16(mce,vatom2)
1796 );
1797
1798 case Iop_Shl16x8:
1799 case Iop_Shr16x8:
1800 case Iop_Sar16x8:
sewardjcbf8be72005-11-10 18:34:41 +00001801 case Iop_Rol16x8:
sewardj43d60752005-11-10 18:13:01 +00001802 return mkUifUV128(mce,
1803 assignNew(mce, Ity_V128, binop(op, vatom1, atom2)),
1804 mkPCast16x8(mce,vatom2)
1805 );
1806
1807 case Iop_Shl32x4:
1808 case Iop_Shr32x4:
1809 case Iop_Sar32x4:
sewardjcbf8be72005-11-10 18:34:41 +00001810 case Iop_Rol32x4:
sewardj43d60752005-11-10 18:13:01 +00001811 return mkUifUV128(mce,
1812 assignNew(mce, Ity_V128, binop(op, vatom1, atom2)),
1813 mkPCast32x4(mce,vatom2)
1814 );
1815
sewardja1d93302004-12-12 16:45:06 +00001816 case Iop_QSub8Ux16:
1817 case Iop_QSub8Sx16:
1818 case Iop_Sub8x16:
1819 case Iop_Min8Ux16:
sewardj43d60752005-11-10 18:13:01 +00001820 case Iop_Min8Sx16:
sewardja1d93302004-12-12 16:45:06 +00001821 case Iop_Max8Ux16:
sewardj43d60752005-11-10 18:13:01 +00001822 case Iop_Max8Sx16:
sewardja1d93302004-12-12 16:45:06 +00001823 case Iop_CmpGT8Sx16:
sewardj43d60752005-11-10 18:13:01 +00001824 case Iop_CmpGT8Ux16:
sewardja1d93302004-12-12 16:45:06 +00001825 case Iop_CmpEQ8x16:
1826 case Iop_Avg8Ux16:
sewardj43d60752005-11-10 18:13:01 +00001827 case Iop_Avg8Sx16:
sewardja1d93302004-12-12 16:45:06 +00001828 case Iop_QAdd8Ux16:
1829 case Iop_QAdd8Sx16:
1830 case Iop_Add8x16:
1831 return binary8Ix16(mce, vatom1, vatom2);
1832
1833 case Iop_QSub16Ux8:
1834 case Iop_QSub16Sx8:
1835 case Iop_Sub16x8:
1836 case Iop_Mul16x8:
1837 case Iop_MulHi16Sx8:
1838 case Iop_MulHi16Ux8:
1839 case Iop_Min16Sx8:
sewardj43d60752005-11-10 18:13:01 +00001840 case Iop_Min16Ux8:
sewardja1d93302004-12-12 16:45:06 +00001841 case Iop_Max16Sx8:
sewardj43d60752005-11-10 18:13:01 +00001842 case Iop_Max16Ux8:
sewardja1d93302004-12-12 16:45:06 +00001843 case Iop_CmpGT16Sx8:
sewardj43d60752005-11-10 18:13:01 +00001844 case Iop_CmpGT16Ux8:
sewardja1d93302004-12-12 16:45:06 +00001845 case Iop_CmpEQ16x8:
1846 case Iop_Avg16Ux8:
sewardj43d60752005-11-10 18:13:01 +00001847 case Iop_Avg16Sx8:
sewardja1d93302004-12-12 16:45:06 +00001848 case Iop_QAdd16Ux8:
1849 case Iop_QAdd16Sx8:
1850 case Iop_Add16x8:
1851 return binary16Ix8(mce, vatom1, vatom2);
1852
1853 case Iop_Sub32x4:
1854 case Iop_CmpGT32Sx4:
sewardj43d60752005-11-10 18:13:01 +00001855 case Iop_CmpGT32Ux4:
sewardja1d93302004-12-12 16:45:06 +00001856 case Iop_CmpEQ32x4:
sewardj43d60752005-11-10 18:13:01 +00001857 case Iop_QAdd32Sx4:
1858 case Iop_QAdd32Ux4:
1859 case Iop_QSub32Sx4:
1860 case Iop_QSub32Ux4:
1861 case Iop_Avg32Ux4:
1862 case Iop_Avg32Sx4:
sewardja1d93302004-12-12 16:45:06 +00001863 case Iop_Add32x4:
sewardj43d60752005-11-10 18:13:01 +00001864 case Iop_Max32Ux4:
1865 case Iop_Max32Sx4:
1866 case Iop_Min32Ux4:
1867 case Iop_Min32Sx4:
sewardja1d93302004-12-12 16:45:06 +00001868 return binary32Ix4(mce, vatom1, vatom2);
1869
1870 case Iop_Sub64x2:
1871 case Iop_Add64x2:
1872 return binary64Ix2(mce, vatom1, vatom2);
1873
1874 case Iop_QNarrow32Sx4:
sewardj43d60752005-11-10 18:13:01 +00001875 case Iop_QNarrow32Ux4:
sewardja1d93302004-12-12 16:45:06 +00001876 case Iop_QNarrow16Sx8:
1877 case Iop_QNarrow16Ux8:
sewardj20d38f22005-02-07 23:50:18 +00001878 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001879
sewardj0b070592004-12-10 21:44:22 +00001880 case Iop_Sub64Fx2:
1881 case Iop_Mul64Fx2:
1882 case Iop_Min64Fx2:
1883 case Iop_Max64Fx2:
1884 case Iop_Div64Fx2:
1885 case Iop_CmpLT64Fx2:
1886 case Iop_CmpLE64Fx2:
1887 case Iop_CmpEQ64Fx2:
sewardj545663e2005-11-05 01:55:04 +00001888 case Iop_CmpUN64Fx2:
sewardj0b070592004-12-10 21:44:22 +00001889 case Iop_Add64Fx2:
1890 return binary64Fx2(mce, vatom1, vatom2);
1891
1892 case Iop_Sub64F0x2:
1893 case Iop_Mul64F0x2:
1894 case Iop_Min64F0x2:
1895 case Iop_Max64F0x2:
1896 case Iop_Div64F0x2:
1897 case Iop_CmpLT64F0x2:
1898 case Iop_CmpLE64F0x2:
1899 case Iop_CmpEQ64F0x2:
sewardj545663e2005-11-05 01:55:04 +00001900 case Iop_CmpUN64F0x2:
sewardj0b070592004-12-10 21:44:22 +00001901 case Iop_Add64F0x2:
1902 return binary64F0x2(mce, vatom1, vatom2);
1903
sewardj170ee212004-12-10 18:57:51 +00001904 case Iop_Sub32Fx4:
1905 case Iop_Mul32Fx4:
1906 case Iop_Min32Fx4:
1907 case Iop_Max32Fx4:
1908 case Iop_Div32Fx4:
1909 case Iop_CmpLT32Fx4:
1910 case Iop_CmpLE32Fx4:
1911 case Iop_CmpEQ32Fx4:
sewardj545663e2005-11-05 01:55:04 +00001912 case Iop_CmpUN32Fx4:
cerione78ba2a2005-11-14 03:00:35 +00001913 case Iop_CmpGT32Fx4:
1914 case Iop_CmpGE32Fx4:
sewardj3245c912004-12-10 14:58:26 +00001915 case Iop_Add32Fx4:
1916 return binary32Fx4(mce, vatom1, vatom2);
1917
sewardj170ee212004-12-10 18:57:51 +00001918 case Iop_Sub32F0x4:
1919 case Iop_Mul32F0x4:
1920 case Iop_Min32F0x4:
1921 case Iop_Max32F0x4:
1922 case Iop_Div32F0x4:
1923 case Iop_CmpLT32F0x4:
1924 case Iop_CmpLE32F0x4:
1925 case Iop_CmpEQ32F0x4:
sewardj545663e2005-11-05 01:55:04 +00001926 case Iop_CmpUN32F0x4:
sewardj170ee212004-12-10 18:57:51 +00001927 case Iop_Add32F0x4:
1928 return binary32F0x4(mce, vatom1, vatom2);
1929
sewardj20d38f22005-02-07 23:50:18 +00001930 /* V128-bit data-steering */
1931 case Iop_SetV128lo32:
1932 case Iop_SetV128lo64:
1933 case Iop_64HLtoV128:
sewardja1d93302004-12-12 16:45:06 +00001934 case Iop_InterleaveLO64x2:
1935 case Iop_InterleaveLO32x4:
1936 case Iop_InterleaveLO16x8:
1937 case Iop_InterleaveLO8x16:
1938 case Iop_InterleaveHI64x2:
1939 case Iop_InterleaveHI32x4:
1940 case Iop_InterleaveHI16x8:
1941 case Iop_InterleaveHI8x16:
sewardj170ee212004-12-10 18:57:51 +00001942 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
sewardj620eb5b2005-10-22 12:50:43 +00001943
1944 /* Perm8x16: rearrange values in left arg using steering values
1945 from right arg. So rearrange the vbits in the same way but
1946 pessimise wrt steering values. */
1947 case Iop_Perm8x16:
1948 return mkUifUV128(
1949 mce,
1950 assignNew(mce, Ity_V128, binop(op, vatom1, atom2)),
1951 mkPCast8x16(mce, vatom2)
1952 );
sewardj170ee212004-12-10 18:57:51 +00001953
sewardj43d60752005-11-10 18:13:01 +00001954 /* These two take the lower half of each 16-bit lane, sign/zero
1955 extend it to 32, and multiply together, producing a 32x4
1956 result (and implicitly ignoring half the operand bits). So
1957 treat it as a bunch of independent 16x8 operations, but then
1958 do 32-bit shifts left-right to copy the lower half results
1959 (which are all 0s or all 1s due to PCasting in binary16Ix8)
1960 into the upper half of each result lane. */
1961 case Iop_MullEven16Ux8:
1962 case Iop_MullEven16Sx8: {
1963 IRAtom* at;
1964 at = binary16Ix8(mce,vatom1,vatom2);
1965 at = assignNew(mce, Ity_V128, binop(Iop_ShlN32x4, at, mkU8(16)));
1966 at = assignNew(mce, Ity_V128, binop(Iop_SarN32x4, at, mkU8(16)));
1967 return at;
1968 }
1969
1970 /* Same deal as Iop_MullEven16{S,U}x8 */
1971 case Iop_MullEven8Ux16:
1972 case Iop_MullEven8Sx16: {
1973 IRAtom* at;
1974 at = binary8Ix16(mce,vatom1,vatom2);
1975 at = assignNew(mce, Ity_V128, binop(Iop_ShlN16x8, at, mkU8(8)));
1976 at = assignNew(mce, Ity_V128, binop(Iop_SarN16x8, at, mkU8(8)));
1977 return at;
1978 }
1979
1980 /* narrow 2xV128 into 1xV128, hi half from left arg, in a 2 x
1981 32x4 -> 16x8 laneage, discarding the upper half of each lane.
1982 Simply apply same op to the V bits, since this really no more
1983 than a data steering operation. */
sewardjcbf8be72005-11-10 18:34:41 +00001984 case Iop_Narrow32x4:
1985 case Iop_Narrow16x8:
sewardj43d60752005-11-10 18:13:01 +00001986 return assignNew(mce, Ity_V128,
1987 binop(op, vatom1, vatom2));
1988
1989 case Iop_ShrV128:
1990 case Iop_ShlV128:
1991 /* Same scheme as with all other shifts. Note: 10 Nov 05:
1992 this is wrong now, scalar shifts are done properly lazily.
1993 Vector shifts should be fixed too. */
1994 complainIfUndefined(mce, atom2);
1995 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1996
1997
sewardj69a13322005-04-23 01:14:51 +00001998 /* I128-bit data-steering */
1999 case Iop_64HLto128:
2000 return assignNew(mce, Ity_I128, binop(op, vatom1, vatom2));
2001
sewardj3245c912004-12-10 14:58:26 +00002002 /* Scalar floating point */
2003
sewardjed69fdb2006-02-03 16:12:27 +00002004 case Iop_RoundF64toInt:
2005 case Iop_RoundF64toF32:
sewardj95448072004-11-22 20:19:51 +00002006 case Iop_F64toI64:
sewardje9e16d32004-12-10 13:17:55 +00002007 case Iop_I64toF64:
2008 /* First arg is I32 (rounding mode), second is F64 or I64
2009 (data). */
sewardj95448072004-11-22 20:19:51 +00002010 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
2011
2012 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
2013 /* Takes two F64 args. */
2014 case Iop_F64toI32:
sewardje9e16d32004-12-10 13:17:55 +00002015 case Iop_F64toF32:
sewardj95448072004-11-22 20:19:51 +00002016 /* First arg is I32 (rounding mode), second is F64 (data). */
2017 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
2018
2019 case Iop_F64toI16:
2020 /* First arg is I32 (rounding mode), second is F64 (data). */
2021 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
2022
2023 case Iop_ScaleF64:
2024 case Iop_Yl2xF64:
2025 case Iop_Yl2xp1F64:
2026 case Iop_PRemF64:
sewardj96403eb2005-04-01 20:20:12 +00002027 case Iop_PRem1F64:
sewardj95448072004-11-22 20:19:51 +00002028 case Iop_AtanF64:
sewardj95448072004-11-22 20:19:51 +00002029 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
2030
2031 case Iop_CmpF64:
2032 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
2033
2034 /* non-FP after here */
2035
2036 case Iop_DivModU64to32:
2037 case Iop_DivModS64to32:
2038 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
2039
sewardj69a13322005-04-23 01:14:51 +00002040 case Iop_DivModU128to64:
2041 case Iop_DivModS128to64:
2042 return mkLazy2(mce, Ity_I128, vatom1, vatom2);
2043
sewardj95448072004-11-22 20:19:51 +00002044 case Iop_16HLto32:
sewardj170ee212004-12-10 18:57:51 +00002045 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardj95448072004-11-22 20:19:51 +00002046 case Iop_32HLto64:
sewardj170ee212004-12-10 18:57:51 +00002047 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardj95448072004-11-22 20:19:51 +00002048
sewardj6cf40ff2005-04-20 22:31:26 +00002049 case Iop_MullS64:
2050 case Iop_MullU64: {
2051 IRAtom* vLo64 = mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
2052 IRAtom* vHi64 = mkPCastTo(mce, Ity_I64, vLo64);
2053 return assignNew(mce, Ity_I128, binop(Iop_64HLto128, vHi64, vLo64));
2054 }
2055
sewardj95448072004-11-22 20:19:51 +00002056 case Iop_MullS32:
2057 case Iop_MullU32: {
2058 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
2059 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
2060 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
2061 }
2062
2063 case Iop_MullS16:
2064 case Iop_MullU16: {
2065 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
2066 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
2067 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
2068 }
2069
2070 case Iop_MullS8:
2071 case Iop_MullU8: {
2072 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
2073 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
2074 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
2075 }
2076
cerion9e591082005-06-23 15:28:34 +00002077 case Iop_DivS32:
2078 case Iop_DivU32:
2079 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
2080
sewardjb00944a2005-12-23 12:47:16 +00002081 case Iop_DivS64:
2082 case Iop_DivU64:
2083 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
2084
sewardj95448072004-11-22 20:19:51 +00002085 case Iop_Add32:
sewardjd5204dc2004-12-31 01:16:11 +00002086 if (mce->bogusLiterals)
2087 return expensiveAddSub(mce,True,Ity_I32,
2088 vatom1,vatom2, atom1,atom2);
2089 else
2090 goto cheap_AddSub32;
sewardj95448072004-11-22 20:19:51 +00002091 case Iop_Sub32:
sewardjd5204dc2004-12-31 01:16:11 +00002092 if (mce->bogusLiterals)
2093 return expensiveAddSub(mce,False,Ity_I32,
2094 vatom1,vatom2, atom1,atom2);
2095 else
2096 goto cheap_AddSub32;
2097
2098 cheap_AddSub32:
sewardj95448072004-11-22 20:19:51 +00002099 case Iop_Mul32:
sewardj992dff92005-10-07 11:08:55 +00002100 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
2101
sewardj463b3d92005-07-18 11:41:15 +00002102 case Iop_CmpORD32S:
2103 case Iop_CmpORD32U:
sewardj1bc82102005-12-23 00:16:24 +00002104 case Iop_CmpORD64S:
2105 case Iop_CmpORD64U:
2106 return doCmpORD(mce, op, vatom1,vatom2, atom1,atom2);
sewardj95448072004-11-22 20:19:51 +00002107
sewardj681be302005-01-15 20:43:58 +00002108 case Iop_Add64:
tomd9774d72005-06-27 08:11:01 +00002109 if (mce->bogusLiterals)
2110 return expensiveAddSub(mce,True,Ity_I64,
2111 vatom1,vatom2, atom1,atom2);
2112 else
2113 goto cheap_AddSub64;
sewardj681be302005-01-15 20:43:58 +00002114 case Iop_Sub64:
tomd9774d72005-06-27 08:11:01 +00002115 if (mce->bogusLiterals)
2116 return expensiveAddSub(mce,False,Ity_I64,
2117 vatom1,vatom2, atom1,atom2);
2118 else
2119 goto cheap_AddSub64;
2120
2121 cheap_AddSub64:
2122 case Iop_Mul64:
sewardj681be302005-01-15 20:43:58 +00002123 return mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
2124
sewardj95448072004-11-22 20:19:51 +00002125 case Iop_Mul16:
2126 case Iop_Add16:
2127 case Iop_Sub16:
2128 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
2129
2130 case Iop_Sub8:
2131 case Iop_Add8:
2132 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
2133
sewardj69a13322005-04-23 01:14:51 +00002134 case Iop_CmpEQ64:
sewardje6f8af42005-07-06 18:48:59 +00002135 case Iop_CmpNE64:
sewardj69a13322005-04-23 01:14:51 +00002136 if (mce->bogusLiterals)
2137 return expensiveCmpEQorNE(mce,Ity_I64, vatom1,vatom2, atom1,atom2 );
2138 else
2139 goto cheap_cmp64;
2140 cheap_cmp64:
tomcd986332005-04-26 07:44:48 +00002141 case Iop_CmpLE64S: case Iop_CmpLE64U:
2142 case Iop_CmpLT64U: case Iop_CmpLT64S:
sewardj69a13322005-04-23 01:14:51 +00002143 return mkPCastTo(mce, Ity_I1, mkUifU64(mce, vatom1,vatom2));
2144
sewardjd5204dc2004-12-31 01:16:11 +00002145 case Iop_CmpEQ32:
sewardje6f8af42005-07-06 18:48:59 +00002146 case Iop_CmpNE32:
sewardjd5204dc2004-12-31 01:16:11 +00002147 if (mce->bogusLiterals)
2148 return expensiveCmpEQorNE(mce,Ity_I32, vatom1,vatom2, atom1,atom2 );
2149 else
2150 goto cheap_cmp32;
sewardjd5204dc2004-12-31 01:16:11 +00002151 cheap_cmp32:
sewardj95448072004-11-22 20:19:51 +00002152 case Iop_CmpLE32S: case Iop_CmpLE32U:
2153 case Iop_CmpLT32U: case Iop_CmpLT32S:
sewardj95448072004-11-22 20:19:51 +00002154 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
2155
2156 case Iop_CmpEQ16: case Iop_CmpNE16:
2157 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
2158
2159 case Iop_CmpEQ8: case Iop_CmpNE8:
2160 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
2161
sewardjaaddbc22005-10-07 09:49:53 +00002162 case Iop_Shl64: case Iop_Shr64: case Iop_Sar64:
2163 return scalarShift( mce, Ity_I64, op, vatom1,vatom2, atom1,atom2 );
2164
sewardj95448072004-11-22 20:19:51 +00002165 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
sewardjaaddbc22005-10-07 09:49:53 +00002166 return scalarShift( mce, Ity_I32, op, vatom1,vatom2, atom1,atom2 );
sewardj95448072004-11-22 20:19:51 +00002167
sewardjdb67f5f2004-12-14 01:15:31 +00002168 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardjaaddbc22005-10-07 09:49:53 +00002169 return scalarShift( mce, Ity_I16, op, vatom1,vatom2, atom1,atom2 );
sewardj95448072004-11-22 20:19:51 +00002170
2171 case Iop_Shl8: case Iop_Shr8:
sewardjaaddbc22005-10-07 09:49:53 +00002172 return scalarShift( mce, Ity_I8, op, vatom1,vatom2, atom1,atom2 );
sewardj95448072004-11-22 20:19:51 +00002173
sewardj20d38f22005-02-07 23:50:18 +00002174 case Iop_AndV128:
2175 uifu = mkUifUV128; difd = mkDifDV128;
2176 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj7010f6e2004-12-10 13:35:22 +00002177 case Iop_And64:
2178 uifu = mkUifU64; difd = mkDifD64;
2179 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardj95448072004-11-22 20:19:51 +00002180 case Iop_And32:
2181 uifu = mkUifU32; difd = mkDifD32;
2182 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
2183 case Iop_And16:
2184 uifu = mkUifU16; difd = mkDifD16;
2185 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
2186 case Iop_And8:
2187 uifu = mkUifU8; difd = mkDifD8;
2188 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
2189
sewardj20d38f22005-02-07 23:50:18 +00002190 case Iop_OrV128:
2191 uifu = mkUifUV128; difd = mkDifDV128;
2192 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj7010f6e2004-12-10 13:35:22 +00002193 case Iop_Or64:
2194 uifu = mkUifU64; difd = mkDifD64;
2195 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardj95448072004-11-22 20:19:51 +00002196 case Iop_Or32:
2197 uifu = mkUifU32; difd = mkDifD32;
2198 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
2199 case Iop_Or16:
2200 uifu = mkUifU16; difd = mkDifD16;
2201 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
2202 case Iop_Or8:
2203 uifu = mkUifU8; difd = mkDifD8;
2204 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
2205
2206 do_And_Or:
2207 return
2208 assignNew(
2209 mce,
2210 and_or_ty,
2211 difd(mce, uifu(mce, vatom1, vatom2),
2212 difd(mce, improve(mce, atom1, vatom1),
2213 improve(mce, atom2, vatom2) ) ) );
2214
2215 case Iop_Xor8:
2216 return mkUifU8(mce, vatom1, vatom2);
2217 case Iop_Xor16:
2218 return mkUifU16(mce, vatom1, vatom2);
2219 case Iop_Xor32:
2220 return mkUifU32(mce, vatom1, vatom2);
sewardj7010f6e2004-12-10 13:35:22 +00002221 case Iop_Xor64:
2222 return mkUifU64(mce, vatom1, vatom2);
sewardj20d38f22005-02-07 23:50:18 +00002223 case Iop_XorV128:
2224 return mkUifUV128(mce, vatom1, vatom2);
njn25e49d8e72002-09-23 09:36:25 +00002225
2226 default:
sewardj95448072004-11-22 20:19:51 +00002227 ppIROp(op);
2228 VG_(tool_panic)("memcheck:expr2vbits_Binop");
njn25e49d8e72002-09-23 09:36:25 +00002229 }
njn25e49d8e72002-09-23 09:36:25 +00002230}
2231
njn25e49d8e72002-09-23 09:36:25 +00002232
sewardj95448072004-11-22 20:19:51 +00002233static
2234IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
2235{
2236 IRAtom* vatom = expr2vbits( mce, atom );
2237 tl_assert(isOriginalAtom(mce,atom));
2238 switch (op) {
2239
sewardj0b070592004-12-10 21:44:22 +00002240 case Iop_Sqrt64Fx2:
2241 return unary64Fx2(mce, vatom);
2242
2243 case Iop_Sqrt64F0x2:
2244 return unary64F0x2(mce, vatom);
2245
sewardj170ee212004-12-10 18:57:51 +00002246 case Iop_Sqrt32Fx4:
2247 case Iop_RSqrt32Fx4:
2248 case Iop_Recip32Fx4:
cerion176cb4c2005-11-16 17:21:49 +00002249 case Iop_I32UtoFx4:
2250 case Iop_I32StoFx4:
2251 case Iop_QFtoI32Ux4_RZ:
2252 case Iop_QFtoI32Sx4_RZ:
2253 case Iop_RoundF32x4_RM:
2254 case Iop_RoundF32x4_RP:
2255 case Iop_RoundF32x4_RN:
2256 case Iop_RoundF32x4_RZ:
sewardj170ee212004-12-10 18:57:51 +00002257 return unary32Fx4(mce, vatom);
2258
2259 case Iop_Sqrt32F0x4:
2260 case Iop_RSqrt32F0x4:
2261 case Iop_Recip32F0x4:
2262 return unary32F0x4(mce, vatom);
2263
sewardj20d38f22005-02-07 23:50:18 +00002264 case Iop_32UtoV128:
2265 case Iop_64UtoV128:
sewardj620eb5b2005-10-22 12:50:43 +00002266 case Iop_Dup8x16:
2267 case Iop_Dup16x8:
2268 case Iop_Dup32x4:
sewardj170ee212004-12-10 18:57:51 +00002269 return assignNew(mce, Ity_V128, unop(op, vatom));
2270
sewardj95448072004-11-22 20:19:51 +00002271 case Iop_F32toF64:
2272 case Iop_I32toF64:
sewardj95448072004-11-22 20:19:51 +00002273 case Iop_NegF64:
2274 case Iop_SinF64:
2275 case Iop_CosF64:
2276 case Iop_TanF64:
2277 case Iop_SqrtF64:
2278 case Iop_AbsF64:
2279 case Iop_2xm1F64:
sewardj4f3e0f22006-01-27 15:11:31 +00002280 case Iop_Est5FRSqrt:
sewardj39cc7352005-06-09 21:31:55 +00002281 case Iop_Clz64:
2282 case Iop_Ctz64:
sewardj95448072004-11-22 20:19:51 +00002283 return mkPCastTo(mce, Ity_I64, vatom);
2284
sewardj95448072004-11-22 20:19:51 +00002285 case Iop_Clz32:
2286 case Iop_Ctz32:
sewardjed69fdb2006-02-03 16:12:27 +00002287 case Iop_TruncF64asF32:
sewardj95448072004-11-22 20:19:51 +00002288 return mkPCastTo(mce, Ity_I32, vatom);
2289
sewardjd9dbc192005-04-27 11:40:27 +00002290 case Iop_1Uto64:
2291 case Iop_8Uto64:
2292 case Iop_8Sto64:
2293 case Iop_16Uto64:
2294 case Iop_16Sto64:
sewardj95448072004-11-22 20:19:51 +00002295 case Iop_32Sto64:
2296 case Iop_32Uto64:
sewardj20d38f22005-02-07 23:50:18 +00002297 case Iop_V128to64:
2298 case Iop_V128HIto64:
sewardj6cf40ff2005-04-20 22:31:26 +00002299 case Iop_128HIto64:
2300 case Iop_128to64:
sewardj95448072004-11-22 20:19:51 +00002301 return assignNew(mce, Ity_I64, unop(op, vatom));
2302
2303 case Iop_64to32:
2304 case Iop_64HIto32:
2305 case Iop_1Uto32:
sewardj463b3d92005-07-18 11:41:15 +00002306 case Iop_1Sto32:
sewardj95448072004-11-22 20:19:51 +00002307 case Iop_8Uto32:
2308 case Iop_16Uto32:
2309 case Iop_16Sto32:
2310 case Iop_8Sto32:
cerionfafaa0d2005-09-12 22:29:38 +00002311 case Iop_V128to32:
sewardj95448072004-11-22 20:19:51 +00002312 return assignNew(mce, Ity_I32, unop(op, vatom));
2313
2314 case Iop_8Sto16:
2315 case Iop_8Uto16:
2316 case Iop_32to16:
2317 case Iop_32HIto16:
sewardjd9dbc192005-04-27 11:40:27 +00002318 case Iop_64to16:
sewardj95448072004-11-22 20:19:51 +00002319 return assignNew(mce, Ity_I16, unop(op, vatom));
2320
2321 case Iop_1Uto8:
2322 case Iop_16to8:
2323 case Iop_32to8:
sewardjd9dbc192005-04-27 11:40:27 +00002324 case Iop_64to8:
sewardj95448072004-11-22 20:19:51 +00002325 return assignNew(mce, Ity_I8, unop(op, vatom));
2326
2327 case Iop_32to1:
2328 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
2329
sewardjd9dbc192005-04-27 11:40:27 +00002330 case Iop_64to1:
2331 return assignNew(mce, Ity_I1, unop(Iop_64to1, vatom));
2332
sewardj95448072004-11-22 20:19:51 +00002333 case Iop_ReinterpF64asI64:
2334 case Iop_ReinterpI64asF64:
sewardj0b070592004-12-10 21:44:22 +00002335 case Iop_ReinterpI32asF32:
sewardj20d38f22005-02-07 23:50:18 +00002336 case Iop_NotV128:
sewardj7010f6e2004-12-10 13:35:22 +00002337 case Iop_Not64:
sewardj95448072004-11-22 20:19:51 +00002338 case Iop_Not32:
2339 case Iop_Not16:
2340 case Iop_Not8:
2341 case Iop_Not1:
2342 return vatom;
sewardj7010f6e2004-12-10 13:35:22 +00002343
sewardje53bd992005-05-03 12:22:00 +00002344 /* Neg* really fall under the Add/Sub banner, and as such you
2345 might think would qualify for the 'expensive add/sub'
2346 treatment. However, in this case since the implied literal
2347 is zero (0 - arg), we just do the cheap thing anyway. */
2348 case Iop_Neg8:
2349 return mkLeft8(mce, vatom);
2350 case Iop_Neg16:
2351 return mkLeft16(mce, vatom);
2352 case Iop_Neg32:
2353 return mkLeft32(mce, vatom);
2354
sewardj95448072004-11-22 20:19:51 +00002355 default:
2356 ppIROp(op);
2357 VG_(tool_panic)("memcheck:expr2vbits_Unop");
2358 }
2359}
2360
2361
sewardj170ee212004-12-10 18:57:51 +00002362/* Worker function; do not call directly. */
sewardj95448072004-11-22 20:19:51 +00002363static
sewardj2e595852005-06-30 23:33:37 +00002364IRAtom* expr2vbits_Load_WRK ( MCEnv* mce,
2365 IREndness end, IRType ty,
2366 IRAtom* addr, UInt bias )
sewardj95448072004-11-22 20:19:51 +00002367{
2368 void* helper;
2369 Char* hname;
2370 IRDirty* di;
2371 IRTemp datavbits;
2372 IRAtom* addrAct;
2373
2374 tl_assert(isOriginalAtom(mce,addr));
sewardj2e595852005-06-30 23:33:37 +00002375 tl_assert(end == Iend_LE || end == Iend_BE);
sewardj95448072004-11-22 20:19:51 +00002376
2377 /* First, emit a definedness test for the address. This also sets
2378 the address (shadow) to 'defined' following the test. */
2379 complainIfUndefined( mce, addr );
2380
2381 /* Now cook up a call to the relevant helper function, to read the
2382 data V bits from shadow memory. */
2383 ty = shadowType(ty);
sewardj2e595852005-06-30 23:33:37 +00002384
2385 if (end == Iend_LE) {
2386 switch (ty) {
2387 case Ity_I64: helper = &MC_(helperc_LOADV8le);
2388 hname = "MC_(helperc_LOADV8le)";
2389 break;
2390 case Ity_I32: helper = &MC_(helperc_LOADV4le);
2391 hname = "MC_(helperc_LOADV4le)";
2392 break;
2393 case Ity_I16: helper = &MC_(helperc_LOADV2le);
2394 hname = "MC_(helperc_LOADV2le)";
2395 break;
sewardj8cf88b72005-07-08 01:29:33 +00002396 case Ity_I8: helper = &MC_(helperc_LOADV1);
2397 hname = "MC_(helperc_LOADV1)";
sewardj2e595852005-06-30 23:33:37 +00002398 break;
2399 default: ppIRType(ty);
2400 VG_(tool_panic)("memcheck:do_shadow_Load(LE)");
2401 }
2402 } else {
sewardj8cf88b72005-07-08 01:29:33 +00002403 switch (ty) {
2404 case Ity_I64: helper = &MC_(helperc_LOADV8be);
2405 hname = "MC_(helperc_LOADV8be)";
2406 break;
2407 case Ity_I32: helper = &MC_(helperc_LOADV4be);
2408 hname = "MC_(helperc_LOADV4be)";
2409 break;
2410 case Ity_I16: helper = &MC_(helperc_LOADV2be);
2411 hname = "MC_(helperc_LOADV2be)";
2412 break;
2413 case Ity_I8: helper = &MC_(helperc_LOADV1);
2414 hname = "MC_(helperc_LOADV1)";
2415 break;
2416 default: ppIRType(ty);
2417 VG_(tool_panic)("memcheck:do_shadow_Load(BE)");
2418 }
sewardj95448072004-11-22 20:19:51 +00002419 }
2420
2421 /* Generate the actual address into addrAct. */
2422 if (bias == 0) {
2423 addrAct = addr;
2424 } else {
sewardj7cf97ee2004-11-28 14:25:01 +00002425 IROp mkAdd;
2426 IRAtom* eBias;
sewardj95448072004-11-22 20:19:51 +00002427 IRType tyAddr = mce->hWordTy;
2428 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj7cf97ee2004-11-28 14:25:01 +00002429 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2430 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj95448072004-11-22 20:19:51 +00002431 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2432 }
2433
2434 /* We need to have a place to park the V bits we're just about to
2435 read. */
2436 datavbits = newIRTemp(mce->bb->tyenv, ty);
2437 di = unsafeIRDirty_1_N( datavbits,
sewardj53ee1fc2005-12-23 02:29:58 +00002438 1/*regparms*/,
2439 hname, VG_(fnptr_to_fnentry)( helper ),
sewardj95448072004-11-22 20:19:51 +00002440 mkIRExprVec_1( addrAct ));
2441 setHelperAnns( mce, di );
2442 stmt( mce->bb, IRStmt_Dirty(di) );
2443
2444 return mkexpr(datavbits);
2445}
2446
2447
2448static
sewardj2e595852005-06-30 23:33:37 +00002449IRAtom* expr2vbits_Load ( MCEnv* mce,
2450 IREndness end, IRType ty,
2451 IRAtom* addr, UInt bias )
sewardj170ee212004-12-10 18:57:51 +00002452{
2453 IRAtom *v64hi, *v64lo;
sewardj2e595852005-06-30 23:33:37 +00002454 tl_assert(end == Iend_LE || end == Iend_BE);
sewardj170ee212004-12-10 18:57:51 +00002455 switch (shadowType(ty)) {
2456 case Ity_I8:
2457 case Ity_I16:
2458 case Ity_I32:
2459 case Ity_I64:
sewardj2e595852005-06-30 23:33:37 +00002460 return expr2vbits_Load_WRK(mce, end, ty, addr, bias);
sewardj170ee212004-12-10 18:57:51 +00002461 case Ity_V128:
sewardj2e595852005-06-30 23:33:37 +00002462 if (end == Iend_LE) {
2463 v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
2464 v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
2465 } else {
sewardj2e595852005-06-30 23:33:37 +00002466 v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
2467 v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
2468 }
sewardj170ee212004-12-10 18:57:51 +00002469 return assignNew( mce,
2470 Ity_V128,
sewardj20d38f22005-02-07 23:50:18 +00002471 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj170ee212004-12-10 18:57:51 +00002472 default:
sewardj2e595852005-06-30 23:33:37 +00002473 VG_(tool_panic)("expr2vbits_Load");
sewardj170ee212004-12-10 18:57:51 +00002474 }
2475}
2476
2477
2478static
sewardj95448072004-11-22 20:19:51 +00002479IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
2480 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
2481{
2482 IRAtom *vbitsC, *vbits0, *vbitsX;
2483 IRType ty;
2484 /* Given Mux0X(cond,expr0,exprX), generate
2485 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
2486 That is, steer the V bits like the originals, but trash the
2487 result if the steering value is undefined. This gives
2488 lazy propagation. */
2489 tl_assert(isOriginalAtom(mce, cond));
2490 tl_assert(isOriginalAtom(mce, expr0));
2491 tl_assert(isOriginalAtom(mce, exprX));
2492
2493 vbitsC = expr2vbits(mce, cond);
2494 vbits0 = expr2vbits(mce, expr0);
2495 vbitsX = expr2vbits(mce, exprX);
2496 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
2497
2498 return
2499 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
2500 mkPCastTo(mce, ty, vbitsC) );
2501}
2502
2503/* --------- This is the main expression-handling function. --------- */
2504
2505static
2506IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
2507{
2508 switch (e->tag) {
2509
2510 case Iex_Get:
2511 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
2512
2513 case Iex_GetI:
2514 return shadow_GETI( mce, e->Iex.GetI.descr,
2515 e->Iex.GetI.ix, e->Iex.GetI.bias );
2516
2517 case Iex_Tmp:
2518 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
2519
2520 case Iex_Const:
2521 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
2522
sewardjed69fdb2006-02-03 16:12:27 +00002523 case Iex_Triop:
2524 return expr2vbits_Triop(
2525 mce,
2526 e->Iex.Triop.op,
2527 e->Iex.Triop.arg1, e->Iex.Triop.arg2, e->Iex.Triop.arg3
2528 );
2529
sewardj95448072004-11-22 20:19:51 +00002530 case Iex_Binop:
2531 return expr2vbits_Binop(
2532 mce,
2533 e->Iex.Binop.op,
2534 e->Iex.Binop.arg1, e->Iex.Binop.arg2
2535 );
2536
2537 case Iex_Unop:
2538 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
2539
sewardj2e595852005-06-30 23:33:37 +00002540 case Iex_Load:
2541 return expr2vbits_Load( mce, e->Iex.Load.end,
2542 e->Iex.Load.ty,
2543 e->Iex.Load.addr, 0/*addr bias*/ );
sewardj95448072004-11-22 20:19:51 +00002544
2545 case Iex_CCall:
2546 return mkLazyN( mce, e->Iex.CCall.args,
2547 e->Iex.CCall.retty,
2548 e->Iex.CCall.cee );
2549
2550 case Iex_Mux0X:
2551 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
2552 e->Iex.Mux0X.exprX);
njn25e49d8e72002-09-23 09:36:25 +00002553
2554 default:
sewardj95448072004-11-22 20:19:51 +00002555 VG_(printf)("\n");
2556 ppIRExpr(e);
2557 VG_(printf)("\n");
2558 VG_(tool_panic)("memcheck: expr2vbits");
njn25e49d8e72002-09-23 09:36:25 +00002559 }
njn25e49d8e72002-09-23 09:36:25 +00002560}
2561
2562/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00002563/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
njn25e49d8e72002-09-23 09:36:25 +00002564/*------------------------------------------------------------*/
2565
sewardj95448072004-11-22 20:19:51 +00002566/* Widen a value to the host word size. */
njn25e49d8e72002-09-23 09:36:25 +00002567
2568static
sewardj95448072004-11-22 20:19:51 +00002569IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
njn25e49d8e72002-09-23 09:36:25 +00002570{
sewardj7cf97ee2004-11-28 14:25:01 +00002571 IRType ty, tyH;
2572
sewardj95448072004-11-22 20:19:51 +00002573 /* vatom is vbits-value and as such can only have a shadow type. */
2574 tl_assert(isShadowAtom(mce,vatom));
njn25e49d8e72002-09-23 09:36:25 +00002575
sewardj7cf97ee2004-11-28 14:25:01 +00002576 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
2577 tyH = mce->hWordTy;
njn25e49d8e72002-09-23 09:36:25 +00002578
sewardj95448072004-11-22 20:19:51 +00002579 if (tyH == Ity_I32) {
2580 switch (ty) {
2581 case Ity_I32: return vatom;
2582 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
2583 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
2584 default: goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00002585 }
sewardj6cf40ff2005-04-20 22:31:26 +00002586 } else
2587 if (tyH == Ity_I64) {
2588 switch (ty) {
2589 case Ity_I32: return assignNew(mce, tyH, unop(Iop_32Uto64, vatom));
sewardj69a13322005-04-23 01:14:51 +00002590 case Ity_I16: return assignNew(mce, tyH, unop(Iop_32Uto64,
2591 assignNew(mce, Ity_I32, unop(Iop_16Uto32, vatom))));
2592 case Ity_I8: return assignNew(mce, tyH, unop(Iop_32Uto64,
2593 assignNew(mce, Ity_I32, unop(Iop_8Uto32, vatom))));
sewardj6cf40ff2005-04-20 22:31:26 +00002594 default: goto unhandled;
2595 }
sewardj95448072004-11-22 20:19:51 +00002596 } else {
2597 goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00002598 }
sewardj95448072004-11-22 20:19:51 +00002599 unhandled:
2600 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
2601 VG_(tool_panic)("zwidenToHostWord");
njn25e49d8e72002-09-23 09:36:25 +00002602}
2603
njn25e49d8e72002-09-23 09:36:25 +00002604
sewardj95448072004-11-22 20:19:51 +00002605/* Generate a shadow store. addr is always the original address atom.
2606 You can pass in either originals or V-bits for the data atom, but
2607 obviously not both. */
njn25e49d8e72002-09-23 09:36:25 +00002608
sewardj95448072004-11-22 20:19:51 +00002609static
sewardj2e595852005-06-30 23:33:37 +00002610void do_shadow_Store ( MCEnv* mce,
2611 IREndness end,
2612 IRAtom* addr, UInt bias,
2613 IRAtom* data, IRAtom* vdata )
njn25e49d8e72002-09-23 09:36:25 +00002614{
sewardj170ee212004-12-10 18:57:51 +00002615 IROp mkAdd;
2616 IRType ty, tyAddr;
2617 IRDirty *di, *diLo64, *diHi64;
2618 IRAtom *addrAct, *addrLo64, *addrHi64;
2619 IRAtom *vdataLo64, *vdataHi64;
sewardj2e595852005-06-30 23:33:37 +00002620 IRAtom *eBias, *eBiasLo64, *eBiasHi64;
sewardj95448072004-11-22 20:19:51 +00002621 void* helper = NULL;
2622 Char* hname = NULL;
sewardj170ee212004-12-10 18:57:51 +00002623
2624 tyAddr = mce->hWordTy;
2625 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2626 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj2e595852005-06-30 23:33:37 +00002627 tl_assert( end == Iend_LE || end == Iend_BE );
sewardj170ee212004-12-10 18:57:51 +00002628
2629 di = diLo64 = diHi64 = NULL;
sewardj2e595852005-06-30 23:33:37 +00002630 eBias = eBiasLo64 = eBiasHi64 = NULL;
sewardj170ee212004-12-10 18:57:51 +00002631 addrAct = addrLo64 = addrHi64 = NULL;
2632 vdataLo64 = vdataHi64 = NULL;
njn25e49d8e72002-09-23 09:36:25 +00002633
sewardj95448072004-11-22 20:19:51 +00002634 if (data) {
2635 tl_assert(!vdata);
2636 tl_assert(isOriginalAtom(mce, data));
2637 tl_assert(bias == 0);
2638 vdata = expr2vbits( mce, data );
2639 } else {
2640 tl_assert(vdata);
2641 }
njn25e49d8e72002-09-23 09:36:25 +00002642
sewardj95448072004-11-22 20:19:51 +00002643 tl_assert(isOriginalAtom(mce,addr));
2644 tl_assert(isShadowAtom(mce,vdata));
njn25e49d8e72002-09-23 09:36:25 +00002645
sewardj95448072004-11-22 20:19:51 +00002646 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
njn25e49d8e72002-09-23 09:36:25 +00002647
sewardj95448072004-11-22 20:19:51 +00002648 /* First, emit a definedness test for the address. This also sets
2649 the address (shadow) to 'defined' following the test. */
2650 complainIfUndefined( mce, addr );
njn25e49d8e72002-09-23 09:36:25 +00002651
sewardj170ee212004-12-10 18:57:51 +00002652 /* Now decide which helper function to call to write the data V
2653 bits into shadow memory. */
sewardj2e595852005-06-30 23:33:37 +00002654 if (end == Iend_LE) {
2655 switch (ty) {
2656 case Ity_V128: /* we'll use the helper twice */
2657 case Ity_I64: helper = &MC_(helperc_STOREV8le);
2658 hname = "MC_(helperc_STOREV8le)";
2659 break;
2660 case Ity_I32: helper = &MC_(helperc_STOREV4le);
2661 hname = "MC_(helperc_STOREV4le)";
2662 break;
2663 case Ity_I16: helper = &MC_(helperc_STOREV2le);
2664 hname = "MC_(helperc_STOREV2le)";
2665 break;
sewardj8cf88b72005-07-08 01:29:33 +00002666 case Ity_I8: helper = &MC_(helperc_STOREV1);
2667 hname = "MC_(helperc_STOREV1)";
sewardj2e595852005-06-30 23:33:37 +00002668 break;
2669 default: VG_(tool_panic)("memcheck:do_shadow_Store(LE)");
2670 }
2671 } else {
sewardj8cf88b72005-07-08 01:29:33 +00002672 switch (ty) {
2673 case Ity_V128: /* we'll use the helper twice */
2674 case Ity_I64: helper = &MC_(helperc_STOREV8be);
2675 hname = "MC_(helperc_STOREV8be)";
2676 break;
2677 case Ity_I32: helper = &MC_(helperc_STOREV4be);
2678 hname = "MC_(helperc_STOREV4be)";
2679 break;
2680 case Ity_I16: helper = &MC_(helperc_STOREV2be);
2681 hname = "MC_(helperc_STOREV2be)";
2682 break;
2683 case Ity_I8: helper = &MC_(helperc_STOREV1);
2684 hname = "MC_(helperc_STOREV1)";
2685 break;
2686 default: VG_(tool_panic)("memcheck:do_shadow_Store(BE)");
2687 }
sewardj95448072004-11-22 20:19:51 +00002688 }
njn25e49d8e72002-09-23 09:36:25 +00002689
sewardj170ee212004-12-10 18:57:51 +00002690 if (ty == Ity_V128) {
2691
sewardj20d38f22005-02-07 23:50:18 +00002692 /* V128-bit case */
sewardj170ee212004-12-10 18:57:51 +00002693 /* See comment in next clause re 64-bit regparms */
sewardj2e595852005-06-30 23:33:37 +00002694 /* also, need to be careful about endianness */
2695
2696 Int offLo64, offHi64;
2697 if (end == Iend_LE) {
2698 offLo64 = 0;
2699 offHi64 = 8;
2700 } else {
sewardj2e595852005-06-30 23:33:37 +00002701 offLo64 = 8;
2702 offHi64 = 0;
2703 }
2704
2705 eBiasLo64 = tyAddr==Ity_I32 ? mkU32(bias+offLo64) : mkU64(bias+offLo64);
2706 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBiasLo64) );
sewardj20d38f22005-02-07 23:50:18 +00002707 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj170ee212004-12-10 18:57:51 +00002708 diLo64 = unsafeIRDirty_0_N(
sewardj53ee1fc2005-12-23 02:29:58 +00002709 1/*regparms*/,
2710 hname, VG_(fnptr_to_fnentry)( helper ),
2711 mkIRExprVec_2( addrLo64, vdataLo64 )
2712 );
sewardj2e595852005-06-30 23:33:37 +00002713 eBiasHi64 = tyAddr==Ity_I32 ? mkU32(bias+offHi64) : mkU64(bias+offHi64);
2714 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBiasHi64) );
sewardj20d38f22005-02-07 23:50:18 +00002715 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj170ee212004-12-10 18:57:51 +00002716 diHi64 = unsafeIRDirty_0_N(
sewardj53ee1fc2005-12-23 02:29:58 +00002717 1/*regparms*/,
2718 hname, VG_(fnptr_to_fnentry)( helper ),
2719 mkIRExprVec_2( addrHi64, vdataHi64 )
2720 );
sewardj170ee212004-12-10 18:57:51 +00002721 setHelperAnns( mce, diLo64 );
2722 setHelperAnns( mce, diHi64 );
2723 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2724 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2725
sewardj95448072004-11-22 20:19:51 +00002726 } else {
sewardj170ee212004-12-10 18:57:51 +00002727
2728 /* 8/16/32/64-bit cases */
2729 /* Generate the actual address into addrAct. */
2730 if (bias == 0) {
2731 addrAct = addr;
2732 } else {
2733 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2734 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2735 }
2736
2737 if (ty == Ity_I64) {
2738 /* We can't do this with regparm 2 on 32-bit platforms, since
2739 the back ends aren't clever enough to handle 64-bit
2740 regparm args. Therefore be different. */
2741 di = unsafeIRDirty_0_N(
sewardj53ee1fc2005-12-23 02:29:58 +00002742 1/*regparms*/,
2743 hname, VG_(fnptr_to_fnentry)( helper ),
2744 mkIRExprVec_2( addrAct, vdata )
2745 );
sewardj170ee212004-12-10 18:57:51 +00002746 } else {
2747 di = unsafeIRDirty_0_N(
sewardj53ee1fc2005-12-23 02:29:58 +00002748 2/*regparms*/,
2749 hname, VG_(fnptr_to_fnentry)( helper ),
sewardj170ee212004-12-10 18:57:51 +00002750 mkIRExprVec_2( addrAct,
sewardj53ee1fc2005-12-23 02:29:58 +00002751 zwidenToHostWord( mce, vdata ))
2752 );
sewardj170ee212004-12-10 18:57:51 +00002753 }
2754 setHelperAnns( mce, di );
2755 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj95448072004-11-22 20:19:51 +00002756 }
njn25e49d8e72002-09-23 09:36:25 +00002757
sewardj95448072004-11-22 20:19:51 +00002758}
njn25e49d8e72002-09-23 09:36:25 +00002759
njn25e49d8e72002-09-23 09:36:25 +00002760
sewardj95448072004-11-22 20:19:51 +00002761/* Do lazy pessimistic propagation through a dirty helper call, by
2762 looking at the annotations on it. This is the most complex part of
2763 Memcheck. */
njn25e49d8e72002-09-23 09:36:25 +00002764
sewardj95448072004-11-22 20:19:51 +00002765static IRType szToITy ( Int n )
2766{
2767 switch (n) {
2768 case 1: return Ity_I8;
2769 case 2: return Ity_I16;
2770 case 4: return Ity_I32;
2771 case 8: return Ity_I64;
2772 default: VG_(tool_panic)("szToITy(memcheck)");
2773 }
2774}
njn25e49d8e72002-09-23 09:36:25 +00002775
sewardj95448072004-11-22 20:19:51 +00002776static
2777void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2778{
sewardj2e595852005-06-30 23:33:37 +00002779 Int i, n, offset, toDo, gSz, gOff;
2780 IRAtom *src, *here, *curr;
2781 IRType tyAddr, tySrc, tyDst;
2782 IRTemp dst;
2783 IREndness end;
2784
2785 /* What's the native endianness? We need to know this. */
sewardj6e340c72005-07-10 00:53:42 +00002786# if defined(VG_BIGENDIAN)
sewardj2e595852005-06-30 23:33:37 +00002787 end = Iend_BE;
sewardj6e340c72005-07-10 00:53:42 +00002788# elif defined(VG_LITTLEENDIAN)
sewardj2e595852005-06-30 23:33:37 +00002789 end = Iend_LE;
2790# else
2791# error "Unknown endianness"
2792# endif
njn25e49d8e72002-09-23 09:36:25 +00002793
sewardj95448072004-11-22 20:19:51 +00002794 /* First check the guard. */
2795 complainIfUndefined(mce, d->guard);
2796
2797 /* Now round up all inputs and PCast over them. */
sewardj7cf97ee2004-11-28 14:25:01 +00002798 curr = definedOfType(Ity_I32);
sewardj95448072004-11-22 20:19:51 +00002799
2800 /* Inputs: unmasked args */
2801 for (i = 0; d->args[i]; i++) {
2802 if (d->cee->mcx_mask & (1<<i)) {
2803 /* ignore this arg */
njn25e49d8e72002-09-23 09:36:25 +00002804 } else {
sewardj95448072004-11-22 20:19:51 +00002805 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2806 curr = mkUifU32(mce, here, curr);
njn25e49d8e72002-09-23 09:36:25 +00002807 }
2808 }
sewardj95448072004-11-22 20:19:51 +00002809
2810 /* Inputs: guest state that we read. */
2811 for (i = 0; i < d->nFxState; i++) {
2812 tl_assert(d->fxState[i].fx != Ifx_None);
2813 if (d->fxState[i].fx == Ifx_Write)
2814 continue;
sewardja7203252004-11-26 19:17:47 +00002815
2816 /* Ignore any sections marked as 'always defined'. */
2817 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
sewardje9e16d32004-12-10 13:17:55 +00002818 if (0)
sewardja7203252004-11-26 19:17:47 +00002819 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2820 d->fxState[i].offset, d->fxState[i].size );
2821 continue;
2822 }
2823
sewardj95448072004-11-22 20:19:51 +00002824 /* This state element is read or modified. So we need to
sewardje9e16d32004-12-10 13:17:55 +00002825 consider it. If larger than 8 bytes, deal with it in 8-byte
2826 chunks. */
2827 gSz = d->fxState[i].size;
2828 gOff = d->fxState[i].offset;
2829 tl_assert(gSz > 0);
2830 while (True) {
2831 if (gSz == 0) break;
2832 n = gSz <= 8 ? gSz : 8;
2833 /* update 'curr' with UifU of the state slice
2834 gOff .. gOff+n-1 */
2835 tySrc = szToITy( n );
2836 src = assignNew( mce, tySrc,
2837 shadow_GET(mce, gOff, tySrc ) );
2838 here = mkPCastTo( mce, Ity_I32, src );
2839 curr = mkUifU32(mce, here, curr);
2840 gSz -= n;
2841 gOff += n;
2842 }
2843
sewardj95448072004-11-22 20:19:51 +00002844 }
2845
2846 /* Inputs: memory. First set up some info needed regardless of
2847 whether we're doing reads or writes. */
2848 tyAddr = Ity_INVALID;
2849
2850 if (d->mFx != Ifx_None) {
2851 /* Because we may do multiple shadow loads/stores from the same
2852 base address, it's best to do a single test of its
2853 definedness right now. Post-instrumentation optimisation
2854 should remove all but this test. */
2855 tl_assert(d->mAddr);
2856 complainIfUndefined(mce, d->mAddr);
2857
2858 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
2859 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2860 tl_assert(tyAddr == mce->hWordTy); /* not really right */
2861 }
2862
2863 /* Deal with memory inputs (reads or modifies) */
2864 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2865 offset = 0;
2866 toDo = d->mSize;
sewardj2e595852005-06-30 23:33:37 +00002867 /* chew off 32-bit chunks. We don't care about the endianness
2868 since it's all going to be condensed down to a single bit,
2869 but nevertheless choose an endianness which is hopefully
2870 native to the platform. */
sewardj95448072004-11-22 20:19:51 +00002871 while (toDo >= 4) {
2872 here = mkPCastTo(
2873 mce, Ity_I32,
sewardj2e595852005-06-30 23:33:37 +00002874 expr2vbits_Load ( mce, end, Ity_I32,
sewardj95448072004-11-22 20:19:51 +00002875 d->mAddr, d->mSize - toDo )
2876 );
2877 curr = mkUifU32(mce, here, curr);
2878 toDo -= 4;
2879 }
2880 /* chew off 16-bit chunks */
2881 while (toDo >= 2) {
2882 here = mkPCastTo(
2883 mce, Ity_I32,
sewardj2e595852005-06-30 23:33:37 +00002884 expr2vbits_Load ( mce, end, Ity_I16,
sewardj95448072004-11-22 20:19:51 +00002885 d->mAddr, d->mSize - toDo )
2886 );
2887 curr = mkUifU32(mce, here, curr);
2888 toDo -= 2;
2889 }
2890 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
2891 }
2892
2893 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2894 all the inputs to the helper. Now we need to re-distribute the
2895 results to all destinations. */
2896
2897 /* Outputs: the destination temporary, if there is one. */
2898 if (d->tmp != IRTemp_INVALID) {
2899 dst = findShadowTmp(mce, d->tmp);
2900 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2901 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2902 }
2903
2904 /* Outputs: guest state that we write or modify. */
2905 for (i = 0; i < d->nFxState; i++) {
2906 tl_assert(d->fxState[i].fx != Ifx_None);
2907 if (d->fxState[i].fx == Ifx_Read)
2908 continue;
sewardja7203252004-11-26 19:17:47 +00002909 /* Ignore any sections marked as 'always defined'. */
2910 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2911 continue;
sewardje9e16d32004-12-10 13:17:55 +00002912 /* This state element is written or modified. So we need to
2913 consider it. If larger than 8 bytes, deal with it in 8-byte
2914 chunks. */
2915 gSz = d->fxState[i].size;
2916 gOff = d->fxState[i].offset;
2917 tl_assert(gSz > 0);
2918 while (True) {
2919 if (gSz == 0) break;
2920 n = gSz <= 8 ? gSz : 8;
2921 /* Write suitably-casted 'curr' to the state slice
2922 gOff .. gOff+n-1 */
2923 tyDst = szToITy( n );
2924 do_shadow_PUT( mce, gOff,
2925 NULL, /* original atom */
2926 mkPCastTo( mce, tyDst, curr ) );
2927 gSz -= n;
2928 gOff += n;
2929 }
sewardj95448072004-11-22 20:19:51 +00002930 }
2931
sewardj2e595852005-06-30 23:33:37 +00002932 /* Outputs: memory that we write or modify. Same comments about
2933 endianness as above apply. */
sewardj95448072004-11-22 20:19:51 +00002934 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2935 offset = 0;
2936 toDo = d->mSize;
2937 /* chew off 32-bit chunks */
2938 while (toDo >= 4) {
sewardj2e595852005-06-30 23:33:37 +00002939 do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
2940 NULL, /* original data */
2941 mkPCastTo( mce, Ity_I32, curr ) );
sewardj95448072004-11-22 20:19:51 +00002942 toDo -= 4;
2943 }
2944 /* chew off 16-bit chunks */
2945 while (toDo >= 2) {
sewardj2e595852005-06-30 23:33:37 +00002946 do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
2947 NULL, /* original data */
2948 mkPCastTo( mce, Ity_I16, curr ) );
sewardj95448072004-11-22 20:19:51 +00002949 toDo -= 2;
2950 }
2951 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
2952 }
2953
njn25e49d8e72002-09-23 09:36:25 +00002954}
2955
sewardj826ec492005-05-12 18:05:00 +00002956/* We have an ABI hint telling us that [base .. base+len-1] is to
2957 become undefined ("writable"). Generate code to call a helper to
2958 notify the A/V bit machinery of this fact.
2959
2960 We call
2961 void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len );
2962*/
2963static
2964void do_AbiHint ( MCEnv* mce, IRExpr* base, Int len )
2965{
2966 IRDirty* di;
2967 di = unsafeIRDirty_0_N(
2968 0/*regparms*/,
2969 "MC_(helperc_MAKE_STACK_UNINIT)",
sewardj53ee1fc2005-12-23 02:29:58 +00002970 VG_(fnptr_to_fnentry)( &MC_(helperc_MAKE_STACK_UNINIT) ),
sewardj826ec492005-05-12 18:05:00 +00002971 mkIRExprVec_2( base, mkIRExpr_HWord( (UInt)len) )
2972 );
2973 stmt( mce->bb, IRStmt_Dirty(di) );
2974}
2975
njn25e49d8e72002-09-23 09:36:25 +00002976
sewardj95448072004-11-22 20:19:51 +00002977/*------------------------------------------------------------*/
2978/*--- Memcheck main ---*/
2979/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00002980
sewardj95448072004-11-22 20:19:51 +00002981static Bool isBogusAtom ( IRAtom* at )
njn25e49d8e72002-09-23 09:36:25 +00002982{
sewardj95448072004-11-22 20:19:51 +00002983 ULong n = 0;
2984 IRConst* con;
sewardj710d6c22005-03-20 18:55:15 +00002985 tl_assert(isIRAtom(at));
sewardj95448072004-11-22 20:19:51 +00002986 if (at->tag == Iex_Tmp)
2987 return False;
2988 tl_assert(at->tag == Iex_Const);
2989 con = at->Iex.Const.con;
2990 switch (con->tag) {
sewardjd5204dc2004-12-31 01:16:11 +00002991 case Ico_U1: return False;
2992 case Ico_U8: n = (ULong)con->Ico.U8; break;
2993 case Ico_U16: n = (ULong)con->Ico.U16; break;
2994 case Ico_U32: n = (ULong)con->Ico.U32; break;
2995 case Ico_U64: n = (ULong)con->Ico.U64; break;
2996 case Ico_F64: return False;
2997 case Ico_F64i: return False;
2998 case Ico_V128: return False;
sewardj95448072004-11-22 20:19:51 +00002999 default: ppIRExpr(at); tl_assert(0);
3000 }
3001 /* VG_(printf)("%llx\n", n); */
sewardj96a922e2005-04-23 23:26:29 +00003002 return (/*32*/ n == 0xFEFEFEFFULL
3003 /*32*/ || n == 0x80808080ULL
tomd9774d72005-06-27 08:11:01 +00003004 /*64*/ || n == 0xFFFFFFFFFEFEFEFFULL
sewardj96a922e2005-04-23 23:26:29 +00003005 /*64*/ || n == 0xFEFEFEFEFEFEFEFFULL
tomd9774d72005-06-27 08:11:01 +00003006 /*64*/ || n == 0x0000000000008080ULL
sewardj96a922e2005-04-23 23:26:29 +00003007 /*64*/ || n == 0x8080808080808080ULL
3008 /*64*/ || n == 0x0101010101010101ULL
3009 );
sewardj95448072004-11-22 20:19:51 +00003010}
njn25e49d8e72002-09-23 09:36:25 +00003011
sewardj95448072004-11-22 20:19:51 +00003012static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
3013{
sewardjd5204dc2004-12-31 01:16:11 +00003014 Int i;
3015 IRExpr* e;
3016 IRDirty* d;
sewardj95448072004-11-22 20:19:51 +00003017 switch (st->tag) {
3018 case Ist_Tmp:
3019 e = st->Ist.Tmp.data;
3020 switch (e->tag) {
3021 case Iex_Get:
3022 case Iex_Tmp:
3023 return False;
sewardjd5204dc2004-12-31 01:16:11 +00003024 case Iex_Const:
3025 return isBogusAtom(e);
sewardj95448072004-11-22 20:19:51 +00003026 case Iex_Unop:
3027 return isBogusAtom(e->Iex.Unop.arg);
sewardjd5204dc2004-12-31 01:16:11 +00003028 case Iex_GetI:
3029 return isBogusAtom(e->Iex.GetI.ix);
sewardj95448072004-11-22 20:19:51 +00003030 case Iex_Binop:
3031 return isBogusAtom(e->Iex.Binop.arg1)
3032 || isBogusAtom(e->Iex.Binop.arg2);
sewardjed69fdb2006-02-03 16:12:27 +00003033 case Iex_Triop:
3034 return isBogusAtom(e->Iex.Triop.arg1)
3035 || isBogusAtom(e->Iex.Triop.arg2)
3036 || isBogusAtom(e->Iex.Triop.arg3);
sewardj95448072004-11-22 20:19:51 +00003037 case Iex_Mux0X:
3038 return isBogusAtom(e->Iex.Mux0X.cond)
3039 || isBogusAtom(e->Iex.Mux0X.expr0)
3040 || isBogusAtom(e->Iex.Mux0X.exprX);
sewardj2e595852005-06-30 23:33:37 +00003041 case Iex_Load:
3042 return isBogusAtom(e->Iex.Load.addr);
sewardj95448072004-11-22 20:19:51 +00003043 case Iex_CCall:
3044 for (i = 0; e->Iex.CCall.args[i]; i++)
3045 if (isBogusAtom(e->Iex.CCall.args[i]))
3046 return True;
3047 return False;
3048 default:
3049 goto unhandled;
3050 }
sewardjd5204dc2004-12-31 01:16:11 +00003051 case Ist_Dirty:
3052 d = st->Ist.Dirty.details;
3053 for (i = 0; d->args[i]; i++)
3054 if (isBogusAtom(d->args[i]))
3055 return True;
3056 if (d->guard && isBogusAtom(d->guard))
3057 return True;
3058 if (d->mAddr && isBogusAtom(d->mAddr))
3059 return True;
3060 return False;
sewardj95448072004-11-22 20:19:51 +00003061 case Ist_Put:
3062 return isBogusAtom(st->Ist.Put.data);
sewardjd5204dc2004-12-31 01:16:11 +00003063 case Ist_PutI:
3064 return isBogusAtom(st->Ist.PutI.ix)
3065 || isBogusAtom(st->Ist.PutI.data);
sewardj2e595852005-06-30 23:33:37 +00003066 case Ist_Store:
3067 return isBogusAtom(st->Ist.Store.addr)
3068 || isBogusAtom(st->Ist.Store.data);
sewardj95448072004-11-22 20:19:51 +00003069 case Ist_Exit:
sewardjd5204dc2004-12-31 01:16:11 +00003070 return isBogusAtom(st->Ist.Exit.guard);
sewardj826ec492005-05-12 18:05:00 +00003071 case Ist_AbiHint:
3072 return isBogusAtom(st->Ist.AbiHint.base);
sewardj21dc3452005-03-21 00:27:41 +00003073 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00003074 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00003075 case Ist_MFence:
3076 return False;
sewardj95448072004-11-22 20:19:51 +00003077 default:
3078 unhandled:
3079 ppIRStmt(st);
3080 VG_(tool_panic)("hasBogusLiterals");
3081 }
3082}
njn25e49d8e72002-09-23 09:36:25 +00003083
njn25e49d8e72002-09-23 09:36:25 +00003084
sewardj461df9c2006-01-17 02:06:39 +00003085IRBB* MC_(instrument) ( VgCallbackClosure* closure,
3086 IRBB* bb_in,
3087 VexGuestLayout* layout,
3088 VexGuestExtents* vge,
sewardjd54babf2005-03-21 00:55:49 +00003089 IRType gWordTy, IRType hWordTy )
sewardj95448072004-11-22 20:19:51 +00003090{
sewardj151b90d2005-07-06 19:42:23 +00003091 Bool verboze = False; //True;
3092 Bool bogus;
sewardjd5204dc2004-12-31 01:16:11 +00003093 Int i, j, first_stmt;
sewardj95448072004-11-22 20:19:51 +00003094 IRStmt* st;
sewardjd5204dc2004-12-31 01:16:11 +00003095 MCEnv mce;
sewardjd54babf2005-03-21 00:55:49 +00003096 IRBB* bb;
3097
3098 if (gWordTy != hWordTy) {
3099 /* We don't currently support this case. */
3100 VG_(tool_panic)("host/guest word size mismatch");
3101 }
njn25e49d8e72002-09-23 09:36:25 +00003102
sewardj6cf40ff2005-04-20 22:31:26 +00003103 /* Check we're not completely nuts */
3104 tl_assert(sizeof(UWord) == sizeof(void*));
3105 tl_assert(sizeof(Word) == sizeof(void*));
3106 tl_assert(sizeof(ULong) == 8);
3107 tl_assert(sizeof(Long) == 8);
3108 tl_assert(sizeof(UInt) == 4);
3109 tl_assert(sizeof(Int) == 4);
3110
sewardj95448072004-11-22 20:19:51 +00003111 /* Set up BB */
sewardjd54babf2005-03-21 00:55:49 +00003112 bb = emptyIRBB();
sewardj95448072004-11-22 20:19:51 +00003113 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
3114 bb->next = dopyIRExpr(bb_in->next);
3115 bb->jumpkind = bb_in->jumpkind;
njn25e49d8e72002-09-23 09:36:25 +00003116
sewardj95448072004-11-22 20:19:51 +00003117 /* Set up the running environment. Only .bb is modified as we go
3118 along. */
3119 mce.bb = bb;
3120 mce.layout = layout;
3121 mce.n_originalTmps = bb->tyenv->types_used;
3122 mce.hWordTy = hWordTy;
sewardjd5204dc2004-12-31 01:16:11 +00003123 mce.bogusLiterals = False;
sewardj95448072004-11-22 20:19:51 +00003124 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
3125 for (i = 0; i < mce.n_originalTmps; i++)
3126 mce.tmpMap[i] = IRTemp_INVALID;
3127
sewardj151b90d2005-07-06 19:42:23 +00003128 /* Make a preliminary inspection of the statements, to see if there
3129 are any dodgy-looking literals. If there are, we generate
3130 extra-detailed (hence extra-expensive) instrumentation in
3131 places. Scan the whole bb even if dodgyness is found earlier,
3132 so that the flatness assertion is applied to all stmts. */
3133
3134 bogus = False;
sewardj95448072004-11-22 20:19:51 +00003135
3136 for (i = 0; i < bb_in->stmts_used; i++) {
sewardj151b90d2005-07-06 19:42:23 +00003137
sewardj95448072004-11-22 20:19:51 +00003138 st = bb_in->stmts[i];
sewardj21dc3452005-03-21 00:27:41 +00003139 tl_assert(st);
sewardj95448072004-11-22 20:19:51 +00003140 tl_assert(isFlatIRStmt(st));
3141
sewardj151b90d2005-07-06 19:42:23 +00003142 if (!bogus) {
3143 bogus = checkForBogusLiterals(st);
3144 if (0 && bogus) {
sewardj95448072004-11-22 20:19:51 +00003145 VG_(printf)("bogus: ");
3146 ppIRStmt(st);
3147 VG_(printf)("\n");
3148 }
3149 }
sewardjd5204dc2004-12-31 01:16:11 +00003150
sewardj151b90d2005-07-06 19:42:23 +00003151 }
3152
3153 mce.bogusLiterals = bogus;
3154
3155 /* Iterate over the stmts to generate instrumentation. */
3156
3157 for (i = 0; i < bb_in->stmts_used; i++) {
3158
3159 st = bb_in->stmts[i];
sewardj95448072004-11-22 20:19:51 +00003160 first_stmt = bb->stmts_used;
3161
3162 if (verboze) {
3163 ppIRStmt(st);
3164 VG_(printf)("\n\n");
3165 }
3166
sewardj29faa502005-03-16 18:20:21 +00003167 /* Generate instrumentation code for each stmt ... */
3168
sewardj95448072004-11-22 20:19:51 +00003169 switch (st->tag) {
3170
3171 case Ist_Tmp:
3172 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
3173 expr2vbits( &mce, st->Ist.Tmp.data) );
njn25e49d8e72002-09-23 09:36:25 +00003174 break;
3175
sewardj95448072004-11-22 20:19:51 +00003176 case Ist_Put:
3177 do_shadow_PUT( &mce,
3178 st->Ist.Put.offset,
3179 st->Ist.Put.data,
3180 NULL /* shadow atom */ );
njn25e49d8e72002-09-23 09:36:25 +00003181 break;
3182
sewardj95448072004-11-22 20:19:51 +00003183 case Ist_PutI:
3184 do_shadow_PUTI( &mce,
3185 st->Ist.PutI.descr,
3186 st->Ist.PutI.ix,
3187 st->Ist.PutI.bias,
3188 st->Ist.PutI.data );
njn25e49d8e72002-09-23 09:36:25 +00003189 break;
3190
sewardj2e595852005-06-30 23:33:37 +00003191 case Ist_Store:
3192 do_shadow_Store( &mce, st->Ist.Store.end,
3193 st->Ist.Store.addr, 0/* addr bias */,
3194 st->Ist.Store.data,
3195 NULL /* shadow data */ );
njn25e49d8e72002-09-23 09:36:25 +00003196 break;
3197
sewardj95448072004-11-22 20:19:51 +00003198 case Ist_Exit:
sewardjd5204dc2004-12-31 01:16:11 +00003199 complainIfUndefined( &mce, st->Ist.Exit.guard );
njn25e49d8e72002-09-23 09:36:25 +00003200 break;
3201
sewardj21dc3452005-03-21 00:27:41 +00003202 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00003203 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00003204 case Ist_MFence:
3205 break;
3206
sewardj95448072004-11-22 20:19:51 +00003207 case Ist_Dirty:
3208 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
njn25e49d8e72002-09-23 09:36:25 +00003209 break;
3210
sewardj826ec492005-05-12 18:05:00 +00003211 case Ist_AbiHint:
3212 do_AbiHint( &mce, st->Ist.AbiHint.base, st->Ist.AbiHint.len );
3213 break;
3214
njn25e49d8e72002-09-23 09:36:25 +00003215 default:
sewardj95448072004-11-22 20:19:51 +00003216 VG_(printf)("\n");
3217 ppIRStmt(st);
3218 VG_(printf)("\n");
3219 VG_(tool_panic)("memcheck: unhandled IRStmt");
3220
3221 } /* switch (st->tag) */
3222
3223 if (verboze) {
3224 for (j = first_stmt; j < bb->stmts_used; j++) {
3225 VG_(printf)(" ");
3226 ppIRStmt(bb->stmts[j]);
3227 VG_(printf)("\n");
3228 }
3229 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00003230 }
sewardj95448072004-11-22 20:19:51 +00003231
sewardj29faa502005-03-16 18:20:21 +00003232 /* ... and finally copy the stmt itself to the output. */
sewardj95448072004-11-22 20:19:51 +00003233 addStmtToIRBB(bb, st);
3234
njn25e49d8e72002-09-23 09:36:25 +00003235 }
njn25e49d8e72002-09-23 09:36:25 +00003236
sewardj95448072004-11-22 20:19:51 +00003237 /* Now we need to complain if the jump target is undefined. */
3238 first_stmt = bb->stmts_used;
njn25e49d8e72002-09-23 09:36:25 +00003239
sewardj95448072004-11-22 20:19:51 +00003240 if (verboze) {
3241 VG_(printf)("bb->next = ");
3242 ppIRExpr(bb->next);
3243 VG_(printf)("\n\n");
3244 }
njn25e49d8e72002-09-23 09:36:25 +00003245
sewardj95448072004-11-22 20:19:51 +00003246 complainIfUndefined( &mce, bb->next );
njn25e49d8e72002-09-23 09:36:25 +00003247
sewardj95448072004-11-22 20:19:51 +00003248 if (verboze) {
3249 for (j = first_stmt; j < bb->stmts_used; j++) {
3250 VG_(printf)(" ");
3251 ppIRStmt(bb->stmts[j]);
3252 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00003253 }
sewardj95448072004-11-22 20:19:51 +00003254 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00003255 }
njn25e49d8e72002-09-23 09:36:25 +00003256
sewardj95448072004-11-22 20:19:51 +00003257 return bb;
3258}
njn25e49d8e72002-09-23 09:36:25 +00003259
3260/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00003261/*--- end mc_translate.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00003262/*--------------------------------------------------------------------*/