blob: 79150df6cb269eb9e73fd3ad44d1b34755f8993e [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
nethercotebb1c9912004-01-04 16:43:23 +000011 Copyright (C) 2000-2004 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
66 /* READONLY: the guest layout. This indicates which parts of
67 the guest state should be regarded as 'always defined'. */
68 VexGuestLayout* layout;
69 /* READONLY: the host word type. Needed for constructing
70 arguments of type 'HWord' to be passed to helper functions.
71 Ity_I32 or Ity_I64 only. */
72 IRType hWordTy;
73 }
74 MCEnv;
75
76/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
77 demand), as they are encountered. This is for two reasons.
78
79 (1) (less important reason): Many original tmps are unused due to
80 initial IR optimisation, and we do not want to spaces in tables
81 tracking them.
82
83 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
84 table indexed [0 .. n_types-1], which gives the current shadow for
85 each original tmp, or INVALID_IRTEMP if none is so far assigned.
86 It is necessary to support making multiple assignments to a shadow
87 -- specifically, after testing a shadow for definedness, it needs
88 to be made defined. But IR's SSA property disallows this.
89
90 (2) (more important reason): Therefore, when a shadow needs to get
91 a new value, a new temporary is created, the value is assigned to
92 that, and the tmpMap is updated to reflect the new binding.
93
94 A corollary is that if the tmpMap maps a given tmp to
95 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
96 there's a read-before-write error in the original tmps. The IR
97 sanity checker should catch all such anomalies, however.
njn25e49d8e72002-09-23 09:36:25 +000098*/
sewardj95448072004-11-22 20:19:51 +000099
100/* Find the tmp currently shadowing the given original tmp. If none
101 so far exists, allocate one. */
102static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
njn25e49d8e72002-09-23 09:36:25 +0000103{
sewardj95448072004-11-22 20:19:51 +0000104 tl_assert(orig < mce->n_originalTmps);
105 if (mce->tmpMap[orig] == IRTemp_INVALID) {
106 mce->tmpMap[orig]
107 = newIRTemp(mce->bb->tyenv,
108 shadowType(mce->bb->tyenv->types[orig]));
njn25e49d8e72002-09-23 09:36:25 +0000109 }
sewardj95448072004-11-22 20:19:51 +0000110 return mce->tmpMap[orig];
njn25e49d8e72002-09-23 09:36:25 +0000111}
112
sewardj95448072004-11-22 20:19:51 +0000113/* Allocate a new shadow for the given original tmp. This means any
114 previous shadow is abandoned. This is needed because it is
115 necessary to give a new value to a shadow once it has been tested
116 for undefinedness, but unfortunately IR's SSA property disallows
117 this. Instead we must abandon the old shadow, allocate a new one
118 and use that instead. */
119static void newShadowTmp ( MCEnv* mce, IRTemp orig )
njn25e49d8e72002-09-23 09:36:25 +0000120{
sewardj95448072004-11-22 20:19:51 +0000121 tl_assert(orig < mce->n_originalTmps);
122 mce->tmpMap[orig]
123 = newIRTemp(mce->bb->tyenv,
124 shadowType(mce->bb->tyenv->types[orig]));
125}
126
127
128/*------------------------------------------------------------*/
129/*--- IRAtoms -- a subset of IRExprs ---*/
130/*------------------------------------------------------------*/
131
132/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
133 isAtom() in libvex_ir.h. Because this instrumenter expects flat
134 input, most of this code deals in atoms. Usefully, a value atom
135 always has a V-value which is also an atom: constants are shadowed
136 by constants, and temps are shadowed by the corresponding shadow
137 temporary. */
138
139typedef IRExpr IRAtom;
140
141/* (used for sanity checks only): is this an atom which looks
142 like it's from original code? */
143static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
144{
145 if (a1->tag == Iex_Const)
146 return True;
147 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
148 return True;
149 return False;
150}
151
152/* (used for sanity checks only): is this an atom which looks
153 like it's from shadow code? */
154static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
155{
156 if (a1->tag == Iex_Const)
157 return True;
158 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
159 return True;
160 return False;
161}
162
163/* (used for sanity checks only): check that both args are atoms and
164 are identically-kinded. */
165static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
166{
167 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
168 return True;
169 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
170 return True;
171 return False;
172}
173
174
175/*------------------------------------------------------------*/
176/*--- Type management ---*/
177/*------------------------------------------------------------*/
178
179/* Shadow state is always accessed using integer types. This returns
180 an integer type with the same size (as per sizeofIRType) as the
181 given type. The only valid shadow types are Bit, I8, I16, I32,
sewardj3245c912004-12-10 14:58:26 +0000182 I64, V128. */
sewardj95448072004-11-22 20:19:51 +0000183
184static IRType shadowType ( IRType ty )
185{
186 switch (ty) {
187 case Ity_I1:
188 case Ity_I8:
189 case Ity_I16:
190 case Ity_I32:
sewardj3245c912004-12-10 14:58:26 +0000191 case Ity_I64: return ty;
192 case Ity_F32: return Ity_I32;
193 case Ity_F64: return Ity_I64;
194 case Ity_V128: return Ity_V128;
sewardj95448072004-11-22 20:19:51 +0000195 default: ppIRType(ty);
196 VG_(tool_panic)("memcheck:shadowType");
197 }
198}
199
200/* Produce a 'defined' value of the given shadow type. Should only be
201 supplied shadow types (Bit/I8/I16/I32/UI64). */
202static IRExpr* definedOfType ( IRType ty ) {
203 switch (ty) {
204 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
205 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
206 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
207 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
208 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
209 default: VG_(tool_panic)("memcheck:definedOfType");
njn25e49d8e72002-09-23 09:36:25 +0000210 }
211}
212
213
sewardj95448072004-11-22 20:19:51 +0000214/*------------------------------------------------------------*/
215/*--- Constructing IR fragments ---*/
216/*------------------------------------------------------------*/
217
218/* assign value to tmp */
219#define assign(_bb,_tmp,_expr) \
220 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
221
222/* add stmt to a bb */
223#define stmt(_bb,_stmt) \
224 addStmtToIRBB((_bb), (_stmt))
225
226/* build various kinds of expressions */
227#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
228#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
229#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
230#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
231#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
232#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
233#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
234
235/* bind the given expression to a new temporary, and return the
236 temporary. This effectively converts an arbitrary expression into
237 an atom. */
238static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
239 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
240 assign(mce->bb, t, e);
241 return mkexpr(t);
242}
243
244
245/*------------------------------------------------------------*/
246/*--- Constructing definedness primitive ops ---*/
247/*------------------------------------------------------------*/
248
249/* --------- Defined-if-either-defined --------- */
250
251static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
252 tl_assert(isShadowAtom(mce,a1));
253 tl_assert(isShadowAtom(mce,a2));
254 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
255}
256
257static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
258 tl_assert(isShadowAtom(mce,a1));
259 tl_assert(isShadowAtom(mce,a2));
260 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
261}
262
263static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
264 tl_assert(isShadowAtom(mce,a1));
265 tl_assert(isShadowAtom(mce,a2));
266 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
267}
268
sewardj7010f6e2004-12-10 13:35:22 +0000269static IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
270 tl_assert(isShadowAtom(mce,a1));
271 tl_assert(isShadowAtom(mce,a2));
272 return assignNew(mce, Ity_I64, binop(Iop_And64, a1, a2));
273}
274
sewardj95448072004-11-22 20:19:51 +0000275/* --------- Undefined-if-either-undefined --------- */
276
277static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
278 tl_assert(isShadowAtom(mce,a1));
279 tl_assert(isShadowAtom(mce,a2));
280 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
281}
282
283static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
284 tl_assert(isShadowAtom(mce,a1));
285 tl_assert(isShadowAtom(mce,a2));
286 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
287}
288
289static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
290 tl_assert(isShadowAtom(mce,a1));
291 tl_assert(isShadowAtom(mce,a2));
292 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
293}
294
295static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
296 tl_assert(isShadowAtom(mce,a1));
297 tl_assert(isShadowAtom(mce,a2));
298 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
299}
300
sewardj3245c912004-12-10 14:58:26 +0000301static IRAtom* mkUifU128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
302 tl_assert(isShadowAtom(mce,a1));
303 tl_assert(isShadowAtom(mce,a2));
304 return assignNew(mce, Ity_V128, binop(Iop_Or128, a1, a2));
305}
306
sewardj95448072004-11-22 20:19:51 +0000307static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
308 switch (vty) {
309 case Ity_I16: return mkUifU16(mce, a1, a2);
310 case Ity_I32: return mkUifU32(mce, a1, a2);
311 case Ity_I64: return mkUifU64(mce, a1, a2);
312 default:
313 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
314 VG_(tool_panic)("memcheck:mkUifU");
njn25e49d8e72002-09-23 09:36:25 +0000315 }
316}
317
sewardj95448072004-11-22 20:19:51 +0000318/* --------- The Left-family of operations. --------- */
njn25e49d8e72002-09-23 09:36:25 +0000319
sewardj95448072004-11-22 20:19:51 +0000320static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
321 tl_assert(isShadowAtom(mce,a1));
322 /* It's safe to duplicate a1 since it's only an atom */
323 return assignNew(mce, Ity_I8,
324 binop(Iop_Or8, a1,
325 assignNew(mce, Ity_I8,
326 /* unop(Iop_Neg8, a1)))); */
327 binop(Iop_Sub8, mkU8(0), a1) )));
328}
329
330static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
331 tl_assert(isShadowAtom(mce,a1));
332 /* It's safe to duplicate a1 since it's only an atom */
333 return assignNew(mce, Ity_I16,
334 binop(Iop_Or16, a1,
335 assignNew(mce, Ity_I16,
336 /* unop(Iop_Neg16, a1)))); */
337 binop(Iop_Sub16, mkU16(0), a1) )));
338}
339
340static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
341 tl_assert(isShadowAtom(mce,a1));
342 /* It's safe to duplicate a1 since it's only an atom */
343 return assignNew(mce, Ity_I32,
344 binop(Iop_Or32, a1,
345 assignNew(mce, Ity_I32,
346 /* unop(Iop_Neg32, a1)))); */
347 binop(Iop_Sub32, mkU32(0), a1) )));
348}
349
350/* --------- 'Improvement' functions for AND/OR. --------- */
351
352/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
353 defined (0); all other -> undefined (1).
354*/
355static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
njn25e49d8e72002-09-23 09:36:25 +0000356{
sewardj95448072004-11-22 20:19:51 +0000357 tl_assert(isOriginalAtom(mce, data));
358 tl_assert(isShadowAtom(mce, vbits));
359 tl_assert(sameKindedAtoms(data, vbits));
360 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
361}
njn25e49d8e72002-09-23 09:36:25 +0000362
sewardj95448072004-11-22 20:19:51 +0000363static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
364{
365 tl_assert(isOriginalAtom(mce, data));
366 tl_assert(isShadowAtom(mce, vbits));
367 tl_assert(sameKindedAtoms(data, vbits));
368 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
369}
njn25e49d8e72002-09-23 09:36:25 +0000370
sewardj95448072004-11-22 20:19:51 +0000371static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
372{
373 tl_assert(isOriginalAtom(mce, data));
374 tl_assert(isShadowAtom(mce, vbits));
375 tl_assert(sameKindedAtoms(data, vbits));
376 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
377}
njn25e49d8e72002-09-23 09:36:25 +0000378
sewardj7010f6e2004-12-10 13:35:22 +0000379static IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
380{
381 tl_assert(isOriginalAtom(mce, data));
382 tl_assert(isShadowAtom(mce, vbits));
383 tl_assert(sameKindedAtoms(data, vbits));
384 return assignNew(mce, Ity_I64, binop(Iop_Or64, data, vbits));
385}
386
sewardj95448072004-11-22 20:19:51 +0000387/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
388 defined (0); all other -> undefined (1).
389*/
390static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
391{
392 tl_assert(isOriginalAtom(mce, data));
393 tl_assert(isShadowAtom(mce, vbits));
394 tl_assert(sameKindedAtoms(data, vbits));
395 return assignNew(
396 mce, Ity_I8,
397 binop(Iop_Or8,
398 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
399 vbits) );
400}
njn25e49d8e72002-09-23 09:36:25 +0000401
sewardj95448072004-11-22 20:19:51 +0000402static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
403{
404 tl_assert(isOriginalAtom(mce, data));
405 tl_assert(isShadowAtom(mce, vbits));
406 tl_assert(sameKindedAtoms(data, vbits));
407 return assignNew(
408 mce, Ity_I16,
409 binop(Iop_Or16,
410 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
411 vbits) );
412}
njn25e49d8e72002-09-23 09:36:25 +0000413
sewardj95448072004-11-22 20:19:51 +0000414static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
415{
416 tl_assert(isOriginalAtom(mce, data));
417 tl_assert(isShadowAtom(mce, vbits));
418 tl_assert(sameKindedAtoms(data, vbits));
419 return assignNew(
420 mce, Ity_I32,
421 binop(Iop_Or32,
422 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
423 vbits) );
424}
425
sewardj7010f6e2004-12-10 13:35:22 +0000426static IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
427{
428 tl_assert(isOriginalAtom(mce, data));
429 tl_assert(isShadowAtom(mce, vbits));
430 tl_assert(sameKindedAtoms(data, vbits));
431 return assignNew(
432 mce, Ity_I64,
433 binop(Iop_Or64,
434 assignNew(mce, Ity_I64, unop(Iop_Not64, data)),
435 vbits) );
436}
437
sewardj95448072004-11-22 20:19:51 +0000438/* --------- Pessimising casts. --------- */
439
440static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
441{
sewardj7cf97ee2004-11-28 14:25:01 +0000442 IRType ty;
443 IRAtom* tmp1;
sewardj95448072004-11-22 20:19:51 +0000444 /* Note, dst_ty is a shadow type, not an original type. */
445 /* First of all, collapse vbits down to a single bit. */
446 tl_assert(isShadowAtom(mce,vbits));
sewardj7cf97ee2004-11-28 14:25:01 +0000447 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
448 tmp1 = NULL;
sewardj95448072004-11-22 20:19:51 +0000449 switch (ty) {
450 case Ity_I1:
451 tmp1 = vbits;
njn25e49d8e72002-09-23 09:36:25 +0000452 break;
sewardj95448072004-11-22 20:19:51 +0000453 case Ity_I8:
454 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
455 break;
456 case Ity_I16:
457 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
458 break;
459 case Ity_I32:
460 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
461 break;
462 case Ity_I64:
463 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
464 break;
465 default:
466 VG_(tool_panic)("mkPCastTo(1)");
467 }
468 tl_assert(tmp1);
469 /* Now widen up to the dst type. */
470 switch (dst_ty) {
471 case Ity_I1:
472 return tmp1;
473 case Ity_I8:
474 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
475 case Ity_I16:
476 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
477 case Ity_I32:
478 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
479 case Ity_I64:
480 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
481 default:
482 ppIRType(dst_ty);
483 VG_(tool_panic)("mkPCastTo(2)");
484 }
485}
486
487
488/*------------------------------------------------------------*/
489/*--- Emit a test and complaint if something is undefined. ---*/
490/*------------------------------------------------------------*/
491
492/* Set the annotations on a dirty helper to indicate that the stack
493 pointer and instruction pointers might be read. This is the
494 behaviour of all 'emit-a-complaint' style functions we might
495 call. */
496
497static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
498 di->nFxState = 2;
499 di->fxState[0].fx = Ifx_Read;
500 di->fxState[0].offset = mce->layout->offset_SP;
501 di->fxState[0].size = mce->layout->sizeof_SP;
502 di->fxState[1].fx = Ifx_Read;
503 di->fxState[1].offset = mce->layout->offset_IP;
504 di->fxState[1].size = mce->layout->sizeof_IP;
505}
506
507
508/* Check the supplied **original** atom for undefinedness, and emit a
509 complaint if so. Once that happens, mark it as defined. This is
510 possible because the atom is either a tmp or literal. If it's a
511 tmp, it will be shadowed by a tmp, and so we can set the shadow to
512 be defined. In fact as mentioned above, we will have to allocate a
513 new tmp to carry the new 'defined' shadow value, and update the
514 original->tmp mapping accordingly; we cannot simply assign a new
515 value to an existing shadow tmp as this breaks SSAness -- resulting
516 in the post-instrumentation sanity checker spluttering in disapproval.
517*/
518static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
519{
sewardj7cf97ee2004-11-28 14:25:01 +0000520 IRAtom* vatom;
521 IRType ty;
522 Int sz;
523 IRDirty* di;
524 IRAtom* cond;
525
sewardj95448072004-11-22 20:19:51 +0000526 /* Since the original expression is atomic, there's no duplicated
527 work generated by making multiple V-expressions for it. So we
528 don't really care about the possibility that someone else may
529 also create a V-interpretion for it. */
530 tl_assert(isOriginalAtom(mce, atom));
sewardj7cf97ee2004-11-28 14:25:01 +0000531 vatom = expr2vbits( mce, atom );
sewardj95448072004-11-22 20:19:51 +0000532 tl_assert(isShadowAtom(mce, vatom));
533 tl_assert(sameKindedAtoms(atom, vatom));
534
sewardj7cf97ee2004-11-28 14:25:01 +0000535 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj95448072004-11-22 20:19:51 +0000536
537 /* sz is only used for constructing the error message */
sewardj7cf97ee2004-11-28 14:25:01 +0000538 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardj95448072004-11-22 20:19:51 +0000539
sewardj7cf97ee2004-11-28 14:25:01 +0000540 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardj95448072004-11-22 20:19:51 +0000541 /* cond will be 0 if all defined, and 1 if any not defined. */
542
sewardj95448072004-11-22 20:19:51 +0000543 switch (sz) {
544 case 0:
545 di = unsafeIRDirty_0_N( 0/*regparms*/,
546 "MC_(helperc_value_check0_fail)",
547 &MC_(helperc_value_check0_fail),
548 mkIRExprVec_0()
549 );
550 break;
551 case 1:
552 di = unsafeIRDirty_0_N( 0/*regparms*/,
553 "MC_(helperc_value_check1_fail)",
554 &MC_(helperc_value_check1_fail),
555 mkIRExprVec_0()
556 );
557 break;
558 case 4:
559 di = unsafeIRDirty_0_N( 0/*regparms*/,
560 "MC_(helperc_value_check4_fail)",
561 &MC_(helperc_value_check4_fail),
562 mkIRExprVec_0()
563 );
564 break;
565 default:
566 di = unsafeIRDirty_0_N( 1/*regparms*/,
567 "MC_(helperc_complain_undef)",
568 &MC_(helperc_complain_undef),
569 mkIRExprVec_1( mkIRExpr_HWord( sz ))
570 );
571 break;
572 }
573 di->guard = cond;
574 setHelperAnns( mce, di );
575 stmt( mce->bb, IRStmt_Dirty(di));
576
577 /* Set the shadow tmp to be defined. First, update the
578 orig->shadow tmp mapping to reflect the fact that this shadow is
579 getting a new value. */
580 tl_assert(isAtom(vatom));
581 /* sameKindedAtoms ... */
582 if (vatom->tag == Iex_Tmp) {
583 tl_assert(atom->tag == Iex_Tmp);
584 newShadowTmp(mce, atom->Iex.Tmp.tmp);
585 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
586 definedOfType(ty));
587 }
588}
589
590
591/*------------------------------------------------------------*/
592/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
593/*------------------------------------------------------------*/
594
595/* Examine the always-defined sections declared in layout to see if
596 the (offset,size) section is within one. Note, is is an error to
597 partially fall into such a region: (offset,size) should either be
598 completely in such a region or completely not-in such a region.
599*/
600static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
601{
602 Int minoffD, maxoffD, i;
603 Int minoff = offset;
604 Int maxoff = minoff + size - 1;
605 tl_assert((minoff & ~0xFFFF) == 0);
606 tl_assert((maxoff & ~0xFFFF) == 0);
607
608 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
609 minoffD = mce->layout->alwaysDefd[i].offset;
610 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
611 tl_assert((minoffD & ~0xFFFF) == 0);
612 tl_assert((maxoffD & ~0xFFFF) == 0);
613
614 if (maxoff < minoffD || maxoffD < minoff)
615 continue; /* no overlap */
616 if (minoff >= minoffD && maxoff <= maxoffD)
617 return True; /* completely contained in an always-defd section */
618
619 VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
620 }
621 return False; /* could not find any containing section */
622}
623
624
625/* Generate into bb suitable actions to shadow this Put. If the state
626 slice is marked 'always defined', do nothing. Otherwise, write the
627 supplied V bits to the shadow state. We can pass in either an
628 original atom or a V-atom, but not both. In the former case the
629 relevant V-bits are then generated from the original.
630*/
631static
632void do_shadow_PUT ( MCEnv* mce, Int offset,
633 IRAtom* atom, IRAtom* vatom )
634{
sewardj7cf97ee2004-11-28 14:25:01 +0000635 IRType ty;
sewardj95448072004-11-22 20:19:51 +0000636 if (atom) {
637 tl_assert(!vatom);
638 tl_assert(isOriginalAtom(mce, atom));
639 vatom = expr2vbits( mce, atom );
640 } else {
641 tl_assert(vatom);
642 tl_assert(isShadowAtom(mce, vatom));
643 }
644
sewardj7cf97ee2004-11-28 14:25:01 +0000645 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardj95448072004-11-22 20:19:51 +0000646 tl_assert(ty != Ity_I1);
647 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
648 /* later: no ... */
649 /* emit code to emit a complaint if any of the vbits are 1. */
650 /* complainIfUndefined(mce, atom); */
651 } else {
652 /* Do a plain shadow Put. */
653 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
654 }
655}
656
657
658/* Return an expression which contains the V bits corresponding to the
659 given GETI (passed in in pieces).
660*/
661static
662void do_shadow_PUTI ( MCEnv* mce,
663 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
664{
sewardj7cf97ee2004-11-28 14:25:01 +0000665 IRAtom* vatom;
666 IRType ty, tyS;
667 Int arrSize;;
668
sewardj95448072004-11-22 20:19:51 +0000669 tl_assert(isOriginalAtom(mce,atom));
sewardj7cf97ee2004-11-28 14:25:01 +0000670 vatom = expr2vbits( mce, atom );
sewardj95448072004-11-22 20:19:51 +0000671 tl_assert(sameKindedAtoms(atom, vatom));
sewardj7cf97ee2004-11-28 14:25:01 +0000672 ty = descr->elemTy;
673 tyS = shadowType(ty);
674 arrSize = descr->nElems * sizeofIRType(ty);
sewardj95448072004-11-22 20:19:51 +0000675 tl_assert(ty != Ity_I1);
676 tl_assert(isOriginalAtom(mce,ix));
677 complainIfUndefined(mce,ix);
678 if (isAlwaysDefd(mce, descr->base, arrSize)) {
679 /* later: no ... */
680 /* emit code to emit a complaint if any of the vbits are 1. */
681 /* complainIfUndefined(mce, atom); */
682 } else {
683 /* Do a cloned version of the Put that refers to the shadow
684 area. */
685 IRArray* new_descr
686 = mkIRArray( descr->base + mce->layout->total_sizeB,
687 tyS, descr->nElems);
688 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
689 }
690}
691
692
693/* Return an expression which contains the V bits corresponding to the
694 given GET (passed in in pieces).
695*/
696static
697IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
698{
699 IRType tyS = shadowType(ty);
700 tl_assert(ty != Ity_I1);
701 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
702 /* Always defined, return all zeroes of the relevant type */
703 return definedOfType(tyS);
704 } else {
705 /* return a cloned version of the Get that refers to the shadow
706 area. */
707 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
708 }
709}
710
711
712/* Return an expression which contains the V bits corresponding to the
713 given GETI (passed in in pieces).
714*/
715static
716IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
717{
718 IRType ty = descr->elemTy;
719 IRType tyS = shadowType(ty);
720 Int arrSize = descr->nElems * sizeofIRType(ty);
721 tl_assert(ty != Ity_I1);
722 tl_assert(isOriginalAtom(mce,ix));
723 complainIfUndefined(mce,ix);
724 if (isAlwaysDefd(mce, descr->base, arrSize)) {
725 /* Always defined, return all zeroes of the relevant type */
726 return definedOfType(tyS);
727 } else {
728 /* return a cloned version of the Get that refers to the shadow
729 area. */
730 IRArray* new_descr
731 = mkIRArray( descr->base + mce->layout->total_sizeB,
732 tyS, descr->nElems);
733 return IRExpr_GetI( new_descr, ix, bias );
734 }
735}
736
737
738/*------------------------------------------------------------*/
739/*--- Generating approximations for unknown operations, ---*/
740/*--- using lazy-propagate semantics ---*/
741/*------------------------------------------------------------*/
742
743/* Lazy propagation of undefinedness from two values, resulting in the
744 specified shadow type.
745*/
746static
747IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
748{
749 /* force everything via 32-bit intermediaries. */
750 IRAtom* at;
751 tl_assert(isShadowAtom(mce,va1));
752 tl_assert(isShadowAtom(mce,va2));
753 at = mkPCastTo(mce, Ity_I32, va1);
754 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
755 at = mkPCastTo(mce, finalVty, at);
756 return at;
757}
758
759
760/* Do the lazy propagation game from a null-terminated vector of
761 atoms. This is presumably the arguments to a helper call, so the
762 IRCallee info is also supplied in order that we can know which
763 arguments should be ignored (via the .mcx_mask field).
764*/
765static
766IRAtom* mkLazyN ( MCEnv* mce,
767 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
768{
769 Int i;
770 IRAtom* here;
771 IRAtom* curr = definedOfType(Ity_I32);
772 for (i = 0; exprvec[i]; i++) {
773 tl_assert(i < 32);
774 tl_assert(isOriginalAtom(mce, exprvec[i]));
775 /* Only take notice of this arg if the callee's mc-exclusion
776 mask does not say it is to be excluded. */
777 if (cee->mcx_mask & (1<<i)) {
778 /* the arg is to be excluded from definedness checking. Do
779 nothing. */
780 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
781 } else {
782 /* calculate the arg's definedness, and pessimistically merge
783 it in. */
784 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
785 curr = mkUifU32(mce, here, curr);
786 }
787 }
788 return mkPCastTo(mce, finalVtype, curr );
789}
790
791
792/*------------------------------------------------------------*/
793/*--- Generating expensive sequences for exact carry-chain ---*/
794/*--- propagation in add/sub and related operations. ---*/
795/*------------------------------------------------------------*/
796
797static
798IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
799 IRAtom* aa, IRAtom* bb )
800{
sewardj7cf97ee2004-11-28 14:25:01 +0000801 IRAtom *a_min, *b_min, *a_max, *b_max;
802 IRType ty;
803 IROp opAND, opOR, opXOR, opNOT, opADD;
804
sewardj95448072004-11-22 20:19:51 +0000805 tl_assert(isShadowAtom(mce,qaa));
806 tl_assert(isShadowAtom(mce,qbb));
807 tl_assert(isOriginalAtom(mce,aa));
808 tl_assert(isOriginalAtom(mce,bb));
809 tl_assert(sameKindedAtoms(qaa,aa));
810 tl_assert(sameKindedAtoms(qbb,bb));
811
sewardj7cf97ee2004-11-28 14:25:01 +0000812 ty = Ity_I32;
813 opAND = Iop_And32;
814 opOR = Iop_Or32;
815 opXOR = Iop_Xor32;
816 opNOT = Iop_Not32;
817 opADD = Iop_Add32;
sewardj95448072004-11-22 20:19:51 +0000818
819 // a_min = aa & ~qaa
820 a_min = assignNew(mce,ty,
821 binop(opAND, aa,
822 assignNew(mce,ty, unop(opNOT, qaa))));
823
824 // b_min = bb & ~qbb
825 b_min = assignNew(mce,ty,
826 binop(opAND, bb,
827 assignNew(mce,ty, unop(opNOT, qbb))));
828
829 // a_max = aa | qaa
830 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
831
832 // b_max = bb | qbb
833 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
834
835 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
836 return
837 assignNew(mce,ty,
838 binop( opOR,
839 assignNew(mce,ty, binop(opOR, qaa, qbb)),
840 assignNew(mce,ty,
841 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
842 assignNew(mce,ty, binop(opADD, a_max, b_max))
843 )
844 )
845 )
846 );
847}
848
849
850/*------------------------------------------------------------*/
sewardj3245c912004-12-10 14:58:26 +0000851/*--- Helpers for dealing with vector primops. ---*/
852/*------------------------------------------------------------*/
853
854/* Here's a simple scheme capable of handling ops derived from SSE1
855 code and while only generating ops that can be efficiently
856 implemented in SSE1. */
857
858/* All-lanes versions are straightforward:
859
860 binary32Fx4(x,y) ==> PCast32x4(UifU128(x#,y#))
861
862 unary32Fx4(x,y) ==> PCast32x4(x#)
863
864 Lowest-lane-only versions are more complex:
865
866 binary32F0x4(x,y) ==> Set128lo32(
867 x#,
868 PCast32(128to32(UifU128(x#,y#)))
869 )
870
871 This is perhaps not so obvious. In particular, it's faster to
872 do a 128-bit UifU and then take the bottom 32 bits than the more
873 obvious scheme of taking the bottom 32 bits of each operand
874 and doing a 32-bit UifU. Basically since UifU is fast and
875 chopping lanes off vector values is slow.
876
877 Finally:
878
879 unary32F0x4(x) ==> Set128lo32(
880 x#,
881 PCast32(128to32(x#))
882 )
883
884 Where:
885
886 PCast32(v#) = 1Sto32(CmpNE32(v#,0))
887 PCast32x4(v#) = CmpNEZ32x4(v#)
888*/
889
890static
891IRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
892{
893 IRAtom* at;
894 tl_assert(isShadowAtom(mce, vatomX));
895 tl_assert(isShadowAtom(mce, vatomY));
896 at = mkUifU128(mce, vatomX, vatomY);
897 at = assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
898 return at;
899}
900
901static
902IRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
903{
904 IRAtom* at;
905 tl_assert(isShadowAtom(mce, vatomX));
906 at = assignNew(mce, Ity_V128, unop(Iop_CmpNEZ32x4, vatomX));
907 return at;
908}
909
910static
911IRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
912{
913 IRAtom* at;
914 tl_assert(isShadowAtom(mce, vatomX));
915 tl_assert(isShadowAtom(mce, vatomY));
916 at = mkUifU128(mce, vatomX, vatomY);
917 at = assignNew(mce, Ity_I32, unop(Iop_128to32, at));
918 at = mkPCastTo(mce, Ity_I32, at);
919 at = assignNew(mce, Ity_V128, binop(Iop_Set128lo32, vatomX, at));
920 return at;
921}
922
923static
924IRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
925{
926 IRAtom* at;
927 tl_assert(isShadowAtom(mce, vatomX));
928 at = assignNew(mce, Ity_I32, unop(Iop_128to32, vatomX));
929 at = mkPCastTo(mce, Ity_I32, at);
930 at = assignNew(mce, Ity_V128, binop(Iop_Set128lo32, vatomX, at));
931 return at;
932}
933
934
935
936/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +0000937/*--- Generate shadow values from all kinds of IRExprs. ---*/
938/*------------------------------------------------------------*/
939
940static
941IRAtom* expr2vbits_Binop ( MCEnv* mce,
942 IROp op,
943 IRAtom* atom1, IRAtom* atom2 )
944{
945 IRType and_or_ty;
946 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
947 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
948 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
949
950 IRAtom* vatom1 = expr2vbits( mce, atom1 );
951 IRAtom* vatom2 = expr2vbits( mce, atom2 );
952
953 tl_assert(isOriginalAtom(mce,atom1));
954 tl_assert(isOriginalAtom(mce,atom2));
955 tl_assert(isShadowAtom(mce,vatom1));
956 tl_assert(isShadowAtom(mce,vatom2));
957 tl_assert(sameKindedAtoms(atom1,vatom1));
958 tl_assert(sameKindedAtoms(atom2,vatom2));
959 switch (op) {
960
sewardj3245c912004-12-10 14:58:26 +0000961 /* 128-bit SIMD */
962
963 case Iop_Add32Fx4:
964 return binary32Fx4(mce, vatom1, vatom2);
965
966 /* Scalar floating point */
967
sewardj95448072004-11-22 20:19:51 +0000968 case Iop_RoundF64:
969 case Iop_F64toI64:
sewardje9e16d32004-12-10 13:17:55 +0000970 case Iop_I64toF64:
971 /* First arg is I32 (rounding mode), second is F64 or I64
972 (data). */
sewardj95448072004-11-22 20:19:51 +0000973 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
974
975 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
976 /* Takes two F64 args. */
977 case Iop_F64toI32:
sewardje9e16d32004-12-10 13:17:55 +0000978 case Iop_F64toF32:
sewardj95448072004-11-22 20:19:51 +0000979 /* First arg is I32 (rounding mode), second is F64 (data). */
980 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
981
982 case Iop_F64toI16:
983 /* First arg is I32 (rounding mode), second is F64 (data). */
984 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
985
986 case Iop_ScaleF64:
987 case Iop_Yl2xF64:
988 case Iop_Yl2xp1F64:
989 case Iop_PRemF64:
990 case Iop_AtanF64:
991 case Iop_AddF64:
992 case Iop_DivF64:
993 case Iop_SubF64:
994 case Iop_MulF64:
995 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
996
997 case Iop_CmpF64:
998 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
999
1000 /* non-FP after here */
1001
1002 case Iop_DivModU64to32:
1003 case Iop_DivModS64to32:
1004 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1005
1006 case Iop_16HLto32:
1007 return assignNew(mce, Ity_I32,
1008 binop(Iop_16HLto32, vatom1, vatom2));
1009 case Iop_32HLto64:
1010 return assignNew(mce, Ity_I64,
1011 binop(Iop_32HLto64, vatom1, vatom2));
1012
1013 case Iop_MullS32:
1014 case Iop_MullU32: {
1015 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1016 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1017 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1018 }
1019
1020 case Iop_MullS16:
1021 case Iop_MullU16: {
1022 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1023 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1024 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1025 }
1026
1027 case Iop_MullS8:
1028 case Iop_MullU8: {
1029 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1030 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1031 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1032 }
1033
1034 case Iop_Add32:
1035# if 0
1036 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1037# endif
1038 case Iop_Sub32:
1039 case Iop_Mul32:
1040 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1041
1042 case Iop_Mul16:
1043 case Iop_Add16:
1044 case Iop_Sub16:
1045 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1046
1047 case Iop_Sub8:
1048 case Iop_Add8:
1049 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1050
1051 case Iop_CmpLE32S: case Iop_CmpLE32U:
1052 case Iop_CmpLT32U: case Iop_CmpLT32S:
1053 case Iop_CmpEQ32: case Iop_CmpNE32:
1054 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
1055
1056 case Iop_CmpEQ16: case Iop_CmpNE16:
1057 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
1058
1059 case Iop_CmpEQ8: case Iop_CmpNE8:
1060 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
1061
1062 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1063 /* Complain if the shift amount is undefined. Then simply
1064 shift the first arg's V bits by the real shift amount. */
1065 complainIfUndefined(mce, atom2);
1066 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1067
1068 case Iop_Shl16: case Iop_Shr16:
1069 /* Same scheme as with 32-bit shifts. */
1070 complainIfUndefined(mce, atom2);
1071 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1072
1073 case Iop_Shl8: case Iop_Shr8:
1074 /* Same scheme as with 32-bit shifts. */
1075 complainIfUndefined(mce, atom2);
1076 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1077
1078 case Iop_Shl64: case Iop_Shr64:
1079 /* Same scheme as with 32-bit shifts. */
1080 complainIfUndefined(mce, atom2);
1081 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1082
sewardj7010f6e2004-12-10 13:35:22 +00001083 case Iop_And64:
1084 uifu = mkUifU64; difd = mkDifD64;
1085 and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
sewardj95448072004-11-22 20:19:51 +00001086 case Iop_And32:
1087 uifu = mkUifU32; difd = mkDifD32;
1088 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
1089 case Iop_And16:
1090 uifu = mkUifU16; difd = mkDifD16;
1091 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
1092 case Iop_And8:
1093 uifu = mkUifU8; difd = mkDifD8;
1094 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1095
sewardj7010f6e2004-12-10 13:35:22 +00001096 case Iop_Or64:
1097 uifu = mkUifU64; difd = mkDifD64;
1098 and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
sewardj95448072004-11-22 20:19:51 +00001099 case Iop_Or32:
1100 uifu = mkUifU32; difd = mkDifD32;
1101 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1102 case Iop_Or16:
1103 uifu = mkUifU16; difd = mkDifD16;
1104 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1105 case Iop_Or8:
1106 uifu = mkUifU8; difd = mkDifD8;
1107 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1108
1109 do_And_Or:
1110 return
1111 assignNew(
1112 mce,
1113 and_or_ty,
1114 difd(mce, uifu(mce, vatom1, vatom2),
1115 difd(mce, improve(mce, atom1, vatom1),
1116 improve(mce, atom2, vatom2) ) ) );
1117
1118 case Iop_Xor8:
1119 return mkUifU8(mce, vatom1, vatom2);
1120 case Iop_Xor16:
1121 return mkUifU16(mce, vatom1, vatom2);
1122 case Iop_Xor32:
1123 return mkUifU32(mce, vatom1, vatom2);
sewardj7010f6e2004-12-10 13:35:22 +00001124 case Iop_Xor64:
1125 return mkUifU64(mce, vatom1, vatom2);
njn25e49d8e72002-09-23 09:36:25 +00001126
1127 default:
sewardj95448072004-11-22 20:19:51 +00001128 ppIROp(op);
1129 VG_(tool_panic)("memcheck:expr2vbits_Binop");
njn25e49d8e72002-09-23 09:36:25 +00001130 }
njn25e49d8e72002-09-23 09:36:25 +00001131}
1132
njn25e49d8e72002-09-23 09:36:25 +00001133
sewardj95448072004-11-22 20:19:51 +00001134static
1135IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1136{
1137 IRAtom* vatom = expr2vbits( mce, atom );
1138 tl_assert(isOriginalAtom(mce,atom));
1139 switch (op) {
1140
1141 case Iop_F32toF64:
1142 case Iop_I32toF64:
sewardj95448072004-11-22 20:19:51 +00001143 case Iop_NegF64:
1144 case Iop_SinF64:
1145 case Iop_CosF64:
1146 case Iop_TanF64:
1147 case Iop_SqrtF64:
1148 case Iop_AbsF64:
1149 case Iop_2xm1F64:
1150 return mkPCastTo(mce, Ity_I64, vatom);
1151
sewardj95448072004-11-22 20:19:51 +00001152 case Iop_Clz32:
1153 case Iop_Ctz32:
1154 return mkPCastTo(mce, Ity_I32, vatom);
1155
1156 case Iop_32Sto64:
1157 case Iop_32Uto64:
1158 return assignNew(mce, Ity_I64, unop(op, vatom));
1159
1160 case Iop_64to32:
1161 case Iop_64HIto32:
1162 case Iop_1Uto32:
1163 case Iop_8Uto32:
1164 case Iop_16Uto32:
1165 case Iop_16Sto32:
1166 case Iop_8Sto32:
1167 return assignNew(mce, Ity_I32, unop(op, vatom));
1168
1169 case Iop_8Sto16:
1170 case Iop_8Uto16:
1171 case Iop_32to16:
1172 case Iop_32HIto16:
1173 return assignNew(mce, Ity_I16, unop(op, vatom));
1174
1175 case Iop_1Uto8:
1176 case Iop_16to8:
1177 case Iop_32to8:
1178 return assignNew(mce, Ity_I8, unop(op, vatom));
1179
1180 case Iop_32to1:
1181 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
1182
1183 case Iop_ReinterpF64asI64:
1184 case Iop_ReinterpI64asF64:
sewardj7010f6e2004-12-10 13:35:22 +00001185 case Iop_Not64:
sewardj95448072004-11-22 20:19:51 +00001186 case Iop_Not32:
1187 case Iop_Not16:
1188 case Iop_Not8:
1189 case Iop_Not1:
1190 return vatom;
sewardj7010f6e2004-12-10 13:35:22 +00001191
sewardj95448072004-11-22 20:19:51 +00001192 default:
1193 ppIROp(op);
1194 VG_(tool_panic)("memcheck:expr2vbits_Unop");
1195 }
1196}
1197
1198
1199static
1200IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
1201{
1202 void* helper;
1203 Char* hname;
1204 IRDirty* di;
1205 IRTemp datavbits;
1206 IRAtom* addrAct;
1207
1208 tl_assert(isOriginalAtom(mce,addr));
1209
1210 /* First, emit a definedness test for the address. This also sets
1211 the address (shadow) to 'defined' following the test. */
1212 complainIfUndefined( mce, addr );
1213
1214 /* Now cook up a call to the relevant helper function, to read the
1215 data V bits from shadow memory. */
1216 ty = shadowType(ty);
1217 switch (ty) {
1218 case Ity_I64: helper = &MC_(helperc_LOADV8);
1219 hname = "MC_(helperc_LOADV8)";
1220 break;
1221 case Ity_I32: helper = &MC_(helperc_LOADV4);
1222 hname = "MC_(helperc_LOADV4)";
1223 break;
1224 case Ity_I16: helper = &MC_(helperc_LOADV2);
1225 hname = "MC_(helperc_LOADV2)";
1226 break;
1227 case Ity_I8: helper = &MC_(helperc_LOADV1);
1228 hname = "MC_(helperc_LOADV1)";
1229 break;
1230 default: ppIRType(ty);
1231 VG_(tool_panic)("memcheck:do_shadow_LDle");
1232 }
1233
1234 /* Generate the actual address into addrAct. */
1235 if (bias == 0) {
1236 addrAct = addr;
1237 } else {
sewardj7cf97ee2004-11-28 14:25:01 +00001238 IROp mkAdd;
1239 IRAtom* eBias;
sewardj95448072004-11-22 20:19:51 +00001240 IRType tyAddr = mce->hWordTy;
1241 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj7cf97ee2004-11-28 14:25:01 +00001242 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1243 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj95448072004-11-22 20:19:51 +00001244 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1245 }
1246
1247 /* We need to have a place to park the V bits we're just about to
1248 read. */
1249 datavbits = newIRTemp(mce->bb->tyenv, ty);
1250 di = unsafeIRDirty_1_N( datavbits,
1251 1/*regparms*/, hname, helper,
1252 mkIRExprVec_1( addrAct ));
1253 setHelperAnns( mce, di );
1254 stmt( mce->bb, IRStmt_Dirty(di) );
1255
1256 return mkexpr(datavbits);
1257}
1258
1259
1260static
1261IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
1262 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
1263{
1264 IRAtom *vbitsC, *vbits0, *vbitsX;
1265 IRType ty;
1266 /* Given Mux0X(cond,expr0,exprX), generate
1267 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
1268 That is, steer the V bits like the originals, but trash the
1269 result if the steering value is undefined. This gives
1270 lazy propagation. */
1271 tl_assert(isOriginalAtom(mce, cond));
1272 tl_assert(isOriginalAtom(mce, expr0));
1273 tl_assert(isOriginalAtom(mce, exprX));
1274
1275 vbitsC = expr2vbits(mce, cond);
1276 vbits0 = expr2vbits(mce, expr0);
1277 vbitsX = expr2vbits(mce, exprX);
1278 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
1279
1280 return
1281 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
1282 mkPCastTo(mce, ty, vbitsC) );
1283}
1284
1285/* --------- This is the main expression-handling function. --------- */
1286
1287static
1288IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
1289{
1290 switch (e->tag) {
1291
1292 case Iex_Get:
1293 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
1294
1295 case Iex_GetI:
1296 return shadow_GETI( mce, e->Iex.GetI.descr,
1297 e->Iex.GetI.ix, e->Iex.GetI.bias );
1298
1299 case Iex_Tmp:
1300 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
1301
1302 case Iex_Const:
1303 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
1304
1305 case Iex_Binop:
1306 return expr2vbits_Binop(
1307 mce,
1308 e->Iex.Binop.op,
1309 e->Iex.Binop.arg1, e->Iex.Binop.arg2
1310 );
1311
1312 case Iex_Unop:
1313 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
1314
1315 case Iex_LDle:
1316 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
1317 e->Iex.LDle.addr, 0/*addr bias*/ );
1318
1319 case Iex_CCall:
1320 return mkLazyN( mce, e->Iex.CCall.args,
1321 e->Iex.CCall.retty,
1322 e->Iex.CCall.cee );
1323
1324 case Iex_Mux0X:
1325 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
1326 e->Iex.Mux0X.exprX);
njn25e49d8e72002-09-23 09:36:25 +00001327
1328 default:
sewardj95448072004-11-22 20:19:51 +00001329 VG_(printf)("\n");
1330 ppIRExpr(e);
1331 VG_(printf)("\n");
1332 VG_(tool_panic)("memcheck: expr2vbits");
njn25e49d8e72002-09-23 09:36:25 +00001333 }
njn25e49d8e72002-09-23 09:36:25 +00001334}
1335
1336/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00001337/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
njn25e49d8e72002-09-23 09:36:25 +00001338/*------------------------------------------------------------*/
1339
sewardj95448072004-11-22 20:19:51 +00001340/* Widen a value to the host word size. */
njn25e49d8e72002-09-23 09:36:25 +00001341
1342static
sewardj95448072004-11-22 20:19:51 +00001343IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
njn25e49d8e72002-09-23 09:36:25 +00001344{
sewardj7cf97ee2004-11-28 14:25:01 +00001345 IRType ty, tyH;
1346
sewardj95448072004-11-22 20:19:51 +00001347 /* vatom is vbits-value and as such can only have a shadow type. */
1348 tl_assert(isShadowAtom(mce,vatom));
njn25e49d8e72002-09-23 09:36:25 +00001349
sewardj7cf97ee2004-11-28 14:25:01 +00001350 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
1351 tyH = mce->hWordTy;
njn25e49d8e72002-09-23 09:36:25 +00001352
sewardj95448072004-11-22 20:19:51 +00001353 if (tyH == Ity_I32) {
1354 switch (ty) {
1355 case Ity_I32: return vatom;
1356 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
1357 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
1358 default: goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00001359 }
sewardj95448072004-11-22 20:19:51 +00001360 } else {
1361 goto unhandled;
sewardj8ec2cfc2002-10-13 00:57:26 +00001362 }
sewardj95448072004-11-22 20:19:51 +00001363 unhandled:
1364 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
1365 VG_(tool_panic)("zwidenToHostWord");
njn25e49d8e72002-09-23 09:36:25 +00001366}
1367
njn25e49d8e72002-09-23 09:36:25 +00001368
sewardj95448072004-11-22 20:19:51 +00001369/* Generate a shadow store. addr is always the original address atom.
1370 You can pass in either originals or V-bits for the data atom, but
1371 obviously not both. */
njn25e49d8e72002-09-23 09:36:25 +00001372
sewardj95448072004-11-22 20:19:51 +00001373static
1374void do_shadow_STle ( MCEnv* mce,
1375 IRAtom* addr, UInt bias,
1376 IRAtom* data, IRAtom* vdata )
njn25e49d8e72002-09-23 09:36:25 +00001377{
sewardj95448072004-11-22 20:19:51 +00001378 IRType ty;
1379 IRDirty* di;
1380 void* helper = NULL;
1381 Char* hname = NULL;
1382 IRAtom* addrAct;
njn25e49d8e72002-09-23 09:36:25 +00001383
sewardj95448072004-11-22 20:19:51 +00001384 if (data) {
1385 tl_assert(!vdata);
1386 tl_assert(isOriginalAtom(mce, data));
1387 tl_assert(bias == 0);
1388 vdata = expr2vbits( mce, data );
1389 } else {
1390 tl_assert(vdata);
1391 }
njn25e49d8e72002-09-23 09:36:25 +00001392
sewardj95448072004-11-22 20:19:51 +00001393 tl_assert(isOriginalAtom(mce,addr));
1394 tl_assert(isShadowAtom(mce,vdata));
njn25e49d8e72002-09-23 09:36:25 +00001395
sewardj95448072004-11-22 20:19:51 +00001396 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
njn25e49d8e72002-09-23 09:36:25 +00001397
sewardj95448072004-11-22 20:19:51 +00001398 /* First, emit a definedness test for the address. This also sets
1399 the address (shadow) to 'defined' following the test. */
1400 complainIfUndefined( mce, addr );
njn25e49d8e72002-09-23 09:36:25 +00001401
sewardj95448072004-11-22 20:19:51 +00001402 /* Now cook up a call to the relevant helper function, to write the
1403 data V bits into shadow memory. */
1404 switch (ty) {
1405 case Ity_I64: helper = &MC_(helperc_STOREV8);
1406 hname = "MC_(helperc_STOREV8)";
1407 break;
1408 case Ity_I32: helper = &MC_(helperc_STOREV4);
1409 hname = "MC_(helperc_STOREV4)";
1410 break;
1411 case Ity_I16: helper = &MC_(helperc_STOREV2);
1412 hname = "MC_(helperc_STOREV2)";
1413 break;
1414 case Ity_I8: helper = &MC_(helperc_STOREV1);
1415 hname = "MC_(helperc_STOREV1)";
1416 break;
1417 default: VG_(tool_panic)("memcheck:do_shadow_STle");
1418 }
njn25e49d8e72002-09-23 09:36:25 +00001419
sewardj95448072004-11-22 20:19:51 +00001420 /* Generate the actual address into addrAct. */
1421 if (bias == 0) {
1422 addrAct = addr;
1423 } else {
sewardj7cf97ee2004-11-28 14:25:01 +00001424 IROp mkAdd;
1425 IRAtom* eBias;
sewardj95448072004-11-22 20:19:51 +00001426 IRType tyAddr = mce->hWordTy;
1427 tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj7cf97ee2004-11-28 14:25:01 +00001428 mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1429 eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj95448072004-11-22 20:19:51 +00001430 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1431 }
njn25e49d8e72002-09-23 09:36:25 +00001432
sewardj95448072004-11-22 20:19:51 +00001433 if (ty == Ity_I64) {
1434 /* We can't do this with regparm 2 on 32-bit platforms, since
1435 the back ends aren't clever enough to handle 64-bit regparm
1436 args. Therefore be different. */
1437 di = unsafeIRDirty_0_N(
1438 1/*regparms*/, hname, helper,
1439 mkIRExprVec_2( addrAct, vdata ));
1440 } else {
1441 di = unsafeIRDirty_0_N(
1442 2/*regparms*/, hname, helper,
1443 mkIRExprVec_2( addrAct,
1444 zwidenToHostWord( mce, vdata )));
1445 }
1446 setHelperAnns( mce, di );
1447 stmt( mce->bb, IRStmt_Dirty(di) );
1448}
njn25e49d8e72002-09-23 09:36:25 +00001449
njn25e49d8e72002-09-23 09:36:25 +00001450
sewardj95448072004-11-22 20:19:51 +00001451/* Do lazy pessimistic propagation through a dirty helper call, by
1452 looking at the annotations on it. This is the most complex part of
1453 Memcheck. */
njn25e49d8e72002-09-23 09:36:25 +00001454
sewardj95448072004-11-22 20:19:51 +00001455static IRType szToITy ( Int n )
1456{
1457 switch (n) {
1458 case 1: return Ity_I8;
1459 case 2: return Ity_I16;
1460 case 4: return Ity_I32;
1461 case 8: return Ity_I64;
1462 default: VG_(tool_panic)("szToITy(memcheck)");
1463 }
1464}
njn25e49d8e72002-09-23 09:36:25 +00001465
sewardj95448072004-11-22 20:19:51 +00001466static
1467void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
1468{
sewardje9e16d32004-12-10 13:17:55 +00001469 Int i, n, offset, toDo, gSz, gOff;
sewardj7cf97ee2004-11-28 14:25:01 +00001470 IRAtom *src, *here, *curr;
sewardj95448072004-11-22 20:19:51 +00001471 IRType tyAddr, tySrc, tyDst;
1472 IRTemp dst;
njn25e49d8e72002-09-23 09:36:25 +00001473
sewardj95448072004-11-22 20:19:51 +00001474 /* First check the guard. */
1475 complainIfUndefined(mce, d->guard);
1476
1477 /* Now round up all inputs and PCast over them. */
sewardj7cf97ee2004-11-28 14:25:01 +00001478 curr = definedOfType(Ity_I32);
sewardj95448072004-11-22 20:19:51 +00001479
1480 /* Inputs: unmasked args */
1481 for (i = 0; d->args[i]; i++) {
1482 if (d->cee->mcx_mask & (1<<i)) {
1483 /* ignore this arg */
njn25e49d8e72002-09-23 09:36:25 +00001484 } else {
sewardj95448072004-11-22 20:19:51 +00001485 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
1486 curr = mkUifU32(mce, here, curr);
njn25e49d8e72002-09-23 09:36:25 +00001487 }
1488 }
sewardj95448072004-11-22 20:19:51 +00001489
1490 /* Inputs: guest state that we read. */
1491 for (i = 0; i < d->nFxState; i++) {
1492 tl_assert(d->fxState[i].fx != Ifx_None);
1493 if (d->fxState[i].fx == Ifx_Write)
1494 continue;
sewardja7203252004-11-26 19:17:47 +00001495
1496 /* Ignore any sections marked as 'always defined'. */
1497 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
sewardje9e16d32004-12-10 13:17:55 +00001498 if (0)
sewardja7203252004-11-26 19:17:47 +00001499 VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
1500 d->fxState[i].offset, d->fxState[i].size );
1501 continue;
1502 }
1503
sewardj95448072004-11-22 20:19:51 +00001504 /* This state element is read or modified. So we need to
sewardje9e16d32004-12-10 13:17:55 +00001505 consider it. If larger than 8 bytes, deal with it in 8-byte
1506 chunks. */
1507 gSz = d->fxState[i].size;
1508 gOff = d->fxState[i].offset;
1509 tl_assert(gSz > 0);
1510 while (True) {
1511 if (gSz == 0) break;
1512 n = gSz <= 8 ? gSz : 8;
1513 /* update 'curr' with UifU of the state slice
1514 gOff .. gOff+n-1 */
1515 tySrc = szToITy( n );
1516 src = assignNew( mce, tySrc,
1517 shadow_GET(mce, gOff, tySrc ) );
1518 here = mkPCastTo( mce, Ity_I32, src );
1519 curr = mkUifU32(mce, here, curr);
1520 gSz -= n;
1521 gOff += n;
1522 }
1523
sewardj95448072004-11-22 20:19:51 +00001524 }
1525
1526 /* Inputs: memory. First set up some info needed regardless of
1527 whether we're doing reads or writes. */
1528 tyAddr = Ity_INVALID;
1529
1530 if (d->mFx != Ifx_None) {
1531 /* Because we may do multiple shadow loads/stores from the same
1532 base address, it's best to do a single test of its
1533 definedness right now. Post-instrumentation optimisation
1534 should remove all but this test. */
1535 tl_assert(d->mAddr);
1536 complainIfUndefined(mce, d->mAddr);
1537
1538 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
1539 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
1540 tl_assert(tyAddr == mce->hWordTy); /* not really right */
1541 }
1542
1543 /* Deal with memory inputs (reads or modifies) */
1544 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
1545 offset = 0;
1546 toDo = d->mSize;
1547 /* chew off 32-bit chunks */
1548 while (toDo >= 4) {
1549 here = mkPCastTo(
1550 mce, Ity_I32,
1551 expr2vbits_LDle ( mce, Ity_I32,
1552 d->mAddr, d->mSize - toDo )
1553 );
1554 curr = mkUifU32(mce, here, curr);
1555 toDo -= 4;
1556 }
1557 /* chew off 16-bit chunks */
1558 while (toDo >= 2) {
1559 here = mkPCastTo(
1560 mce, Ity_I32,
1561 expr2vbits_LDle ( mce, Ity_I16,
1562 d->mAddr, d->mSize - toDo )
1563 );
1564 curr = mkUifU32(mce, here, curr);
1565 toDo -= 2;
1566 }
1567 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
1568 }
1569
1570 /* Whew! So curr is a 32-bit V-value summarising pessimistically
1571 all the inputs to the helper. Now we need to re-distribute the
1572 results to all destinations. */
1573
1574 /* Outputs: the destination temporary, if there is one. */
1575 if (d->tmp != IRTemp_INVALID) {
1576 dst = findShadowTmp(mce, d->tmp);
1577 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
1578 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
1579 }
1580
1581 /* Outputs: guest state that we write or modify. */
1582 for (i = 0; i < d->nFxState; i++) {
1583 tl_assert(d->fxState[i].fx != Ifx_None);
1584 if (d->fxState[i].fx == Ifx_Read)
1585 continue;
sewardja7203252004-11-26 19:17:47 +00001586 /* Ignore any sections marked as 'always defined'. */
1587 if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
1588 continue;
sewardje9e16d32004-12-10 13:17:55 +00001589 /* This state element is written or modified. So we need to
1590 consider it. If larger than 8 bytes, deal with it in 8-byte
1591 chunks. */
1592 gSz = d->fxState[i].size;
1593 gOff = d->fxState[i].offset;
1594 tl_assert(gSz > 0);
1595 while (True) {
1596 if (gSz == 0) break;
1597 n = gSz <= 8 ? gSz : 8;
1598 /* Write suitably-casted 'curr' to the state slice
1599 gOff .. gOff+n-1 */
1600 tyDst = szToITy( n );
1601 do_shadow_PUT( mce, gOff,
1602 NULL, /* original atom */
1603 mkPCastTo( mce, tyDst, curr ) );
1604 gSz -= n;
1605 gOff += n;
1606 }
sewardj95448072004-11-22 20:19:51 +00001607 }
1608
1609 /* Outputs: memory that we write or modify. */
1610 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
1611 offset = 0;
1612 toDo = d->mSize;
1613 /* chew off 32-bit chunks */
1614 while (toDo >= 4) {
1615 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
1616 NULL, /* original data */
1617 mkPCastTo( mce, Ity_I32, curr ) );
1618 toDo -= 4;
1619 }
1620 /* chew off 16-bit chunks */
1621 while (toDo >= 2) {
1622 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
1623 NULL, /* original data */
1624 mkPCastTo( mce, Ity_I16, curr ) );
1625 toDo -= 2;
1626 }
1627 tl_assert(toDo == 0); /* also need to handle 1-byte excess */
1628 }
1629
njn25e49d8e72002-09-23 09:36:25 +00001630}
1631
1632
sewardj95448072004-11-22 20:19:51 +00001633/*------------------------------------------------------------*/
1634/*--- Memcheck main ---*/
1635/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00001636
sewardj95448072004-11-22 20:19:51 +00001637#if 0 /* UNUSED */
1638static Bool isBogusAtom ( IRAtom* at )
njn25e49d8e72002-09-23 09:36:25 +00001639{
sewardj95448072004-11-22 20:19:51 +00001640 ULong n = 0;
1641 IRConst* con;
1642 tl_assert(isAtom(at));
1643 if (at->tag == Iex_Tmp)
1644 return False;
1645 tl_assert(at->tag == Iex_Const);
1646 con = at->Iex.Const.con;
1647 switch (con->tag) {
1648 case Ico_U8: n = (ULong)con->Ico.U8; break;
1649 case Ico_U16: n = (ULong)con->Ico.U16; break;
1650 case Ico_U32: n = (ULong)con->Ico.U32; break;
1651 case Ico_U64: n = (ULong)con->Ico.U64; break;
1652 default: ppIRExpr(at); tl_assert(0);
1653 }
1654 /* VG_(printf)("%llx\n", n); */
1655 return (n == 0xFEFEFEFF
1656 || n == 0x80808080
1657 || n == 0x1010101
1658 || n == 1010100);
1659}
njn25e49d8e72002-09-23 09:36:25 +00001660
sewardj95448072004-11-22 20:19:51 +00001661static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
1662{
1663 Int i;
1664 IRExpr* e;
1665 switch (st->tag) {
1666 case Ist_Tmp:
1667 e = st->Ist.Tmp.data;
1668 switch (e->tag) {
1669 case Iex_Get:
1670 case Iex_Tmp:
1671 return False;
1672 case Iex_Unop:
1673 return isBogusAtom(e->Iex.Unop.arg);
1674 case Iex_Binop:
1675 return isBogusAtom(e->Iex.Binop.arg1)
1676 || isBogusAtom(e->Iex.Binop.arg2);
1677 case Iex_Mux0X:
1678 return isBogusAtom(e->Iex.Mux0X.cond)
1679 || isBogusAtom(e->Iex.Mux0X.expr0)
1680 || isBogusAtom(e->Iex.Mux0X.exprX);
1681 case Iex_LDle:
1682 return isBogusAtom(e->Iex.LDle.addr);
1683 case Iex_CCall:
1684 for (i = 0; e->Iex.CCall.args[i]; i++)
1685 if (isBogusAtom(e->Iex.CCall.args[i]))
1686 return True;
1687 return False;
1688 default:
1689 goto unhandled;
1690 }
1691 case Ist_Put:
1692 return isBogusAtom(st->Ist.Put.data);
1693 case Ist_STle:
1694 return isBogusAtom(st->Ist.STle.addr)
1695 || isBogusAtom(st->Ist.STle.data);
1696 case Ist_Exit:
1697 return isBogusAtom(st->Ist.Exit.cond);
1698 default:
1699 unhandled:
1700 ppIRStmt(st);
1701 VG_(tool_panic)("hasBogusLiterals");
1702 }
1703}
1704#endif /* UNUSED */
njn25e49d8e72002-09-23 09:36:25 +00001705
njn25e49d8e72002-09-23 09:36:25 +00001706
sewardj95448072004-11-22 20:19:51 +00001707IRBB* TL_(instrument) ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
1708{
1709 Bool verboze = False; //True;
njn25e49d8e72002-09-23 09:36:25 +00001710
sewardj95448072004-11-22 20:19:51 +00001711 /* Bool hasBogusLiterals = False; */
njn25e49d8e72002-09-23 09:36:25 +00001712
sewardj95448072004-11-22 20:19:51 +00001713 Int i, j, first_stmt;
1714 IRStmt* st;
1715 MCEnv mce;
njn25e49d8e72002-09-23 09:36:25 +00001716
sewardj95448072004-11-22 20:19:51 +00001717 /* Set up BB */
1718 IRBB* bb = emptyIRBB();
1719 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
1720 bb->next = dopyIRExpr(bb_in->next);
1721 bb->jumpkind = bb_in->jumpkind;
njn25e49d8e72002-09-23 09:36:25 +00001722
sewardj95448072004-11-22 20:19:51 +00001723 /* Set up the running environment. Only .bb is modified as we go
1724 along. */
1725 mce.bb = bb;
1726 mce.layout = layout;
1727 mce.n_originalTmps = bb->tyenv->types_used;
1728 mce.hWordTy = hWordTy;
1729 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
1730 for (i = 0; i < mce.n_originalTmps; i++)
1731 mce.tmpMap[i] = IRTemp_INVALID;
1732
1733 /* Iterate over the stmts. */
1734
1735 for (i = 0; i < bb_in->stmts_used; i++) {
1736 st = bb_in->stmts[i];
1737 if (!st) continue;
1738
1739 tl_assert(isFlatIRStmt(st));
1740
1741 /*
1742 if (!hasBogusLiterals) {
1743 hasBogusLiterals = checkForBogusLiterals(st);
1744 if (hasBogusLiterals) {
1745 VG_(printf)("bogus: ");
1746 ppIRStmt(st);
1747 VG_(printf)("\n");
1748 }
1749 }
1750 */
1751 first_stmt = bb->stmts_used;
1752
1753 if (verboze) {
1754 ppIRStmt(st);
1755 VG_(printf)("\n\n");
1756 }
1757
1758 switch (st->tag) {
1759
1760 case Ist_Tmp:
1761 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
1762 expr2vbits( &mce, st->Ist.Tmp.data) );
njn25e49d8e72002-09-23 09:36:25 +00001763 break;
1764
sewardj95448072004-11-22 20:19:51 +00001765 case Ist_Put:
1766 do_shadow_PUT( &mce,
1767 st->Ist.Put.offset,
1768 st->Ist.Put.data,
1769 NULL /* shadow atom */ );
njn25e49d8e72002-09-23 09:36:25 +00001770 break;
1771
sewardj95448072004-11-22 20:19:51 +00001772 case Ist_PutI:
1773 do_shadow_PUTI( &mce,
1774 st->Ist.PutI.descr,
1775 st->Ist.PutI.ix,
1776 st->Ist.PutI.bias,
1777 st->Ist.PutI.data );
njn25e49d8e72002-09-23 09:36:25 +00001778 break;
1779
sewardj95448072004-11-22 20:19:51 +00001780 case Ist_STle:
1781 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
1782 st->Ist.STle.data,
1783 NULL /* shadow data */ );
njn25e49d8e72002-09-23 09:36:25 +00001784 break;
1785
sewardj95448072004-11-22 20:19:51 +00001786 case Ist_Exit:
1787 /* if (!hasBogusLiterals) */
1788 complainIfUndefined( &mce, st->Ist.Exit.guard );
njn25e49d8e72002-09-23 09:36:25 +00001789 break;
1790
sewardj95448072004-11-22 20:19:51 +00001791 case Ist_Dirty:
1792 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
njn25e49d8e72002-09-23 09:36:25 +00001793 break;
1794
1795 default:
sewardj95448072004-11-22 20:19:51 +00001796 VG_(printf)("\n");
1797 ppIRStmt(st);
1798 VG_(printf)("\n");
1799 VG_(tool_panic)("memcheck: unhandled IRStmt");
1800
1801 } /* switch (st->tag) */
1802
1803 if (verboze) {
1804 for (j = first_stmt; j < bb->stmts_used; j++) {
1805 VG_(printf)(" ");
1806 ppIRStmt(bb->stmts[j]);
1807 VG_(printf)("\n");
1808 }
1809 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00001810 }
sewardj95448072004-11-22 20:19:51 +00001811
1812 addStmtToIRBB(bb, st);
1813
njn25e49d8e72002-09-23 09:36:25 +00001814 }
njn25e49d8e72002-09-23 09:36:25 +00001815
sewardj95448072004-11-22 20:19:51 +00001816 /* Now we need to complain if the jump target is undefined. */
1817 first_stmt = bb->stmts_used;
njn25e49d8e72002-09-23 09:36:25 +00001818
sewardj95448072004-11-22 20:19:51 +00001819 if (verboze) {
1820 VG_(printf)("bb->next = ");
1821 ppIRExpr(bb->next);
1822 VG_(printf)("\n\n");
1823 }
njn25e49d8e72002-09-23 09:36:25 +00001824
sewardj95448072004-11-22 20:19:51 +00001825 complainIfUndefined( &mce, bb->next );
njn25e49d8e72002-09-23 09:36:25 +00001826
sewardj95448072004-11-22 20:19:51 +00001827 if (verboze) {
1828 for (j = first_stmt; j < bb->stmts_used; j++) {
1829 VG_(printf)(" ");
1830 ppIRStmt(bb->stmts[j]);
1831 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00001832 }
sewardj95448072004-11-22 20:19:51 +00001833 VG_(printf)("\n");
njn25e49d8e72002-09-23 09:36:25 +00001834 }
njn25e49d8e72002-09-23 09:36:25 +00001835
sewardj95448072004-11-22 20:19:51 +00001836 return bb;
1837}
njn25e49d8e72002-09-23 09:36:25 +00001838
1839/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00001840/*--- end mc_translate.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00001841/*--------------------------------------------------------------------*/