blob: f6f984b03173cf9a2068086d3f30e0b516e45443 [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
njn25cac76cb2002-09-23 11:21:57 +000032#include "mc_include.h"
njn25e49d8e72002-09-23 09:36:25 +000033
njn25e49d8e72002-09-23 09:36:25 +000034
sewardj95448072004-11-22 20:19:51 +000035/*------------------------------------------------------------*/
36/*--- Forward decls ---*/
37/*------------------------------------------------------------*/
38
39struct _MCEnv;
40
41static IRType shadowType ( IRType ty );
42static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
43
44
45/*------------------------------------------------------------*/
46/*--- Memcheck running state, and tmp management. ---*/
47/*------------------------------------------------------------*/
48
49/* Carries around state during memcheck instrumentation. */
50typedef
51 struct _MCEnv {
52 /* MODIFIED: the bb being constructed. IRStmts are added. */
53 IRBB* bb;
54
55 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
56 original temps to their current their current shadow temp.
57 Initially all entries are IRTemp_INVALID. Entries are added
58 lazily since many original temps are not used due to
59 optimisation prior to instrumentation. Note that floating
60 point original tmps are shadowed by integer tmps of the same
61 size, and Bit-typed original tmps are shadowed by the type
62 Ity_I8. See comment below. */
63 IRTemp* tmpMap;
64 Int n_originalTmps; /* for range checking */
65
sewardjd5204dc2004-12-31 01:16:11 +000066 /* MODIFIED: indicates whether "bogus" literals have so far been
67 found. Starts off False, and may change to True. */
68 Bool bogusLiterals;
69
sewardj95448072004-11-22 20:19:51 +000070 /* READONLY: the guest layout. This indicates which parts of
71 the guest state should be regarded as 'always defined'. */
72 VexGuestLayout* layout;
73 /* READONLY: the host word type. Needed for constructing
74 arguments of type 'HWord' to be passed to helper functions.
75 Ity_I32 or Ity_I64 only. */
76 IRType hWordTy;
77 }
78 MCEnv;
79
80/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
81 demand), as they are encountered. This is for two reasons.
82
83 (1) (less important reason): Many original tmps are unused due to
84 initial IR optimisation, and we do not want to spaces in tables
85 tracking them.
86
87 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
88 table indexed [0 .. n_types-1], which gives the current shadow for
89 each original tmp, or INVALID_IRTEMP if none is so far assigned.
90 It is necessary to support making multiple assignments to a shadow
91 -- specifically, after testing a shadow for definedness, it needs
92 to be made defined. But IR's SSA property disallows this.
93
94 (2) (more important reason): Therefore, when a shadow needs to get
95 a new value, a new temporary is created, the value is assigned to
96 that, and the tmpMap is updated to reflect the new binding.
97
98 A corollary is that if the tmpMap maps a given tmp to
99 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
100 there's a read-before-write error in the original tmps. The IR
101 sanity checker should catch all such anomalies, however.
njn25e49d8e72002-09-23 09:36:25 +0000102*/
sewardj95448072004-11-22 20:19:51 +0000103
104/* Find the tmp currently shadowing the given original tmp. If none
105 so far exists, allocate one. */
106static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
njn25e49d8e72002-09-23 09:36:25 +0000107{
sewardj95448072004-11-22 20:19:51 +0000108 tl_assert(orig < mce->n_originalTmps);
109 if (mce->tmpMap[orig] == IRTemp_INVALID) {
110 mce->tmpMap[orig]
111 = newIRTemp(mce->bb->tyenv,
112 shadowType(mce->bb->tyenv->types[orig]));
njn25e49d8e72002-09-23 09:36:25 +0000113 }
sewardj95448072004-11-22 20:19:51 +0000114 return mce->tmpMap[orig];
njn25e49d8e72002-09-23 09:36:25 +0000115}
116
sewardj95448072004-11-22 20:19:51 +0000117/* Allocate a new shadow for the given original tmp. This means any
118 previous shadow is abandoned. This is needed because it is
119 necessary to give a new value to a shadow once it has been tested
120 for undefinedness, but unfortunately IR's SSA property disallows
121 this. Instead we must abandon the old shadow, allocate a new one
122 and use that instead. */
123static void newShadowTmp ( MCEnv* mce, IRTemp orig )
njn25e49d8e72002-09-23 09:36:25 +0000124{
sewardj95448072004-11-22 20:19:51 +0000125 tl_assert(orig < mce->n_originalTmps);
126 mce->tmpMap[orig]
127 = newIRTemp(mce->bb->tyenv,
128 shadowType(mce->bb->tyenv->types[orig]));
129}
130
131
132/*------------------------------------------------------------*/
133/*--- IRAtoms -- a subset of IRExprs ---*/
134/*------------------------------------------------------------*/
135
136/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
sewardj710d6c22005-03-20 18:55:15 +0000137 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
sewardj95448072004-11-22 20:19:51 +0000138 input, most of this code deals in atoms. Usefully, a value atom
139 always has a V-value which is also an atom: constants are shadowed
140 by constants, and temps are shadowed by the corresponding shadow
141 temporary. */
142
143typedef IRExpr IRAtom;
144
145/* (used for sanity checks only): is this an atom which looks
146 like it's from original code? */
147static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
148{
149 if (a1->tag == Iex_Const)
150 return True;
151 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
152 return True;
153 return False;
154}
155
156/* (used for sanity checks only): is this an atom which looks
157 like it's from shadow code? */
158static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
159{
160 if (a1->tag == Iex_Const)
161 return True;
162 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
163 return True;
164 return False;
165}
166
167/* (used for sanity checks only): check that both args are atoms and
168 are identically-kinded. */
169static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
170{
171 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
172 return True;
173 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
174 return True;
175 return False;
176}
177
178
179/*------------------------------------------------------------*/
180/*--- Type management ---*/
181/*------------------------------------------------------------*/
182
183/* Shadow state is always accessed using integer types. This returns
184 an integer type with the same size (as per sizeofIRType) as the
185 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj3245c912004-12-10 14:58:26 +0000186 I64, V128. */
sewardj95448072004-11-22 20:19:51 +0000187
188static IRType shadowType ( IRType ty )
189{
190 switch (ty) {
191 case Ity_I1:
192 case Ity_I8:
193 case Ity_I16:
194 case Ity_I32:
sewardj3245c912004-12-10 14:58:26 +0000195 case Ity_I64: return ty;
196 case Ity_F32: return Ity_I32;
197 case Ity_F64: return Ity_I64;
198 case Ity_V128: return Ity_V128;
sewardj95448072004-11-22 20:19:51 +0000199 default: ppIRType(ty);
200 VG_(tool_panic)("memcheck:shadowType");
201 }
202}
203
204/* Produce a 'defined' value of the given shadow type. Should only be
205 supplied shadow types (Bit/I8/I16/I32/UI64). */
206static IRExpr* definedOfType ( IRType ty ) {
207 switch (ty) {
sewardj170ee212004-12-10 18:57:51 +0000208 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
209 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
210 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
211 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
212 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
213 case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
sewardj95448072004-11-22 20:19:51 +0000214 default: VG_(tool_panic)("memcheck:definedOfType");
njn25e49d8e72002-09-23 09:36:25 +0000215 }
216}
217
218
sewardj95448072004-11-22 20:19:51 +0000219/*------------------------------------------------------------*/
220/*--- Constructing IR fragments ---*/
221/*------------------------------------------------------------*/
222
223/* assign value to tmp */
224#define assign(_bb,_tmp,_expr) \
225 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
226
227/* add stmt to a bb */
228#define stmt(_bb,_stmt) \
229 addStmtToIRBB((_bb), (_stmt))
230
231/* build various kinds of expressions */
232#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
233#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
234#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
235#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
236#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
237#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
sewardj170ee212004-12-10 18:57:51 +0000238#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
sewardj95448072004-11-22 20:19:51 +0000239#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
240
241/* bind the given expression to a new temporary, and return the
242 temporary. This effectively converts an arbitrary expression into
243 an atom. */
244static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
245 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
246 assign(mce->bb, t, e);
247 return mkexpr(t);
248}
249
250
251/*------------------------------------------------------------*/
252/*--- Constructing definedness primitive ops ---*/
253/*------------------------------------------------------------*/
254
255/* --------- Defined-if-either-defined --------- */
256
257static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
258 tl_assert(isShadowAtom(mce,a1));
259 tl_assert(isShadowAtom(mce,a2));
260 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
261}
262
263static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
264 tl_assert(isShadowAtom(mce,a1));
265 tl_assert(isShadowAtom(mce,a2));
266 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
267}
268
269static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
270 tl_assert(isShadowAtom(mce,a1));
271 tl_assert(isShadowAtom(mce,a2));
272 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
273}
274
sewardj7010f6e2004-12-10 13:35:22 +0000275static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
276 tl_assert(isShadowAtom(mce,a1));
277 tl_assert(isShadowAtom(mce,a2));
278 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
279}
280
sewardj20d38f22005-02-07 23:50:18 +0000281static IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj170ee212004-12-10 18:57:51 +0000282 tl_assert(isShadowAtom(mce,a1));
283 tl_assert(isShadowAtom(mce,a2));
sewardj20d38f22005-02-07 23:50:18 +0000284 return assignNew(mce, Ity_V128, binop(Iop_AndV128, a1, a2));
sewardj170ee212004-12-10 18:57:51 +0000285}
286
sewardj95448072004-11-22 20:19:51 +0000287/* --------- Undefined-if-either-undefined --------- */
288
289static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
290 tl_assert(isShadowAtom(mce,a1));
291 tl_assert(isShadowAtom(mce,a2));
292 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
293}
294
295static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
296 tl_assert(isShadowAtom(mce,a1));
297 tl_assert(isShadowAtom(mce,a2));
298 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
299}
300
301static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
302 tl_assert(isShadowAtom(mce,a1));
303 tl_assert(isShadowAtom(mce,a2));
304 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
305}
306
307static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
308 tl_assert(isShadowAtom(mce,a1));
309 tl_assert(isShadowAtom(mce,a2));
310 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
311}
312
sewardj20d38f22005-02-07 23:50:18 +0000313static IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
sewardj3245c912004-12-10 14:58:26 +0000314 tl_assert(isShadowAtom(mce,a1));
315 tl_assert(isShadowAtom(mce,a2));
sewardj20d38f22005-02-07 23:50:18 +0000316 return assignNew(mce, Ity_V128, binop(Iop_OrV128, a1, a2));
sewardj3245c912004-12-10 14:58:26 +0000317}
318
sewardje50a1b12004-12-17 01:24:54 +0000319static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
sewardj95448072004-11-22 20:19:51 +0000320 switch (vty) {
sewardje50a1b12004-12-17 01:24:54 +0000321 case Ity_I8: return mkUifU8(mce, a1, a2);
sewardja1d93302004-12-12 16:45:06 +0000322 case Ity_I16: return mkUifU16(mce, a1, a2);
323 case Ity_I32: return mkUifU32(mce, a1, a2);
324 case Ity_I64: return mkUifU64(mce, a1, a2);
sewardj20d38f22005-02-07 23:50:18 +0000325 case Ity_V128: return mkUifUV128(mce, a1, a2);
sewardj95448072004-11-22 20:19:51 +0000326 default:
327 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
328 VG_(tool_panic)("memcheck:mkUifU");
njn25e49d8e72002-09-23 09:36:25 +0000329 }
330}
331
sewardj95448072004-11-22 20:19:51 +0000332/* --------- The Left-family of operations. --------- */
njn25e49d8e72002-09-23 09:36:25 +0000333
sewardj95448072004-11-22 20:19:51 +0000334static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
335 tl_assert(isShadowAtom(mce,a1));
336 /* It's safe to duplicate a1 since it's only an atom */
337 return assignNew(mce, Ity_I8,
338 binop(Iop_Or8, a1,
339 assignNew(mce, Ity_I8,
340 /* unop(Iop_Neg8, a1)))); */
341 binop(Iop_Sub8, mkU8(0), a1) )));
342}
343
344static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
345 tl_assert(isShadowAtom(mce,a1));
346 /* It's safe to duplicate a1 since it's only an atom */
347 return assignNew(mce, Ity_I16,
348 binop(Iop_Or16, a1,
349 assignNew(mce, Ity_I16,
350 /* unop(Iop_Neg16, a1)))); */
351 binop(Iop_Sub16, mkU16(0), a1) )));
352}
353
354static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
355 tl_assert(isShadowAtom(mce,a1));
356 /* It's safe to duplicate a1 since it's only an atom */
357 return assignNew(mce, Ity_I32,
358 binop(Iop_Or32, a1,
359 assignNew(mce, Ity_I32,
360 /* unop(Iop_Neg32, a1)))); */
361 binop(Iop_Sub32, mkU32(0), a1) )));
362}
363
sewardj681be302005-01-15 20:43:58 +0000364static IRAtom* mkLeft64 ( 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_I64,
368 binop(Iop_Or64, a1,
369 assignNew(mce, Ity_I64,
370 /* unop(Iop_Neg32, a1)))); */
371 binop(Iop_Sub64, mkU64(0), a1) )));
372}
373
sewardj95448072004-11-22 20:19:51 +0000374/* --------- 'Improvement' functions for AND/OR. --------- */
375
376/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
377 defined (0); all other -> undefined (1).
378*/
379static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
njn25e49d8e72002-09-23 09:36:25 +0000380{
sewardj95448072004-11-22 20:19:51 +0000381 tl_assert(isOriginalAtom(mce, data));
382 tl_assert(isShadowAtom(mce, vbits));
383 tl_assert(sameKindedAtoms(data, vbits));
384 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
385}
njn25e49d8e72002-09-23 09:36:25 +0000386
sewardj95448072004-11-22 20:19:51 +0000387static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
388{
389 tl_assert(isOriginalAtom(mce, data));
390 tl_assert(isShadowAtom(mce, vbits));
391 tl_assert(sameKindedAtoms(data, vbits));
392 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
393}
njn25e49d8e72002-09-23 09:36:25 +0000394
sewardj95448072004-11-22 20:19:51 +0000395static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
396{
397 tl_assert(isOriginalAtom(mce, data));
398 tl_assert(isShadowAtom(mce, vbits));
399 tl_assert(sameKindedAtoms(data, vbits));
400 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
401}
njn25e49d8e72002-09-23 09:36:25 +0000402
sewardj7010f6e2004-12-10 13:35:22 +0000403static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
404{
405 tl_assert(isOriginalAtom(mce, data));
406 tl_assert(isShadowAtom(mce, vbits));
407 tl_assert(sameKindedAtoms(data, vbits));
408 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
409}
410
sewardj20d38f22005-02-07 23:50:18 +0000411static IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj170ee212004-12-10 18:57:51 +0000412{
413 tl_assert(isOriginalAtom(mce, data));
414 tl_assert(isShadowAtom(mce, vbits));
415 tl_assert(sameKindedAtoms(data, vbits));
sewardj20d38f22005-02-07 23:50:18 +0000416 return assignNew(mce, Ity_V128, binop(Iop_OrV128, data, vbits));
sewardj170ee212004-12-10 18:57:51 +0000417}
418
sewardj95448072004-11-22 20:19:51 +0000419/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
420 defined (0); all other -> undefined (1).
421*/
422static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
423{
424 tl_assert(isOriginalAtom(mce, data));
425 tl_assert(isShadowAtom(mce, vbits));
426 tl_assert(sameKindedAtoms(data, vbits));
427 return assignNew(
428 mce, Ity_I8,
429 binop(Iop_Or8,
430 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
431 vbits) );
432}
njn25e49d8e72002-09-23 09:36:25 +0000433
sewardj95448072004-11-22 20:19:51 +0000434static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
435{
436 tl_assert(isOriginalAtom(mce, data));
437 tl_assert(isShadowAtom(mce, vbits));
438 tl_assert(sameKindedAtoms(data, vbits));
439 return assignNew(
440 mce, Ity_I16,
441 binop(Iop_Or16,
442 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
443 vbits) );
444}
njn25e49d8e72002-09-23 09:36:25 +0000445
sewardj95448072004-11-22 20:19:51 +0000446static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
447{
448 tl_assert(isOriginalAtom(mce, data));
449 tl_assert(isShadowAtom(mce, vbits));
450 tl_assert(sameKindedAtoms(data, vbits));
451 return assignNew(
452 mce, Ity_I32,
453 binop(Iop_Or32,
454 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
455 vbits) );
456}
457
sewardj7010f6e2004-12-10 13:35:22 +0000458static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
459{
460 tl_assert(isOriginalAtom(mce, data));
461 tl_assert(isShadowAtom(mce, vbits));
462 tl_assert(sameKindedAtoms(data, vbits));
463 return assignNew(
464 mce, Ity_I64,
465 binop(Iop_Or64,
466 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
467 vbits) );
468}
469
sewardj20d38f22005-02-07 23:50:18 +0000470static IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
sewardj170ee212004-12-10 18:57:51 +0000471{
472 tl_assert(isOriginalAtom(mce, data));
473 tl_assert(isShadowAtom(mce, vbits));
474 tl_assert(sameKindedAtoms(data, vbits));
475 return assignNew(
476 mce, Ity_V128,
sewardj20d38f22005-02-07 23:50:18 +0000477 binop(Iop_OrV128,
478 assignNew(mce, Ity_V128, unop(Iop_NotV128, data)),
sewardj170ee212004-12-10 18:57:51 +0000479 vbits) );
480}
481
sewardj95448072004-11-22 20:19:51 +0000482/* --------- Pessimising casts. --------- */
483
484static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
485{
sewardj7cf97ee2004-11-28 14:25:01 +0000486 IRType ty;
487 IRAtom* tmp1;
sewardj95448072004-11-22 20:19:51 +0000488 /* Note, dst_ty is a shadow type, not an original type. */
489 /* First of all, collapse vbits down to a single bit. */
490 tl_assert(isShadowAtom(mce,vbits));
sewardj7cf97ee2004-11-28 14:25:01 +0000491 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
492 tmp1 = NULL;
sewardj95448072004-11-22 20:19:51 +0000493 switch (ty) {
494 case Ity_I1:
495 tmp1 = vbits;
njn25e49d8e72002-09-23 09:36:25 +0000496 break;
sewardj95448072004-11-22 20:19:51 +0000497 case Ity_I8:
498 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
499 break;
500 case Ity_I16:
501 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
502 break;
503 case Ity_I32:
504 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
505 break;
506 case Ity_I64:
507 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
508 break;
509 default:
510 VG_(tool_panic)("mkPCastTo(1)");
511 }
512 tl_assert(tmp1);
513 /* Now widen up to the dst type. */
514 switch (dst_ty) {
515 case Ity_I1:
516 return tmp1;
517 case Ity_I8:
518 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
519 case Ity_I16:
520 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
521 case Ity_I32:
522 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
523 case Ity_I64:
524 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardja1d93302004-12-12 16:45:06 +0000525 case Ity_V128:
526 tmp1 = assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
sewardj20d38f22005-02-07 23:50:18 +0000527 tmp1 = assignNew(mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
sewardja1d93302004-12-12 16:45:06 +0000528 return tmp1;
sewardj95448072004-11-22 20:19:51 +0000529 default:
530 ppIRType(dst_ty);
531 VG_(tool_panic)("mkPCastTo(2)");
532 }
533}
534
sewardjd5204dc2004-12-31 01:16:11 +0000535/* --------- Accurate interpretation of CmpEQ/CmpNE. --------- */
536/*
537 Normally, we can do CmpEQ/CmpNE by doing UifU on the arguments, and
538 PCasting to Ity_U1. However, sometimes it is necessary to be more
539 accurate. The insight is that the result is defined if two
540 corresponding bits can be found, one from each argument, so that
541 both bits are defined but are different -- that makes EQ say "No"
542 and NE say "Yes". Hence, we compute an improvement term and DifD
543 it onto the "normal" (UifU) result.
544
545 The result is:
546
547 PCastTo<1> (
548 PCastTo<sz>( UifU<sz>(vxx, vyy) ) -- naive version
549 `DifD<sz>`
550 PCastTo<sz>( CmpEQ<sz>( vec, 1....1 ) ) -- improvement term
551 )
552 where
553 vec contains 0 (defined) bits where the corresponding arg bits
554 are defined but different, and 1 bits otherwise:
555
556 vec = UifU<sz>( vxx, vyy, Not<sz>(Xor<sz>( xx, yy )) )
557*/
558static IRAtom* expensiveCmpEQorNE ( MCEnv* mce,
559 IRType ty,
560 IRAtom* vxx, IRAtom* vyy,
561 IRAtom* xx, IRAtom* yy )
562{
563 IRAtom *naive, *vec, *vec_cmpd, *improved, *final_cast, *top;
564 IROp opDIFD, opUIFU, opXOR, opNOT, opCMP;
565
566 tl_assert(isShadowAtom(mce,vxx));
567 tl_assert(isShadowAtom(mce,vyy));
568 tl_assert(isOriginalAtom(mce,xx));
569 tl_assert(isOriginalAtom(mce,yy));
570 tl_assert(sameKindedAtoms(vxx,xx));
571 tl_assert(sameKindedAtoms(vyy,yy));
572
573 switch (ty) {
574 case Ity_I32:
575 opDIFD = Iop_And32;
576 opUIFU = Iop_Or32;
577 opNOT = Iop_Not32;
578 opXOR = Iop_Xor32;
579 opCMP = Iop_CmpEQ32;
580 top = mkU32(0xFFFFFFFF);
581 break;
582 default:
583 VG_(tool_panic)("expensiveCmpEQorNE");
584 }
585
586 naive
587 = mkPCastTo(mce,ty, assignNew(mce, ty, binop(opUIFU, vxx, vyy)));
588
589 vec
590 = assignNew(
591 mce,ty,
592 binop( opUIFU,
593 assignNew(mce,ty, binop(opUIFU, vxx, vyy)),
594 assignNew(
595 mce,ty,
596 unop( opNOT,
597 assignNew(mce,ty, binop(opXOR, xx, yy))))));
598
599 vec_cmpd
600 = mkPCastTo( mce,ty, assignNew(mce,Ity_I1, binop(opCMP, vec, top)));
601
602 improved
603 = assignNew( mce,ty, binop(opDIFD, naive, vec_cmpd) );
604
605 final_cast
606 = mkPCastTo( mce, Ity_I1, improved );
607
608 return final_cast;
609}
610
sewardj95448072004-11-22 20:19:51 +0000611
612/*------------------------------------------------------------*/
613/*--- Emit a test and complaint if something is undefined. ---*/
614/*------------------------------------------------------------*/
615
616/* Set the annotations on a dirty helper to indicate that the stack
617 pointer and instruction pointers might be read. This is the
618 behaviour of all 'emit-a-complaint' style functions we might
619 call. */
620
621static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
622 di->nFxState = 2;
623 di->fxState[0].fx = Ifx_Read;
624 di->fxState[0].offset = mce->layout->offset_SP;
625 di->fxState[0].size = mce->layout->sizeof_SP;
626 di->fxState[1].fx = Ifx_Read;
627 di->fxState[1].offset = mce->layout->offset_IP;
628 di->fxState[1].size = mce->layout->sizeof_IP;
629}
630
631
632/* Check the supplied **original** atom for undefinedness, and emit a
633 complaint if so. Once that happens, mark it as defined. This is
634 possible because the atom is either a tmp or literal. If it's a
635 tmp, it will be shadowed by a tmp, and so we can set the shadow to
636 be defined. In fact as mentioned above, we will have to allocate a
637 new tmp to carry the new 'defined' shadow value, and update the
638 original->tmp mapping accordingly; we cannot simply assign a new
639 value to an existing shadow tmp as this breaks SSAness -- resulting
640 in the post-instrumentation sanity checker spluttering in disapproval.
641*/
642static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
643{
sewardj7cf97ee2004-11-28 14:25:01 +0000644 IRAtom* vatom;
645 IRType ty;
646 Int sz;
647 IRDirty* di;
648 IRAtom* cond;
649
sewardj95448072004-11-22 20:19:51 +0000650 /* Since the original expression is atomic, there's no duplicated
651 work generated by making multiple V-expressions for it. So we
652 don't really care about the possibility that someone else may
653 also create a V-interpretion for it. */
654 tl_assert(isOriginalAtom(mce, atom));
sewardj7cf97ee2004-11-28 14:25:01 +0000655 vatom = expr2vbits( mce, atom );
sewardj95448072004-11-22 20:19:51 +0000656 tl_assert(isShadowAtom(mce, vatom));
657 tl_assert(sameKindedAtoms(atom, vatom));
658
sewardj7cf97ee2004-11-28 14:25:01 +0000659 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj95448072004-11-22 20:19:51 +0000660
661 /* sz is only used for constructing the error message */
sewardj7cf97ee2004-11-28 14:25:01 +0000662 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardj95448072004-11-22 20:19:51 +0000663
sewardj7cf97ee2004-11-28 14:25:01 +0000664 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardj95448072004-11-22 20:19:51 +0000665 /* cond will be 0 if all defined, and 1 if any not defined. */
666
sewardj95448072004-11-22 20:19:51 +0000667 switch (sz) {
668 case 0:
669 di = unsafeIRDirty_0_N( 0/*regparms*/,
670 "MC_(helperc_value_check0_fail)",
671 &MC_(helperc_value_check0_fail),
672 mkIRExprVec_0()
673 );
674 break;
675 case 1:
676 di = unsafeIRDirty_0_N( 0/*regparms*/,
677 "MC_(helperc_value_check1_fail)",
678 &MC_(helperc_value_check1_fail),
679 mkIRExprVec_0()
680 );
681 break;
682 case 4:
683 di = unsafeIRDirty_0_N( 0/*regparms*/,
684 "MC_(helperc_value_check4_fail)",
685 &MC_(helperc_value_check4_fail),
686 mkIRExprVec_0()
687 );
688 break;
689 default:
690 di = unsafeIRDirty_0_N( 1/*regparms*/,
691 "MC_(helperc_complain_undef)",
692 &MC_(helperc_complain_undef),
693 mkIRExprVec_1( mkIRExpr_HWord( sz ))
694 );
695 break;
696 }
697 di->guard = cond;
698 setHelperAnns( mce, di );
699 stmt( mce->bb, IRStmt_Dirty(di));
700
701 /* Set the shadow tmp to be defined. First, update the
702 orig->shadow tmp mapping to reflect the fact that this shadow is
703 getting a new value. */
sewardj710d6c22005-03-20 18:55:15 +0000704 tl_assert(isIRAtom(vatom));
sewardj95448072004-11-22 20:19:51 +0000705 /* sameKindedAtoms ... */
706 if (vatom->tag == Iex_Tmp) {
707 tl_assert(atom->tag == Iex_Tmp);
708 newShadowTmp(mce, atom->Iex.Tmp.tmp);
709 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
710 definedOfType(ty));
711 }
712}
713
714
715/*------------------------------------------------------------*/
716/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
717/*------------------------------------------------------------*/
718
719/* Examine the always-defined sections declared in layout to see if
720 the (offset,size) section is within one. Note, is is an error to
721 partially fall into such a region: (offset,size) should either be
722 completely in such a region or completely not-in such a region.
723*/
724static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
725{
726 Int minoffD, maxoffD, i;
727 Int minoff = offset;
728 Int maxoff = minoff + size - 1;
729 tl_assert((minoff & ~0xFFFF) == 0);
730 tl_assert((maxoff & ~0xFFFF) == 0);
731
732 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
733 minoffD = mce->layout->alwaysDefd[i].offset;
734 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
735 tl_assert((minoffD & ~0xFFFF) == 0);
736 tl_assert((maxoffD & ~0xFFFF) == 0);
737
738 if (maxoff < minoffD || maxoffD < minoff)
739 continue; /* no overlap */
740 if (minoff >= minoffD && maxoff <= maxoffD)
741 return True; /* completely contained in an always-defd section */
742
743 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
744 }
745 return False; /* could not find any containing section */
746}
747
748
749/* Generate into bb suitable actions to shadow this Put. If the state
750 slice is marked 'always defined', do nothing. Otherwise, write the
751 supplied V bits to the shadow state. We can pass in either an
752 original atom or a V-atom, but not both. In the former case the
753 relevant V-bits are then generated from the original.
754*/
755static
756void do_shadow_PUT ( MCEnv* mce, Int offset,
757 IRAtom* atom, IRAtom* vatom )
758{
sewardj7cf97ee2004-11-28 14:25:01 +0000759 IRType ty;
sewardj95448072004-11-22 20:19:51 +0000760 if (atom) {
761 tl_assert(!vatom);
762 tl_assert(isOriginalAtom(mce, atom));
763 vatom = expr2vbits( mce, atom );
764 } else {
765 tl_assert(vatom);
766 tl_assert(isShadowAtom(mce, vatom));
767 }
768
sewardj7cf97ee2004-11-28 14:25:01 +0000769 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj95448072004-11-22 20:19:51 +0000770 tl_assert(ty != Ity_I1);
771 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
772 /* later: no ... */
773 /* emit code to emit a complaint if any of the vbits are 1. */
774 /* complainIfUndefined(mce, atom); */
775 } else {
776 /* Do a plain shadow Put. */
777 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
778 }
779}
780
781
782/* Return an expression which contains the V bits corresponding to the
783 given GETI (passed in in pieces).
784*/
785static
786void do_shadow_PUTI ( MCEnv* mce,
787 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
788{
sewardj7cf97ee2004-11-28 14:25:01 +0000789 IRAtom* vatom;
790 IRType ty, tyS;
791 Int arrSize;;
792
sewardj95448072004-11-22 20:19:51 +0000793 tl_assert(isOriginalAtom(mce,atom));
sewardj7cf97ee2004-11-28 14:25:01 +0000794 vatom = expr2vbits( mce, atom );
sewardj95448072004-11-22 20:19:51 +0000795 tl_assert(sameKindedAtoms(atom, vatom));
sewardj7cf97ee2004-11-28 14:25:01 +0000796 ty = descr->elemTy;
797 tyS = shadowType(ty);
798 arrSize = descr->nElems * sizeofIRType(ty);
sewardj95448072004-11-22 20:19:51 +0000799 tl_assert(ty != Ity_I1);
800 tl_assert(isOriginalAtom(mce,ix));
801 complainIfUndefined(mce,ix);
802 if (isAlwaysDefd(mce, descr->base, arrSize)) {
803 /* later: no ... */
804 /* emit code to emit a complaint if any of the vbits are 1. */
805 /* complainIfUndefined(mce, atom); */
806 } else {
807 /* Do a cloned version of the Put that refers to the shadow
808 area. */
809 IRArray* new_descr
810 = mkIRArray( descr->base + mce->layout->total_sizeB,
811 tyS, descr->nElems);
812 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
813 }
814}
815
816
817/* Return an expression which contains the V bits corresponding to the
818 given GET (passed in in pieces).
819*/
820static
821IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
822{
823 IRType tyS = shadowType(ty);
824 tl_assert(ty != Ity_I1);
825 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
826 /* Always defined, return all zeroes of the relevant type */
827 return definedOfType(tyS);
828 } else {
829 /* return a cloned version of the Get that refers to the shadow
830 area. */
831 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
832 }
833}
834
835
836/* Return an expression which contains the V bits corresponding to the
837 given GETI (passed in in pieces).
838*/
839static
840IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
841{
842 IRType ty = descr->elemTy;
843 IRType tyS = shadowType(ty);
844 Int arrSize = descr->nElems * sizeofIRType(ty);
845 tl_assert(ty != Ity_I1);
846 tl_assert(isOriginalAtom(mce,ix));
847 complainIfUndefined(mce,ix);
848 if (isAlwaysDefd(mce, descr->base, arrSize)) {
849 /* Always defined, return all zeroes of the relevant type */
850 return definedOfType(tyS);
851 } else {
852 /* return a cloned version of the Get that refers to the shadow
853 area. */
854 IRArray* new_descr
855 = mkIRArray( descr->base + mce->layout->total_sizeB,
856 tyS, descr->nElems);
857 return IRExpr_GetI( new_descr, ix, bias );
858 }
859}
860
861
862/*------------------------------------------------------------*/
863/*--- Generating approximations for unknown operations, ---*/
864/*--- using lazy-propagate semantics ---*/
865/*------------------------------------------------------------*/
866
867/* Lazy propagation of undefinedness from two values, resulting in the
868 specified shadow type.
869*/
870static
871IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
872{
873 /* force everything via 32-bit intermediaries. */
874 IRAtom* at;
875 tl_assert(isShadowAtom(mce,va1));
876 tl_assert(isShadowAtom(mce,va2));
877 at = mkPCastTo(mce, Ity_I32, va1);
878 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
879 at = mkPCastTo(mce, finalVty, at);
880 return at;
881}
882
883
884/* Do the lazy propagation game from a null-terminated vector of
885 atoms. This is presumably the arguments to a helper call, so the
886 IRCallee info is also supplied in order that we can know which
887 arguments should be ignored (via the .mcx_mask field).
888*/
889static
890IRAtom* mkLazyN ( MCEnv* mce,
891 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
892{
893 Int i;
894 IRAtom* here;
895 IRAtom* curr = definedOfType(Ity_I32);
896 for (i = 0; exprvec[i]; i++) {
897 tl_assert(i < 32);
898 tl_assert(isOriginalAtom(mce, exprvec[i]));
899 /* Only take notice of this arg if the callee's mc-exclusion
900 mask does not say it is to be excluded. */
901 if (cee->mcx_mask & (1<<i)) {
902 /* the arg is to be excluded from definedness checking. Do
903 nothing. */
904 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
905 } else {
906 /* calculate the arg's definedness, and pessimistically merge
907 it in. */
908 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
909 curr = mkUifU32(mce, here, curr);
910 }
911 }
912 return mkPCastTo(mce, finalVtype, curr );
913}
914
915
916/*------------------------------------------------------------*/
917/*--- Generating expensive sequences for exact carry-chain ---*/
918/*--- propagation in add/sub and related operations. ---*/
919/*------------------------------------------------------------*/
920
921static
sewardjd5204dc2004-12-31 01:16:11 +0000922IRAtom* expensiveAddSub ( MCEnv* mce,
923 Bool add,
924 IRType ty,
925 IRAtom* qaa, IRAtom* qbb,
926 IRAtom* aa, IRAtom* bb )
sewardj95448072004-11-22 20:19:51 +0000927{
sewardj7cf97ee2004-11-28 14:25:01 +0000928 IRAtom *a_min, *b_min, *a_max, *b_max;
sewardjd5204dc2004-12-31 01:16:11 +0000929 IROp opAND, opOR, opXOR, opNOT, opADD, opSUB;
sewardj7cf97ee2004-11-28 14:25:01 +0000930
sewardj95448072004-11-22 20:19:51 +0000931 tl_assert(isShadowAtom(mce,qaa));
932 tl_assert(isShadowAtom(mce,qbb));
933 tl_assert(isOriginalAtom(mce,aa));
934 tl_assert(isOriginalAtom(mce,bb));
935 tl_assert(sameKindedAtoms(qaa,aa));
936 tl_assert(sameKindedAtoms(qbb,bb));
937
sewardjd5204dc2004-12-31 01:16:11 +0000938 switch (ty) {
939 case Ity_I32:
940 opAND = Iop_And32;
941 opOR = Iop_Or32;
942 opXOR = Iop_Xor32;
943 opNOT = Iop_Not32;
944 opADD = Iop_Add32;
945 opSUB = Iop_Sub32;
946 break;
947 default:
948 VG_(tool_panic)("expensiveAddSub");
949 }
sewardj95448072004-11-22 20:19:51 +0000950
951 // a_min = aa & ~qaa
952 a_min = assignNew(mce,ty,
953 binop(opAND, aa,
954 assignNew(mce,ty, unop(opNOT, qaa))));
955
956 // b_min = bb & ~qbb
957 b_min = assignNew(mce,ty,
958 binop(opAND, bb,
959 assignNew(mce,ty, unop(opNOT, qbb))));
960
961 // a_max = aa | qaa
962 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
963
964 // b_max = bb | qbb
965 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
966
sewardjd5204dc2004-12-31 01:16:11 +0000967 if (add) {
968 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
969 return
970 assignNew(mce,ty,
971 binop( opOR,
972 assignNew(mce,ty, binop(opOR, qaa, qbb)),
973 assignNew(mce,ty,
974 binop( opXOR,
975 assignNew(mce,ty, binop(opADD, a_min, b_min)),
976 assignNew(mce,ty, binop(opADD, a_max, b_max))
977 )
sewardj95448072004-11-22 20:19:51 +0000978 )
sewardjd5204dc2004-12-31 01:16:11 +0000979 )
980 );
981 } else {
982 // result = (qaa | qbb) | ((a_min - b_max) ^ (a_max + b_min))
983 return
984 assignNew(mce,ty,
985 binop( opOR,
986 assignNew(mce,ty, binop(opOR, qaa, qbb)),
987 assignNew(mce,ty,
988 binop( opXOR,
989 assignNew(mce,ty, binop(opSUB, a_min, b_max)),
990 assignNew(mce,ty, binop(opSUB, a_max, b_min))
991 )
992 )
993 )
994 );
995 }
996
sewardj95448072004-11-22 20:19:51 +0000997}
998
999
1000/*------------------------------------------------------------*/
sewardj3245c912004-12-10 14:58:26 +00001001/*--- Helpers for dealing with vector primops. ---*/
1002/*------------------------------------------------------------*/
1003
sewardja1d93302004-12-12 16:45:06 +00001004/* Vector pessimisation -- pessimise within each lane individually. */
1005
1006static IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1007{
1008 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1009}
1010
1011static IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1012{
1013 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1014}
1015
1016static IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1017{
1018 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1019}
1020
1021static IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1022{
1023 return assignNew(mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1024}
1025
sewardjacd2e912005-01-13 19:17:06 +00001026static IRAtom* mkPCast32x2 ( MCEnv* mce, IRAtom* at )
1027{
1028 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ32x2, at));
1029}
1030
1031static IRAtom* mkPCast16x4 ( MCEnv* mce, IRAtom* at )
1032{
1033 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ16x4, at));
1034}
1035
1036static IRAtom* mkPCast8x8 ( MCEnv* mce, IRAtom* at )
1037{
1038 return assignNew(mce, Ity_I64, unop(Iop_CmpNEZ8x8, at));
1039}
1040
sewardja1d93302004-12-12 16:45:06 +00001041
sewardj3245c912004-12-10 14:58:26 +00001042/* Here's a simple scheme capable of handling ops derived from SSE1
1043 code and while only generating ops that can be efficiently
1044 implemented in SSE1. */
1045
1046/* All-lanes versions are straightforward:
1047
sewardj20d38f22005-02-07 23:50:18 +00001048 binary32Fx4(x,y) ==> PCast32x4(UifUV128(x#,y#))
sewardj3245c912004-12-10 14:58:26 +00001049
1050 unary32Fx4(x,y) ==> PCast32x4(x#)
1051
1052 Lowest-lane-only versions are more complex:
1053
sewardj20d38f22005-02-07 23:50:18 +00001054 binary32F0x4(x,y) ==> SetV128lo32(
sewardj3245c912004-12-10 14:58:26 +00001055 x#,
sewardj20d38f22005-02-07 23:50:18 +00001056 PCast32(V128to32(UifUV128(x#,y#)))
sewardj3245c912004-12-10 14:58:26 +00001057 )
1058
1059 This is perhaps not so obvious. In particular, it's faster to
sewardj20d38f22005-02-07 23:50:18 +00001060 do a V128-bit UifU and then take the bottom 32 bits than the more
sewardj3245c912004-12-10 14:58:26 +00001061 obvious scheme of taking the bottom 32 bits of each operand
1062 and doing a 32-bit UifU. Basically since UifU is fast and
1063 chopping lanes off vector values is slow.
1064
1065 Finally:
1066
sewardj20d38f22005-02-07 23:50:18 +00001067 unary32F0x4(x) ==> SetV128lo32(
sewardj3245c912004-12-10 14:58:26 +00001068 x#,
sewardj20d38f22005-02-07 23:50:18 +00001069 PCast32(V128to32(x#))
sewardj3245c912004-12-10 14:58:26 +00001070 )
1071
1072 Where:
1073
1074 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
1075 PCast32x4(v#) = CmpNEZ32x4(v#)
1076*/
1077
1078static
1079IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1080{
1081 IRAtom* at;
1082 tl_assert(isShadowAtom(mce, vatomX));
1083 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001084 at = mkUifUV128(mce, vatomX, vatomY);
sewardja1d93302004-12-12 16:45:06 +00001085 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, at));
sewardj3245c912004-12-10 14:58:26 +00001086 return at;
1087}
1088
1089static
1090IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1091{
1092 IRAtom* at;
1093 tl_assert(isShadowAtom(mce, vatomX));
sewardja1d93302004-12-12 16:45:06 +00001094 at = assignNew(mce, Ity_V128, mkPCast32x4(mce, vatomX));
sewardj3245c912004-12-10 14:58:26 +00001095 return at;
1096}
1097
1098static
1099IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1100{
1101 IRAtom* at;
1102 tl_assert(isShadowAtom(mce, vatomX));
1103 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001104 at = mkUifUV128(mce, vatomX, vatomY);
1105 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, at));
sewardj3245c912004-12-10 14:58:26 +00001106 at = mkPCastTo(mce, Ity_I32, at);
sewardj20d38f22005-02-07 23:50:18 +00001107 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj3245c912004-12-10 14:58:26 +00001108 return at;
1109}
1110
1111static
1112IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1113{
1114 IRAtom* at;
1115 tl_assert(isShadowAtom(mce, vatomX));
sewardj20d38f22005-02-07 23:50:18 +00001116 at = assignNew(mce, Ity_I32, unop(Iop_V128to32, vatomX));
sewardj3245c912004-12-10 14:58:26 +00001117 at = mkPCastTo(mce, Ity_I32, at);
sewardj20d38f22005-02-07 23:50:18 +00001118 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
sewardj3245c912004-12-10 14:58:26 +00001119 return at;
1120}
1121
sewardj0b070592004-12-10 21:44:22 +00001122/* --- ... and ... 64Fx2 versions of the same ... --- */
1123
1124static
1125IRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1126{
1127 IRAtom* at;
1128 tl_assert(isShadowAtom(mce, vatomX));
1129 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001130 at = mkUifUV128(mce, vatomX, vatomY);
sewardja1d93302004-12-12 16:45:06 +00001131 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, at));
sewardj0b070592004-12-10 21:44:22 +00001132 return at;
1133}
1134
1135static
1136IRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1137{
1138 IRAtom* at;
1139 tl_assert(isShadowAtom(mce, vatomX));
sewardja1d93302004-12-12 16:45:06 +00001140 at = assignNew(mce, Ity_V128, mkPCast64x2(mce, vatomX));
sewardj0b070592004-12-10 21:44:22 +00001141 return at;
1142}
1143
1144static
1145IRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1146{
1147 IRAtom* at;
1148 tl_assert(isShadowAtom(mce, vatomX));
1149 tl_assert(isShadowAtom(mce, vatomY));
sewardj20d38f22005-02-07 23:50:18 +00001150 at = mkUifUV128(mce, vatomX, vatomY);
1151 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, at));
sewardj0b070592004-12-10 21:44:22 +00001152 at = mkPCastTo(mce, Ity_I64, at);
sewardj20d38f22005-02-07 23:50:18 +00001153 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj0b070592004-12-10 21:44:22 +00001154 return at;
1155}
1156
1157static
1158IRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1159{
1160 IRAtom* at;
1161 tl_assert(isShadowAtom(mce, vatomX));
sewardj20d38f22005-02-07 23:50:18 +00001162 at = assignNew(mce, Ity_I64, unop(Iop_V128to64, vatomX));
sewardj0b070592004-12-10 21:44:22 +00001163 at = mkPCastTo(mce, Ity_I64, at);
sewardj20d38f22005-02-07 23:50:18 +00001164 at = assignNew(mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
sewardj0b070592004-12-10 21:44:22 +00001165 return at;
1166}
1167
sewardja1d93302004-12-12 16:45:06 +00001168/* --- --- Vector saturated narrowing --- --- */
1169
1170/* This is quite subtle. What to do is simple:
1171
1172 Let the original narrowing op be QNarrowW{S,U}xN. Produce:
1173
1174 the-narrowing-op( PCastWxN(vatom1), PCastWxN(vatom2))
1175
1176 Why this is right is not so simple. Consider a lane in the args,
1177 vatom1 or 2, doesn't matter.
1178
1179 After the PCast, that lane is all 0s (defined) or all
1180 1s(undefined).
1181
1182 Both signed and unsigned saturating narrowing of all 0s produces
1183 all 0s, which is what we want.
1184
1185 The all-1s case is more complex. Unsigned narrowing interprets an
1186 all-1s input as the largest unsigned integer, and so produces all
1187 1s as a result since that is the largest unsigned value at the
1188 smaller width.
1189
1190 Signed narrowing interprets all 1s as -1. Fortunately, -1 narrows
1191 to -1, so we still wind up with all 1s at the smaller width.
1192
1193 So: In short, pessimise the args, then apply the original narrowing
1194 op.
1195*/
1196static
sewardj20d38f22005-02-07 23:50:18 +00001197IRAtom* vectorNarrowV128 ( MCEnv* mce, IROp narrow_op,
sewardja1d93302004-12-12 16:45:06 +00001198 IRAtom* vatom1, IRAtom* vatom2)
1199{
1200 IRAtom *at1, *at2, *at3;
1201 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1202 switch (narrow_op) {
1203 case Iop_QNarrow32Sx4: pcast = mkPCast32x4; break;
1204 case Iop_QNarrow16Sx8: pcast = mkPCast16x8; break;
1205 case Iop_QNarrow16Ux8: pcast = mkPCast16x8; break;
sewardj20d38f22005-02-07 23:50:18 +00001206 default: VG_(tool_panic)("vectorNarrowV128");
sewardja1d93302004-12-12 16:45:06 +00001207 }
1208 tl_assert(isShadowAtom(mce,vatom1));
1209 tl_assert(isShadowAtom(mce,vatom2));
1210 at1 = assignNew(mce, Ity_V128, pcast(mce, vatom1));
1211 at2 = assignNew(mce, Ity_V128, pcast(mce, vatom2));
1212 at3 = assignNew(mce, Ity_V128, binop(narrow_op, at1, at2));
1213 return at3;
1214}
1215
sewardjacd2e912005-01-13 19:17:06 +00001216static
1217IRAtom* vectorNarrow64 ( MCEnv* mce, IROp narrow_op,
1218 IRAtom* vatom1, IRAtom* vatom2)
1219{
1220 IRAtom *at1, *at2, *at3;
1221 IRAtom* (*pcast)( MCEnv*, IRAtom* );
1222 switch (narrow_op) {
1223 case Iop_QNarrow32Sx2: pcast = mkPCast32x2; break;
1224 case Iop_QNarrow16Sx4: pcast = mkPCast16x4; break;
1225 case Iop_QNarrow16Ux4: pcast = mkPCast16x4; break;
1226 default: VG_(tool_panic)("vectorNarrow64");
1227 }
1228 tl_assert(isShadowAtom(mce,vatom1));
1229 tl_assert(isShadowAtom(mce,vatom2));
1230 at1 = assignNew(mce, Ity_I64, pcast(mce, vatom1));
1231 at2 = assignNew(mce, Ity_I64, pcast(mce, vatom2));
1232 at3 = assignNew(mce, Ity_I64, binop(narrow_op, at1, at2));
1233 return at3;
1234}
1235
sewardja1d93302004-12-12 16:45:06 +00001236
1237/* --- --- Vector integer arithmetic --- --- */
1238
1239/* Simple ... UifU the args and per-lane pessimise the results. */
sewardjacd2e912005-01-13 19:17:06 +00001240
sewardj20d38f22005-02-07 23:50:18 +00001241/* --- V128-bit versions --- */
sewardjacd2e912005-01-13 19:17:06 +00001242
sewardja1d93302004-12-12 16:45:06 +00001243static
1244IRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1245{
1246 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001247 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001248 at = mkPCast8x16(mce, at);
1249 return at;
1250}
1251
1252static
1253IRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1254{
1255 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001256 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001257 at = mkPCast16x8(mce, at);
1258 return at;
1259}
1260
1261static
1262IRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1263{
1264 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001265 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001266 at = mkPCast32x4(mce, at);
1267 return at;
1268}
1269
1270static
1271IRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1272{
1273 IRAtom* at;
sewardj20d38f22005-02-07 23:50:18 +00001274 at = mkUifUV128(mce, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001275 at = mkPCast64x2(mce, at);
1276 return at;
1277}
sewardj3245c912004-12-10 14:58:26 +00001278
sewardjacd2e912005-01-13 19:17:06 +00001279/* --- 64-bit versions --- */
1280
1281static
1282IRAtom* binary8Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1283{
1284 IRAtom* at;
1285 at = mkUifU64(mce, vatom1, vatom2);
1286 at = mkPCast8x8(mce, at);
1287 return at;
1288}
1289
1290static
1291IRAtom* binary16Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1292{
1293 IRAtom* at;
1294 at = mkUifU64(mce, vatom1, vatom2);
1295 at = mkPCast16x4(mce, at);
1296 return at;
1297}
1298
1299static
1300IRAtom* binary32Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
1301{
1302 IRAtom* at;
1303 at = mkUifU64(mce, vatom1, vatom2);
1304 at = mkPCast32x2(mce, at);
1305 return at;
1306}
1307
sewardj3245c912004-12-10 14:58:26 +00001308
1309/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00001310/*--- Generate shadow values from all kinds of IRExprs. ---*/
1311/*------------------------------------------------------------*/
1312
1313static
1314IRAtom* expr2vbits_Binop ( MCEnv* mce,
1315 IROp op,
1316 IRAtom* atom1, IRAtom* atom2 )
1317{
1318 IRType and_or_ty;
1319 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1320 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1321 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1322
1323 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1324 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1325
1326 tl_assert(isOriginalAtom(mce,atom1));
1327 tl_assert(isOriginalAtom(mce,atom2));
1328 tl_assert(isShadowAtom(mce,vatom1));
1329 tl_assert(isShadowAtom(mce,vatom2));
1330 tl_assert(sameKindedAtoms(atom1,vatom1));
1331 tl_assert(sameKindedAtoms(atom2,vatom2));
1332 switch (op) {
1333
sewardjacd2e912005-01-13 19:17:06 +00001334 /* 64-bit SIMD */
1335
1336 case Iop_ShrN16x4:
1337 case Iop_ShrN32x2:
1338 case Iop_SarN16x4:
1339 case Iop_SarN32x2:
1340 case Iop_ShlN16x4:
1341 case Iop_ShlN32x2:
1342 /* Same scheme as with all other shifts. */
1343 complainIfUndefined(mce, atom2);
1344 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1345
1346 case Iop_QNarrow32Sx2:
1347 case Iop_QNarrow16Sx4:
1348 case Iop_QNarrow16Ux4:
1349 return vectorNarrow64(mce, op, vatom1, vatom2);
1350
1351 case Iop_Min8Ux8:
1352 case Iop_Max8Ux8:
1353 case Iop_Avg8Ux8:
1354 case Iop_QSub8Sx8:
1355 case Iop_QSub8Ux8:
1356 case Iop_Sub8x8:
1357 case Iop_CmpGT8Sx8:
1358 case Iop_CmpEQ8x8:
1359 case Iop_QAdd8Sx8:
1360 case Iop_QAdd8Ux8:
1361 case Iop_Add8x8:
1362 return binary8Ix8(mce, vatom1, vatom2);
1363
1364 case Iop_Min16Sx4:
1365 case Iop_Max16Sx4:
1366 case Iop_Avg16Ux4:
1367 case Iop_QSub16Ux4:
1368 case Iop_QSub16Sx4:
1369 case Iop_Sub16x4:
1370 case Iop_Mul16x4:
1371 case Iop_MulHi16Sx4:
1372 case Iop_MulHi16Ux4:
1373 case Iop_CmpGT16Sx4:
1374 case Iop_CmpEQ16x4:
1375 case Iop_QAdd16Sx4:
1376 case Iop_QAdd16Ux4:
1377 case Iop_Add16x4:
1378 return binary16Ix4(mce, vatom1, vatom2);
1379
1380 case Iop_Sub32x2:
1381 case Iop_CmpGT32Sx2:
1382 case Iop_CmpEQ32x2:
1383 case Iop_Add32x2:
1384 return binary32Ix2(mce, vatom1, vatom2);
1385
1386 /* 64-bit data-steering */
1387 case Iop_InterleaveLO32x2:
1388 case Iop_InterleaveLO16x4:
1389 case Iop_InterleaveLO8x8:
1390 case Iop_InterleaveHI32x2:
1391 case Iop_InterleaveHI16x4:
1392 case Iop_InterleaveHI8x8:
1393 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
1394
sewardj20d38f22005-02-07 23:50:18 +00001395 /* V128-bit SIMD */
sewardj0b070592004-12-10 21:44:22 +00001396
sewardja1d93302004-12-12 16:45:06 +00001397 case Iop_ShrN16x8:
1398 case Iop_ShrN32x4:
1399 case Iop_ShrN64x2:
1400 case Iop_SarN16x8:
1401 case Iop_SarN32x4:
1402 case Iop_ShlN16x8:
1403 case Iop_ShlN32x4:
1404 case Iop_ShlN64x2:
1405 /* Same scheme as with all other shifts. */
1406 complainIfUndefined(mce, atom2);
1407 return assignNew(mce, Ity_V128, binop(op, vatom1, atom2));
1408
1409 case Iop_QSub8Ux16:
1410 case Iop_QSub8Sx16:
1411 case Iop_Sub8x16:
1412 case Iop_Min8Ux16:
1413 case Iop_Max8Ux16:
1414 case Iop_CmpGT8Sx16:
1415 case Iop_CmpEQ8x16:
1416 case Iop_Avg8Ux16:
1417 case Iop_QAdd8Ux16:
1418 case Iop_QAdd8Sx16:
1419 case Iop_Add8x16:
1420 return binary8Ix16(mce, vatom1, vatom2);
1421
1422 case Iop_QSub16Ux8:
1423 case Iop_QSub16Sx8:
1424 case Iop_Sub16x8:
1425 case Iop_Mul16x8:
1426 case Iop_MulHi16Sx8:
1427 case Iop_MulHi16Ux8:
1428 case Iop_Min16Sx8:
1429 case Iop_Max16Sx8:
1430 case Iop_CmpGT16Sx8:
1431 case Iop_CmpEQ16x8:
1432 case Iop_Avg16Ux8:
1433 case Iop_QAdd16Ux8:
1434 case Iop_QAdd16Sx8:
1435 case Iop_Add16x8:
1436 return binary16Ix8(mce, vatom1, vatom2);
1437
1438 case Iop_Sub32x4:
1439 case Iop_CmpGT32Sx4:
1440 case Iop_CmpEQ32x4:
1441 case Iop_Add32x4:
1442 return binary32Ix4(mce, vatom1, vatom2);
1443
1444 case Iop_Sub64x2:
1445 case Iop_Add64x2:
1446 return binary64Ix2(mce, vatom1, vatom2);
1447
1448 case Iop_QNarrow32Sx4:
1449 case Iop_QNarrow16Sx8:
1450 case Iop_QNarrow16Ux8:
sewardj20d38f22005-02-07 23:50:18 +00001451 return vectorNarrowV128(mce, op, vatom1, vatom2);
sewardja1d93302004-12-12 16:45:06 +00001452
sewardj0b070592004-12-10 21:44:22 +00001453 case Iop_Sub64Fx2:
1454 case Iop_Mul64Fx2:
1455 case Iop_Min64Fx2:
1456 case Iop_Max64Fx2:
1457 case Iop_Div64Fx2:
1458 case Iop_CmpLT64Fx2:
1459 case Iop_CmpLE64Fx2:
1460 case Iop_CmpEQ64Fx2:
1461 case Iop_Add64Fx2:
1462 return binary64Fx2(mce, vatom1, vatom2);
1463
1464 case Iop_Sub64F0x2:
1465 case Iop_Mul64F0x2:
1466 case Iop_Min64F0x2:
1467 case Iop_Max64F0x2:
1468 case Iop_Div64F0x2:
1469 case Iop_CmpLT64F0x2:
1470 case Iop_CmpLE64F0x2:
1471 case Iop_CmpEQ64F0x2:
1472 case Iop_Add64F0x2:
1473 return binary64F0x2(mce, vatom1, vatom2);
1474
sewardj170ee212004-12-10 18:57:51 +00001475 case Iop_Sub32Fx4:
1476 case Iop_Mul32Fx4:
1477 case Iop_Min32Fx4:
1478 case Iop_Max32Fx4:
1479 case Iop_Div32Fx4:
1480 case Iop_CmpLT32Fx4:
1481 case Iop_CmpLE32Fx4:
1482 case Iop_CmpEQ32Fx4:
sewardj3245c912004-12-10 14:58:26 +00001483 case Iop_Add32Fx4:
1484 return binary32Fx4(mce, vatom1, vatom2);
1485
sewardj170ee212004-12-10 18:57:51 +00001486 case Iop_Sub32F0x4:
1487 case Iop_Mul32F0x4:
1488 case Iop_Min32F0x4:
1489 case Iop_Max32F0x4:
1490 case Iop_Div32F0x4:
1491 case Iop_CmpLT32F0x4:
1492 case Iop_CmpLE32F0x4:
1493 case Iop_CmpEQ32F0x4:
1494 case Iop_Add32F0x4:
1495 return binary32F0x4(mce, vatom1, vatom2);
1496
sewardj20d38f22005-02-07 23:50:18 +00001497 /* V128-bit data-steering */
1498 case Iop_SetV128lo32:
1499 case Iop_SetV128lo64:
1500 case Iop_64HLtoV128:
sewardja1d93302004-12-12 16:45:06 +00001501 case Iop_InterleaveLO64x2:
1502 case Iop_InterleaveLO32x4:
1503 case Iop_InterleaveLO16x8:
1504 case Iop_InterleaveLO8x16:
1505 case Iop_InterleaveHI64x2:
1506 case Iop_InterleaveHI32x4:
1507 case Iop_InterleaveHI16x8:
1508 case Iop_InterleaveHI8x16:
sewardj170ee212004-12-10 18:57:51 +00001509 return assignNew(mce, Ity_V128, binop(op, vatom1, vatom2));
1510
sewardj3245c912004-12-10 14:58:26 +00001511 /* Scalar floating point */
1512
sewardj95448072004-11-22 20:19:51 +00001513 case Iop_RoundF64:
1514 case Iop_F64toI64:
sewardje9e16d32004-12-10 13:17:55 +00001515 case Iop_I64toF64:
1516 /* First arg is I32 (rounding mode), second is F64 or I64
1517 (data). */
sewardj95448072004-11-22 20:19:51 +00001518 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1519
1520 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1521 /* Takes two F64 args. */
1522 case Iop_F64toI32:
sewardje9e16d32004-12-10 13:17:55 +00001523 case Iop_F64toF32:
sewardj95448072004-11-22 20:19:51 +00001524 /* First arg is I32 (rounding mode), second is F64 (data). */
1525 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1526
1527 case Iop_F64toI16:
1528 /* First arg is I32 (rounding mode), second is F64 (data). */
1529 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1530
1531 case Iop_ScaleF64:
1532 case Iop_Yl2xF64:
1533 case Iop_Yl2xp1F64:
1534 case Iop_PRemF64:
1535 case Iop_AtanF64:
1536 case Iop_AddF64:
1537 case Iop_DivF64:
1538 case Iop_SubF64:
1539 case Iop_MulF64:
1540 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1541
1542 case Iop_CmpF64:
1543 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1544
1545 /* non-FP after here */
1546
1547 case Iop_DivModU64to32:
1548 case Iop_DivModS64to32:
1549 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1550
1551 case Iop_16HLto32:
sewardj170ee212004-12-10 18:57:51 +00001552 return assignNew(mce, Ity_I32, binop(op, vatom1, vatom2));
sewardj95448072004-11-22 20:19:51 +00001553 case Iop_32HLto64:
sewardj170ee212004-12-10 18:57:51 +00001554 return assignNew(mce, Ity_I64, binop(op, vatom1, vatom2));
sewardj95448072004-11-22 20:19:51 +00001555
1556 case Iop_MullS32:
1557 case Iop_MullU32: {
1558 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1559 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1560 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1561 }
1562
1563 case Iop_MullS16:
1564 case Iop_MullU16: {
1565 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1566 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1567 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1568 }
1569
1570 case Iop_MullS8:
1571 case Iop_MullU8: {
1572 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1573 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1574 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1575 }
1576
1577 case Iop_Add32:
sewardjd5204dc2004-12-31 01:16:11 +00001578 if (mce->bogusLiterals)
1579 return expensiveAddSub(mce,True,Ity_I32,
1580 vatom1,vatom2, atom1,atom2);
1581 else
1582 goto cheap_AddSub32;
sewardj95448072004-11-22 20:19:51 +00001583 case Iop_Sub32:
sewardjd5204dc2004-12-31 01:16:11 +00001584 if (mce->bogusLiterals)
1585 return expensiveAddSub(mce,False,Ity_I32,
1586 vatom1,vatom2, atom1,atom2);
1587 else
1588 goto cheap_AddSub32;
1589
1590 cheap_AddSub32:
sewardj95448072004-11-22 20:19:51 +00001591 case Iop_Mul32:
1592 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1593
sewardj681be302005-01-15 20:43:58 +00001594 /* could do better: Add64, Sub64 */
1595 case Iop_Add64:
1596 case Iop_Sub64:
1597 return mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
1598
sewardj95448072004-11-22 20:19:51 +00001599 case Iop_Mul16:
1600 case Iop_Add16:
1601 case Iop_Sub16:
1602 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1603
1604 case Iop_Sub8:
1605 case Iop_Add8:
1606 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1607
sewardjd5204dc2004-12-31 01:16:11 +00001608 case Iop_CmpEQ32:
1609 if (mce->bogusLiterals)
1610 return expensiveCmpEQorNE(mce,Ity_I32, vatom1,vatom2, atom1,atom2 );
1611 else
1612 goto cheap_cmp32;
1613
1614 cheap_cmp32:
sewardj95448072004-11-22 20:19:51 +00001615 case Iop_CmpLE32S: case Iop_CmpLE32U:
1616 case Iop_CmpLT32U: case Iop_CmpLT32S:
sewardjd5204dc2004-12-31 01:16:11 +00001617 case Iop_CmpNE32:
sewardj95448072004-11-22 20:19:51 +00001618 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
1619
1620 case Iop_CmpEQ16: case Iop_CmpNE16:
1621 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
1622
1623 case Iop_CmpEQ8: case Iop_CmpNE8:
1624 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
1625
1626 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1627 /* Complain if the shift amount is undefined. Then simply
1628 shift the first arg's V bits by the real shift amount. */
1629 complainIfUndefined(mce, atom2);
1630 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1631
sewardjdb67f5f2004-12-14 01:15:31 +00001632 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
sewardj95448072004-11-22 20:19:51 +00001633 /* Same scheme as with 32-bit shifts. */
1634 complainIfUndefined(mce, atom2);
1635 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1636
1637 case Iop_Shl8: case Iop_Shr8:
1638 /* Same scheme as with 32-bit shifts. */
1639 complainIfUndefined(mce, atom2);
1640 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1641
1642 case Iop_Shl64: case Iop_Shr64:
1643 /* Same scheme as with 32-bit shifts. */
1644 complainIfUndefined(mce, atom2);
1645 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1646
sewardj20d38f22005-02-07 23:50:18 +00001647 case Iop_AndV128:
1648 uifu = mkUifUV128; difd = mkDifDV128;
1649 and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
sewardj7010f6e2004-12-10 13:35:22 +00001650 case Iop_And64:
1651 uifu = mkUifU64; difd = mkDifD64;
1652 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardj95448072004-11-22 20:19:51 +00001653 case Iop_And32:
1654 uifu = mkUifU32; difd = mkDifD32;
1655 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
1656 case Iop_And16:
1657 uifu = mkUifU16; difd = mkDifD16;
1658 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
1659 case Iop_And8:
1660 uifu = mkUifU8; difd = mkDifD8;
1661 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1662
sewardj20d38f22005-02-07 23:50:18 +00001663 case Iop_OrV128:
1664 uifu = mkUifUV128; difd = mkDifDV128;
1665 and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
sewardj7010f6e2004-12-10 13:35:22 +00001666 case Iop_Or64:
1667 uifu = mkUifU64; difd = mkDifD64;
1668 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardj95448072004-11-22 20:19:51 +00001669 case Iop_Or32:
1670 uifu = mkUifU32; difd = mkDifD32;
1671 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1672 case Iop_Or16:
1673 uifu = mkUifU16; difd = mkDifD16;
1674 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1675 case Iop_Or8:
1676 uifu = mkUifU8; difd = mkDifD8;
1677 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1678
1679 do_And_Or:
1680 return
1681 assignNew(
1682 mce,
1683 and_or_ty,
1684 difd(mce, uifu(mce, vatom1, vatom2),
1685 difd(mce, improve(mce, atom1, vatom1),
1686 improve(mce, atom2, vatom2) ) ) );
1687
1688 case Iop_Xor8:
1689 return mkUifU8(mce, vatom1, vatom2);
1690 case Iop_Xor16:
1691 return mkUifU16(mce, vatom1, vatom2);
1692 case Iop_Xor32:
1693 return mkUifU32(mce, vatom1, vatom2);
sewardj7010f6e2004-12-10 13:35:22 +00001694 case Iop_Xor64:
1695 return mkUifU64(mce, vatom1, vatom2);
sewardj20d38f22005-02-07 23:50:18 +00001696 case Iop_XorV128:
1697 return mkUifUV128(mce, vatom1, vatom2);
njn25e49d8e72002-09-23 09:36:25 +00001698
1699 default:
sewardj95448072004-11-22 20:19:51 +00001700 ppIROp(op);
1701 VG_(tool_panic)("memcheck:expr2vbits_Binop");
njn25e49d8e72002-09-23 09:36:25 +00001702 }
njn25e49d8e72002-09-23 09:36:25 +00001703}
1704
njn25e49d8e72002-09-23 09:36:25 +00001705
sewardj95448072004-11-22 20:19:51 +00001706static
1707IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1708{
1709 IRAtom* vatom = expr2vbits( mce, atom );
1710 tl_assert(isOriginalAtom(mce,atom));
1711 switch (op) {
1712
sewardj0b070592004-12-10 21:44:22 +00001713 case Iop_Sqrt64Fx2:
1714 return unary64Fx2(mce, vatom);
1715
1716 case Iop_Sqrt64F0x2:
1717 return unary64F0x2(mce, vatom);
1718
sewardj170ee212004-12-10 18:57:51 +00001719 case Iop_Sqrt32Fx4:
1720 case Iop_RSqrt32Fx4:
1721 case Iop_Recip32Fx4:
1722 return unary32Fx4(mce, vatom);
1723
1724 case Iop_Sqrt32F0x4:
1725 case Iop_RSqrt32F0x4:
1726 case Iop_Recip32F0x4:
1727 return unary32F0x4(mce, vatom);
1728
sewardj20d38f22005-02-07 23:50:18 +00001729 case Iop_32UtoV128:
1730 case Iop_64UtoV128:
sewardj170ee212004-12-10 18:57:51 +00001731 return assignNew(mce, Ity_V128, unop(op, vatom));
1732
sewardj95448072004-11-22 20:19:51 +00001733 case Iop_F32toF64:
1734 case Iop_I32toF64:
sewardj95448072004-11-22 20:19:51 +00001735 case Iop_NegF64:
1736 case Iop_SinF64:
1737 case Iop_CosF64:
1738 case Iop_TanF64:
1739 case Iop_SqrtF64:
1740 case Iop_AbsF64:
1741 case Iop_2xm1F64:
1742 return mkPCastTo(mce, Ity_I64, vatom);
1743
sewardj95448072004-11-22 20:19:51 +00001744 case Iop_Clz32:
1745 case Iop_Ctz32:
1746 return mkPCastTo(mce, Ity_I32, vatom);
1747
1748 case Iop_32Sto64:
1749 case Iop_32Uto64:
sewardj20d38f22005-02-07 23:50:18 +00001750 case Iop_V128to64:
1751 case Iop_V128HIto64:
sewardj95448072004-11-22 20:19:51 +00001752 return assignNew(mce, Ity_I64, unop(op, vatom));
1753
1754 case Iop_64to32:
1755 case Iop_64HIto32:
1756 case Iop_1Uto32:
1757 case Iop_8Uto32:
1758 case Iop_16Uto32:
1759 case Iop_16Sto32:
1760 case Iop_8Sto32:
1761 return assignNew(mce, Ity_I32, unop(op, vatom));
1762
1763 case Iop_8Sto16:
1764 case Iop_8Uto16:
1765 case Iop_32to16:
1766 case Iop_32HIto16:
1767 return assignNew(mce, Ity_I16, unop(op, vatom));
1768
1769 case Iop_1Uto8:
1770 case Iop_16to8:
1771 case Iop_32to8:
1772 return assignNew(mce, Ity_I8, unop(op, vatom));
1773
1774 case Iop_32to1:
1775 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
1776
1777 case Iop_ReinterpF64asI64:
1778 case Iop_ReinterpI64asF64:
sewardj0b070592004-12-10 21:44:22 +00001779 case Iop_ReinterpI32asF32:
sewardj20d38f22005-02-07 23:50:18 +00001780 case Iop_NotV128:
sewardj7010f6e2004-12-10 13:35:22 +00001781 case Iop_Not64:
sewardj95448072004-11-22 20:19:51 +00001782 case Iop_Not32:
1783 case Iop_Not16:
1784 case Iop_Not8:
1785 case Iop_Not1:
1786 return vatom;
sewardj7010f6e2004-12-10 13:35:22 +00001787
sewardj95448072004-11-22 20:19:51 +00001788 default:
1789 ppIROp(op);
1790 VG_(tool_panic)("memcheck:expr2vbits_Unop");
1791 }
1792}
1793
1794
sewardj170ee212004-12-10 18:57:51 +00001795/* Worker function; do not call directly. */
sewardj95448072004-11-22 20:19:51 +00001796static
sewardj170ee212004-12-10 18:57:51 +00001797IRAtom* expr2vbits_LDle_WRK ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardj95448072004-11-22 20:19:51 +00001798{
1799 void* helper;
1800 Char* hname;
1801 IRDirty* di;
1802 IRTemp datavbits;
1803 IRAtom* addrAct;
1804
1805 tl_assert(isOriginalAtom(mce,addr));
1806
1807 /* First, emit a definedness test for the address. This also sets
1808 the address (shadow) to 'defined' following the test. */
1809 complainIfUndefined( mce, addr );
1810
1811 /* Now cook up a call to the relevant helper function, to read the
1812 data V bits from shadow memory. */
1813 ty = shadowType(ty);
1814 switch (ty) {
1815 case Ity_I64: helper = &MC_(helperc_LOADV8);
1816 hname = "MC_(helperc_LOADV8)";
1817 break;
1818 case Ity_I32: helper = &MC_(helperc_LOADV4);
1819 hname = "MC_(helperc_LOADV4)";
1820 break;
1821 case Ity_I16: helper = &MC_(helperc_LOADV2);
1822 hname = "MC_(helperc_LOADV2)";
1823 break;
1824 case Ity_I8: helper = &MC_(helperc_LOADV1);
1825 hname = "MC_(helperc_LOADV1)";
1826 break;
1827 default: ppIRType(ty);
1828 VG_(tool_panic)("memcheck:do_shadow_LDle");
1829 }
1830
1831 /* Generate the actual address into addrAct. */
1832 if (bias == 0) {
1833 addrAct = addr;
1834 } else {
sewardj7cf97ee2004-11-28 14:25:01 +00001835 IROp mkAdd;
1836 IRAtom* eBias;
sewardj95448072004-11-22 20:19:51 +00001837 IRType tyAddr = mce->hWordTy;
1838 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj7cf97ee2004-11-28 14:25:01 +00001839 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1840 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj95448072004-11-22 20:19:51 +00001841 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1842 }
1843
1844 /* We need to have a place to park the V bits we're just about to
1845 read. */
1846 datavbits = newIRTemp(mce->bb->tyenv, ty);
1847 di = unsafeIRDirty_1_N( datavbits,
1848 1/*regparms*/, hname, helper,
1849 mkIRExprVec_1( addrAct ));
1850 setHelperAnns( mce, di );
1851 stmt( mce->bb, IRStmt_Dirty(di) );
1852
1853 return mkexpr(datavbits);
1854}
1855
1856
1857static
sewardj170ee212004-12-10 18:57:51 +00001858IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
1859{
1860 IRAtom *v64hi, *v64lo;
1861 switch (shadowType(ty)) {
1862 case Ity_I8:
1863 case Ity_I16:
1864 case Ity_I32:
1865 case Ity_I64:
1866 return expr2vbits_LDle_WRK(mce, ty, addr, bias);
1867 case Ity_V128:
1868 v64lo = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias);
1869 v64hi = expr2vbits_LDle_WRK(mce, Ity_I64, addr, bias+8);
1870 return assignNew( mce,
1871 Ity_V128,
sewardj20d38f22005-02-07 23:50:18 +00001872 binop(Iop_64HLtoV128, v64hi, v64lo));
sewardj170ee212004-12-10 18:57:51 +00001873 default:
1874 VG_(tool_panic)("expr2vbits_LDle");
1875 }
1876}
1877
1878
1879static
sewardj95448072004-11-22 20:19:51 +00001880IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
1881 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
1882{
1883 IRAtom *vbitsC, *vbits0, *vbitsX;
1884 IRType ty;
1885 /* Given Mux0X(cond,expr0,exprX), generate
1886 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
1887 That is, steer the V bits like the originals, but trash the
1888 result if the steering value is undefined. This gives
1889 lazy propagation. */
1890 tl_assert(isOriginalAtom(mce, cond));
1891 tl_assert(isOriginalAtom(mce, expr0));
1892 tl_assert(isOriginalAtom(mce, exprX));
1893
1894 vbitsC = expr2vbits(mce, cond);
1895 vbits0 = expr2vbits(mce, expr0);
1896 vbitsX = expr2vbits(mce, exprX);
1897 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
1898
1899 return
1900 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
1901 mkPCastTo(mce, ty, vbitsC) );
1902}
1903
1904/* --------- This is the main expression-handling function. --------- */
1905
1906static
1907IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
1908{
1909 switch (e->tag) {
1910
1911 case Iex_Get:
1912 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
1913
1914 case Iex_GetI:
1915 return shadow_GETI( mce, e->Iex.GetI.descr,
1916 e->Iex.GetI.ix, e->Iex.GetI.bias );
1917
1918 case Iex_Tmp:
1919 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
1920
1921 case Iex_Const:
1922 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
1923
1924 case Iex_Binop:
1925 return expr2vbits_Binop(
1926 mce,
1927 e->Iex.Binop.op,
1928 e->Iex.Binop.arg1, e->Iex.Binop.arg2
1929 );
1930
1931 case Iex_Unop:
1932 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
1933
1934 case Iex_LDle:
1935 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
1936 e->Iex.LDle.addr, 0/*addr bias*/ );
1937
1938 case Iex_CCall:
1939 return mkLazyN( mce, e->Iex.CCall.args,
1940 e->Iex.CCall.retty,
1941 e->Iex.CCall.cee );
1942
1943 case Iex_Mux0X:
1944 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
1945 e->Iex.Mux0X.exprX);
njn25e49d8e72002-09-23 09:36:25 +00001946
1947 default:
sewardj95448072004-11-22 20:19:51 +00001948 VG_(printf)("\n");
1949 ppIRExpr(e);
1950 VG_(printf)("\n");
1951 VG_(tool_panic)("memcheck: expr2vbits");
njn25e49d8e72002-09-23 09:36:25 +00001952 }
njn25e49d8e72002-09-23 09:36:25 +00001953}
1954
1955/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00001956/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
njn25e49d8e72002-09-23 09:36:25 +00001957/*------------------------------------------------------------*/
1958
sewardj95448072004-11-22 20:19:51 +00001959/* Widen a value to the host word size. */
njn25e49d8e72002-09-23 09:36:25 +00001960
1961static
sewardj95448072004-11-22 20:19:51 +00001962IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
njn25e49d8e72002-09-23 09:36:25 +00001963{
sewardj7cf97ee2004-11-28 14:25:01 +00001964 IRType ty, tyH;
1965
sewardj95448072004-11-22 20:19:51 +00001966 /* vatom is vbits-value and as such can only have a shadow type. */
1967 tl_assert(isShadowAtom(mce,vatom));
njn25e49d8e72002-09-23 09:36:25 +00001968
sewardj7cf97ee2004-11-28 14:25:01 +00001969 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
1970 tyH = mce->hWordTy;
njn25e49d8e72002-09-23 09:36:25 +00001971
sewardj95448072004-11-22 20:19:51 +00001972 if (tyH == Ity_I32) {
1973 switch (ty) {
1974 case Ity_I32: return vatom;
1975 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
1976 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
1977 default: goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00001978 }
sewardj95448072004-11-22 20:19:51 +00001979 } else {
1980 goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00001981 }
sewardj95448072004-11-22 20:19:51 +00001982 unhandled:
1983 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
1984 VG_(tool_panic)("zwidenToHostWord");
njn25e49d8e72002-09-23 09:36:25 +00001985}
1986
njn25e49d8e72002-09-23 09:36:25 +00001987
sewardj95448072004-11-22 20:19:51 +00001988/* Generate a shadow store. addr is always the original address atom.
1989 You can pass in either originals or V-bits for the data atom, but
1990 obviously not both. */
njn25e49d8e72002-09-23 09:36:25 +00001991
sewardj95448072004-11-22 20:19:51 +00001992static
1993void do_shadow_STle ( MCEnv* mce,
1994 IRAtom* addr, UInt bias,
1995 IRAtom* data, IRAtom* vdata )
njn25e49d8e72002-09-23 09:36:25 +00001996{
sewardj170ee212004-12-10 18:57:51 +00001997 IROp mkAdd;
1998 IRType ty, tyAddr;
1999 IRDirty *di, *diLo64, *diHi64;
2000 IRAtom *addrAct, *addrLo64, *addrHi64;
2001 IRAtom *vdataLo64, *vdataHi64;
2002 IRAtom *eBias, *eBias0, *eBias8;
sewardj95448072004-11-22 20:19:51 +00002003 void* helper = NULL;
2004 Char* hname = NULL;
sewardj170ee212004-12-10 18:57:51 +00002005
2006 tyAddr = mce->hWordTy;
2007 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
2008 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
2009
2010 di = diLo64 = diHi64 = NULL;
2011 eBias = eBias0 = eBias8 = NULL;
2012 addrAct = addrLo64 = addrHi64 = NULL;
2013 vdataLo64 = vdataHi64 = NULL;
njn25e49d8e72002-09-23 09:36:25 +00002014
sewardj95448072004-11-22 20:19:51 +00002015 if (data) {
2016 tl_assert(!vdata);
2017 tl_assert(isOriginalAtom(mce, data));
2018 tl_assert(bias == 0);
2019 vdata = expr2vbits( mce, data );
2020 } else {
2021 tl_assert(vdata);
2022 }
njn25e49d8e72002-09-23 09:36:25 +00002023
sewardj95448072004-11-22 20:19:51 +00002024 tl_assert(isOriginalAtom(mce,addr));
2025 tl_assert(isShadowAtom(mce,vdata));
njn25e49d8e72002-09-23 09:36:25 +00002026
sewardj95448072004-11-22 20:19:51 +00002027 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
njn25e49d8e72002-09-23 09:36:25 +00002028
sewardj95448072004-11-22 20:19:51 +00002029 /* First, emit a definedness test for the address. This also sets
2030 the address (shadow) to 'defined' following the test. */
2031 complainIfUndefined( mce, addr );
njn25e49d8e72002-09-23 09:36:25 +00002032
sewardj170ee212004-12-10 18:57:51 +00002033 /* Now decide which helper function to call to write the data V
2034 bits into shadow memory. */
sewardj95448072004-11-22 20:19:51 +00002035 switch (ty) {
sewardj170ee212004-12-10 18:57:51 +00002036 case Ity_V128: /* we'll use the helper twice */
sewardj95448072004-11-22 20:19:51 +00002037 case Ity_I64: helper = &MC_(helperc_STOREV8);
2038 hname = "MC_(helperc_STOREV8)";
2039 break;
2040 case Ity_I32: helper = &MC_(helperc_STOREV4);
2041 hname = "MC_(helperc_STOREV4)";
2042 break;
2043 case Ity_I16: helper = &MC_(helperc_STOREV2);
2044 hname = "MC_(helperc_STOREV2)";
2045 break;
2046 case Ity_I8: helper = &MC_(helperc_STOREV1);
2047 hname = "MC_(helperc_STOREV1)";
2048 break;
2049 default: VG_(tool_panic)("memcheck:do_shadow_STle");
2050 }
njn25e49d8e72002-09-23 09:36:25 +00002051
sewardj170ee212004-12-10 18:57:51 +00002052 if (ty == Ity_V128) {
2053
sewardj20d38f22005-02-07 23:50:18 +00002054 /* V128-bit case */
sewardj170ee212004-12-10 18:57:51 +00002055 /* See comment in next clause re 64-bit regparms */
2056 eBias0 = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2057 addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias0) );
sewardj20d38f22005-02-07 23:50:18 +00002058 vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata));
sewardj170ee212004-12-10 18:57:51 +00002059 diLo64 = unsafeIRDirty_0_N(
2060 1/*regparms*/, hname, helper,
2061 mkIRExprVec_2( addrLo64, vdataLo64 ));
2062
2063 eBias8 = tyAddr==Ity_I32 ? mkU32(bias+8) : mkU64(bias+8);
2064 addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias8) );
sewardj20d38f22005-02-07 23:50:18 +00002065 vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata));
sewardj170ee212004-12-10 18:57:51 +00002066 diHi64 = unsafeIRDirty_0_N(
2067 1/*regparms*/, hname, helper,
2068 mkIRExprVec_2( addrHi64, vdataHi64 ));
2069
2070 setHelperAnns( mce, diLo64 );
2071 setHelperAnns( mce, diHi64 );
2072 stmt( mce->bb, IRStmt_Dirty(diLo64) );
2073 stmt( mce->bb, IRStmt_Dirty(diHi64) );
2074
sewardj95448072004-11-22 20:19:51 +00002075 } else {
sewardj170ee212004-12-10 18:57:51 +00002076
2077 /* 8/16/32/64-bit cases */
2078 /* Generate the actual address into addrAct. */
2079 if (bias == 0) {
2080 addrAct = addr;
2081 } else {
2082 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
2083 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
2084 }
2085
2086 if (ty == Ity_I64) {
2087 /* We can't do this with regparm 2 on 32-bit platforms, since
2088 the back ends aren't clever enough to handle 64-bit
2089 regparm args. Therefore be different. */
2090 di = unsafeIRDirty_0_N(
2091 1/*regparms*/, hname, helper,
2092 mkIRExprVec_2( addrAct, vdata ));
2093 } else {
2094 di = unsafeIRDirty_0_N(
2095 2/*regparms*/, hname, helper,
2096 mkIRExprVec_2( addrAct,
2097 zwidenToHostWord( mce, vdata )));
2098 }
2099 setHelperAnns( mce, di );
2100 stmt( mce->bb, IRStmt_Dirty(di) );
sewardj95448072004-11-22 20:19:51 +00002101 }
njn25e49d8e72002-09-23 09:36:25 +00002102
sewardj95448072004-11-22 20:19:51 +00002103}
njn25e49d8e72002-09-23 09:36:25 +00002104
njn25e49d8e72002-09-23 09:36:25 +00002105
sewardj95448072004-11-22 20:19:51 +00002106/* Do lazy pessimistic propagation through a dirty helper call, by
2107 looking at the annotations on it. This is the most complex part of
2108 Memcheck. */
njn25e49d8e72002-09-23 09:36:25 +00002109
sewardj95448072004-11-22 20:19:51 +00002110static IRType szToITy ( Int n )
2111{
2112 switch (n) {
2113 case 1: return Ity_I8;
2114 case 2: return Ity_I16;
2115 case 4: return Ity_I32;
2116 case 8: return Ity_I64;
2117 default: VG_(tool_panic)("szToITy(memcheck)");
2118 }
2119}
njn25e49d8e72002-09-23 09:36:25 +00002120
sewardj95448072004-11-22 20:19:51 +00002121static
2122void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
2123{
sewardje9e16d32004-12-10 13:17:55 +00002124 Int i, n, offset, toDo, gSz, gOff;
sewardj7cf97ee2004-11-28 14:25:01 +00002125 IRAtom *src, *here, *curr;
sewardj95448072004-11-22 20:19:51 +00002126 IRType tyAddr, tySrc, tyDst;
2127 IRTemp dst;
njn25e49d8e72002-09-23 09:36:25 +00002128
sewardj95448072004-11-22 20:19:51 +00002129 /* First check the guard. */
2130 complainIfUndefined(mce, d->guard);
2131
2132 /* Now round up all inputs and PCast over them. */
sewardj7cf97ee2004-11-28 14:25:01 +00002133 curr = definedOfType(Ity_I32);
sewardj95448072004-11-22 20:19:51 +00002134
2135 /* Inputs: unmasked args */
2136 for (i = 0; d->args[i]; i++) {
2137 if (d->cee->mcx_mask & (1<<i)) {
2138 /* ignore this arg */
njn25e49d8e72002-09-23 09:36:25 +00002139 } else {
sewardj95448072004-11-22 20:19:51 +00002140 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
2141 curr = mkUifU32(mce, here, curr);
njn25e49d8e72002-09-23 09:36:25 +00002142 }
2143 }
sewardj95448072004-11-22 20:19:51 +00002144
2145 /* Inputs: guest state that we read. */
2146 for (i = 0; i < d->nFxState; i++) {
2147 tl_assert(d->fxState[i].fx != Ifx_None);
2148 if (d->fxState[i].fx == Ifx_Write)
2149 continue;
sewardja7203252004-11-26 19:17:47 +00002150
2151 /* Ignore any sections marked as 'always defined'. */
2152 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
sewardje9e16d32004-12-10 13:17:55 +00002153 if (0)
sewardja7203252004-11-26 19:17:47 +00002154 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
2155 d->fxState[i].offset, d->fxState[i].size );
2156 continue;
2157 }
2158
sewardj95448072004-11-22 20:19:51 +00002159 /* This state element is read or modified. So we need to
sewardje9e16d32004-12-10 13:17:55 +00002160 consider it. If larger than 8 bytes, deal with it in 8-byte
2161 chunks. */
2162 gSz = d->fxState[i].size;
2163 gOff = d->fxState[i].offset;
2164 tl_assert(gSz > 0);
2165 while (True) {
2166 if (gSz == 0) break;
2167 n = gSz <= 8 ? gSz : 8;
2168 /* update 'curr' with UifU of the state slice
2169 gOff .. gOff+n-1 */
2170 tySrc = szToITy( n );
2171 src = assignNew( mce, tySrc,
2172 shadow_GET(mce, gOff, tySrc ) );
2173 here = mkPCastTo( mce, Ity_I32, src );
2174 curr = mkUifU32(mce, here, curr);
2175 gSz -= n;
2176 gOff += n;
2177 }
2178
sewardj95448072004-11-22 20:19:51 +00002179 }
2180
2181 /* Inputs: memory. First set up some info needed regardless of
2182 whether we're doing reads or writes. */
2183 tyAddr = Ity_INVALID;
2184
2185 if (d->mFx != Ifx_None) {
2186 /* Because we may do multiple shadow loads/stores from the same
2187 base address, it's best to do a single test of its
2188 definedness right now. Post-instrumentation optimisation
2189 should remove all but this test. */
2190 tl_assert(d->mAddr);
2191 complainIfUndefined(mce, d->mAddr);
2192
2193 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
2194 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
2195 tl_assert(tyAddr == mce->hWordTy); /* not really right */
2196 }
2197
2198 /* Deal with memory inputs (reads or modifies) */
2199 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
2200 offset = 0;
2201 toDo = d->mSize;
2202 /* chew off 32-bit chunks */
2203 while (toDo >= 4) {
2204 here = mkPCastTo(
2205 mce, Ity_I32,
2206 expr2vbits_LDle ( mce, Ity_I32,
2207 d->mAddr, d->mSize - toDo )
2208 );
2209 curr = mkUifU32(mce, here, curr);
2210 toDo -= 4;
2211 }
2212 /* chew off 16-bit chunks */
2213 while (toDo >= 2) {
2214 here = mkPCastTo(
2215 mce, Ity_I32,
2216 expr2vbits_LDle ( mce, Ity_I16,
2217 d->mAddr, d->mSize - toDo )
2218 );
2219 curr = mkUifU32(mce, here, curr);
2220 toDo -= 2;
2221 }
2222 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
2223 }
2224
2225 /* Whew! So curr is a 32-bit V-value summarising pessimistically
2226 all the inputs to the helper. Now we need to re-distribute the
2227 results to all destinations. */
2228
2229 /* Outputs: the destination temporary, if there is one. */
2230 if (d->tmp != IRTemp_INVALID) {
2231 dst = findShadowTmp(mce, d->tmp);
2232 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
2233 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
2234 }
2235
2236 /* Outputs: guest state that we write or modify. */
2237 for (i = 0; i < d->nFxState; i++) {
2238 tl_assert(d->fxState[i].fx != Ifx_None);
2239 if (d->fxState[i].fx == Ifx_Read)
2240 continue;
sewardja7203252004-11-26 19:17:47 +00002241 /* Ignore any sections marked as 'always defined'. */
2242 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
2243 continue;
sewardje9e16d32004-12-10 13:17:55 +00002244 /* This state element is written or modified. So we need to
2245 consider it. If larger than 8 bytes, deal with it in 8-byte
2246 chunks. */
2247 gSz = d->fxState[i].size;
2248 gOff = d->fxState[i].offset;
2249 tl_assert(gSz > 0);
2250 while (True) {
2251 if (gSz == 0) break;
2252 n = gSz <= 8 ? gSz : 8;
2253 /* Write suitably-casted 'curr' to the state slice
2254 gOff .. gOff+n-1 */
2255 tyDst = szToITy( n );
2256 do_shadow_PUT( mce, gOff,
2257 NULL, /* original atom */
2258 mkPCastTo( mce, tyDst, curr ) );
2259 gSz -= n;
2260 gOff += n;
2261 }
sewardj95448072004-11-22 20:19:51 +00002262 }
2263
2264 /* Outputs: memory that we write or modify. */
2265 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
2266 offset = 0;
2267 toDo = d->mSize;
2268 /* chew off 32-bit chunks */
2269 while (toDo >= 4) {
2270 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2271 NULL, /* original data */
2272 mkPCastTo( mce, Ity_I32, curr ) );
2273 toDo -= 4;
2274 }
2275 /* chew off 16-bit chunks */
2276 while (toDo >= 2) {
2277 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
2278 NULL, /* original data */
2279 mkPCastTo( mce, Ity_I16, curr ) );
2280 toDo -= 2;
2281 }
2282 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
2283 }
2284
njn25e49d8e72002-09-23 09:36:25 +00002285}
2286
2287
sewardj95448072004-11-22 20:19:51 +00002288/*------------------------------------------------------------*/
2289/*--- Memcheck main ---*/
2290/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00002291
sewardj95448072004-11-22 20:19:51 +00002292static Bool isBogusAtom ( IRAtom* at )
njn25e49d8e72002-09-23 09:36:25 +00002293{
sewardj95448072004-11-22 20:19:51 +00002294 ULong n = 0;
2295 IRConst* con;
sewardj710d6c22005-03-20 18:55:15 +00002296 tl_assert(isIRAtom(at));
sewardj95448072004-11-22 20:19:51 +00002297 if (at->tag == Iex_Tmp)
2298 return False;
2299 tl_assert(at->tag == Iex_Const);
2300 con = at->Iex.Const.con;
2301 switch (con->tag) {
sewardjd5204dc2004-12-31 01:16:11 +00002302 case Ico_U1: return False;
2303 case Ico_U8: n = (ULong)con->Ico.U8; break;
2304 case Ico_U16: n = (ULong)con->Ico.U16; break;
2305 case Ico_U32: n = (ULong)con->Ico.U32; break;
2306 case Ico_U64: n = (ULong)con->Ico.U64; break;
2307 case Ico_F64: return False;
2308 case Ico_F64i: return False;
2309 case Ico_V128: return False;
sewardj95448072004-11-22 20:19:51 +00002310 default: ppIRExpr(at); tl_assert(0);
2311 }
2312 /* VG_(printf)("%llx\n", n); */
2313 return (n == 0xFEFEFEFF
sewardjd5204dc2004-12-31 01:16:11 +00002314 || n == 0x80808080 /*
2315 || n == 0x01010101
2316 || n == 0x01010100*/);
sewardj95448072004-11-22 20:19:51 +00002317}
njn25e49d8e72002-09-23 09:36:25 +00002318
sewardj95448072004-11-22 20:19:51 +00002319static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
2320{
sewardjd5204dc2004-12-31 01:16:11 +00002321 Int i;
2322 IRExpr* e;
2323 IRDirty* d;
sewardj95448072004-11-22 20:19:51 +00002324 switch (st->tag) {
2325 case Ist_Tmp:
2326 e = st->Ist.Tmp.data;
2327 switch (e->tag) {
2328 case Iex_Get:
2329 case Iex_Tmp:
2330 return False;
sewardjd5204dc2004-12-31 01:16:11 +00002331 case Iex_Const:
2332 return isBogusAtom(e);
sewardj95448072004-11-22 20:19:51 +00002333 case Iex_Unop:
2334 return isBogusAtom(e->Iex.Unop.arg);
sewardjd5204dc2004-12-31 01:16:11 +00002335 case Iex_GetI:
2336 return isBogusAtom(e->Iex.GetI.ix);
sewardj95448072004-11-22 20:19:51 +00002337 case Iex_Binop:
2338 return isBogusAtom(e->Iex.Binop.arg1)
2339 || isBogusAtom(e->Iex.Binop.arg2);
2340 case Iex_Mux0X:
2341 return isBogusAtom(e->Iex.Mux0X.cond)
2342 || isBogusAtom(e->Iex.Mux0X.expr0)
2343 || isBogusAtom(e->Iex.Mux0X.exprX);
2344 case Iex_LDle:
2345 return isBogusAtom(e->Iex.LDle.addr);
2346 case Iex_CCall:
2347 for (i = 0; e->Iex.CCall.args[i]; i++)
2348 if (isBogusAtom(e->Iex.CCall.args[i]))
2349 return True;
2350 return False;
2351 default:
2352 goto unhandled;
2353 }
sewardjd5204dc2004-12-31 01:16:11 +00002354 case Ist_Dirty:
2355 d = st->Ist.Dirty.details;
2356 for (i = 0; d->args[i]; i++)
2357 if (isBogusAtom(d->args[i]))
2358 return True;
2359 if (d->guard && isBogusAtom(d->guard))
2360 return True;
2361 if (d->mAddr && isBogusAtom(d->mAddr))
2362 return True;
2363 return False;
sewardj95448072004-11-22 20:19:51 +00002364 case Ist_Put:
2365 return isBogusAtom(st->Ist.Put.data);
sewardjd5204dc2004-12-31 01:16:11 +00002366 case Ist_PutI:
2367 return isBogusAtom(st->Ist.PutI.ix)
2368 || isBogusAtom(st->Ist.PutI.data);
sewardj95448072004-11-22 20:19:51 +00002369 case Ist_STle:
2370 return isBogusAtom(st->Ist.STle.addr)
2371 || isBogusAtom(st->Ist.STle.data);
2372 case Ist_Exit:
sewardjd5204dc2004-12-31 01:16:11 +00002373 return isBogusAtom(st->Ist.Exit.guard);
sewardj21dc3452005-03-21 00:27:41 +00002374 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00002375 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00002376 case Ist_MFence:
2377 return False;
sewardj95448072004-11-22 20:19:51 +00002378 default:
2379 unhandled:
2380 ppIRStmt(st);
2381 VG_(tool_panic)("hasBogusLiterals");
2382 }
2383}
njn25e49d8e72002-09-23 09:36:25 +00002384
njn25e49d8e72002-09-23 09:36:25 +00002385
sewardjd54babf2005-03-21 00:55:49 +00002386IRBB* TL_(instrument) ( IRBB* bb_in, VexGuestLayout* layout,
2387 IRType gWordTy, IRType hWordTy )
sewardj95448072004-11-22 20:19:51 +00002388{
2389 Bool verboze = False; //True;
njn25e49d8e72002-09-23 09:36:25 +00002390
sewardjd5204dc2004-12-31 01:16:11 +00002391 Int i, j, first_stmt;
sewardj95448072004-11-22 20:19:51 +00002392 IRStmt* st;
sewardjd5204dc2004-12-31 01:16:11 +00002393 MCEnv mce;
sewardjd54babf2005-03-21 00:55:49 +00002394 IRBB* bb;
2395
2396 if (gWordTy != hWordTy) {
2397 /* We don't currently support this case. */
2398 VG_(tool_panic)("host/guest word size mismatch");
2399 }
njn25e49d8e72002-09-23 09:36:25 +00002400
sewardj95448072004-11-22 20:19:51 +00002401 /* Set up BB */
sewardjd54babf2005-03-21 00:55:49 +00002402 bb = emptyIRBB();
sewardj95448072004-11-22 20:19:51 +00002403 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
2404 bb->next = dopyIRExpr(bb_in->next);
2405 bb->jumpkind = bb_in->jumpkind;
njn25e49d8e72002-09-23 09:36:25 +00002406
sewardj95448072004-11-22 20:19:51 +00002407 /* Set up the running environment. Only .bb is modified as we go
2408 along. */
2409 mce.bb = bb;
2410 mce.layout = layout;
2411 mce.n_originalTmps = bb->tyenv->types_used;
2412 mce.hWordTy = hWordTy;
sewardjd5204dc2004-12-31 01:16:11 +00002413 mce.bogusLiterals = False;
sewardj95448072004-11-22 20:19:51 +00002414 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
2415 for (i = 0; i < mce.n_originalTmps; i++)
2416 mce.tmpMap[i] = IRTemp_INVALID;
2417
2418 /* Iterate over the stmts. */
2419
2420 for (i = 0; i < bb_in->stmts_used; i++) {
2421 st = bb_in->stmts[i];
sewardj21dc3452005-03-21 00:27:41 +00002422 tl_assert(st);
sewardj95448072004-11-22 20:19:51 +00002423
2424 tl_assert(isFlatIRStmt(st));
2425
sewardjd5204dc2004-12-31 01:16:11 +00002426 if (!mce.bogusLiterals) {
2427 mce.bogusLiterals = checkForBogusLiterals(st);
2428 if (0&& mce.bogusLiterals) {
sewardj95448072004-11-22 20:19:51 +00002429 VG_(printf)("bogus: ");
2430 ppIRStmt(st);
2431 VG_(printf)("\n");
2432 }
2433 }
sewardjd5204dc2004-12-31 01:16:11 +00002434
sewardj95448072004-11-22 20:19:51 +00002435 first_stmt = bb->stmts_used;
2436
2437 if (verboze) {
2438 ppIRStmt(st);
2439 VG_(printf)("\n\n");
2440 }
2441
sewardj29faa502005-03-16 18:20:21 +00002442 /* Generate instrumentation code for each stmt ... */
2443
sewardj95448072004-11-22 20:19:51 +00002444 switch (st->tag) {
2445
2446 case Ist_Tmp:
2447 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
2448 expr2vbits( &mce, st->Ist.Tmp.data) );
njn25e49d8e72002-09-23 09:36:25 +00002449 break;
2450
sewardj95448072004-11-22 20:19:51 +00002451 case Ist_Put:
2452 do_shadow_PUT( &mce,
2453 st->Ist.Put.offset,
2454 st->Ist.Put.data,
2455 NULL /* shadow atom */ );
njn25e49d8e72002-09-23 09:36:25 +00002456 break;
2457
sewardj95448072004-11-22 20:19:51 +00002458 case Ist_PutI:
2459 do_shadow_PUTI( &mce,
2460 st->Ist.PutI.descr,
2461 st->Ist.PutI.ix,
2462 st->Ist.PutI.bias,
2463 st->Ist.PutI.data );
njn25e49d8e72002-09-23 09:36:25 +00002464 break;
2465
sewardj95448072004-11-22 20:19:51 +00002466 case Ist_STle:
2467 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
2468 st->Ist.STle.data,
2469 NULL /* shadow data */ );
njn25e49d8e72002-09-23 09:36:25 +00002470 break;
2471
sewardj95448072004-11-22 20:19:51 +00002472 case Ist_Exit:
sewardjd5204dc2004-12-31 01:16:11 +00002473 complainIfUndefined( &mce, st->Ist.Exit.guard );
njn25e49d8e72002-09-23 09:36:25 +00002474 break;
2475
sewardj21dc3452005-03-21 00:27:41 +00002476 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00002477 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00002478 case Ist_MFence:
2479 break;
2480
sewardj95448072004-11-22 20:19:51 +00002481 case Ist_Dirty:
2482 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
njn25e49d8e72002-09-23 09:36:25 +00002483 break;
2484
2485 default:
sewardj95448072004-11-22 20:19:51 +00002486 VG_(printf)("\n");
2487 ppIRStmt(st);
2488 VG_(printf)("\n");
2489 VG_(tool_panic)("memcheck: unhandled IRStmt");
2490
2491 } /* switch (st->tag) */
2492
2493 if (verboze) {
2494 for (j = first_stmt; j < bb->stmts_used; j++) {
2495 VG_(printf)(" ");
2496 ppIRStmt(bb->stmts[j]);
2497 VG_(printf)("\n");
2498 }
2499 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00002500 }
sewardj95448072004-11-22 20:19:51 +00002501
sewardj29faa502005-03-16 18:20:21 +00002502 /* ... and finally copy the stmt itself to the output. */
sewardj95448072004-11-22 20:19:51 +00002503 addStmtToIRBB(bb, st);
2504
njn25e49d8e72002-09-23 09:36:25 +00002505 }
njn25e49d8e72002-09-23 09:36:25 +00002506
sewardj95448072004-11-22 20:19:51 +00002507 /* Now we need to complain if the jump target is undefined. */
2508 first_stmt = bb->stmts_used;
njn25e49d8e72002-09-23 09:36:25 +00002509
sewardj95448072004-11-22 20:19:51 +00002510 if (verboze) {
2511 VG_(printf)("bb->next = ");
2512 ppIRExpr(bb->next);
2513 VG_(printf)("\n\n");
2514 }
njn25e49d8e72002-09-23 09:36:25 +00002515
sewardj95448072004-11-22 20:19:51 +00002516 complainIfUndefined( &mce, bb->next );
njn25e49d8e72002-09-23 09:36:25 +00002517
sewardj95448072004-11-22 20:19:51 +00002518 if (verboze) {
2519 for (j = first_stmt; j < bb->stmts_used; j++) {
2520 VG_(printf)(" ");
2521 ppIRStmt(bb->stmts[j]);
2522 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00002523 }
sewardj95448072004-11-22 20:19:51 +00002524 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00002525 }
njn25e49d8e72002-09-23 09:36:25 +00002526
sewardj95448072004-11-22 20:19:51 +00002527 return bb;
2528}
njn25e49d8e72002-09-23 09:36:25 +00002529
2530/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00002531/*--- end mc_translate.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00002532/*--------------------------------------------------------------------*/