blob: 34f96439229f0f8f0562eb7025ce955a283eaae6 [file] [log] [blame]
njn25e49d8e72002-09-23 09:36:25 +00001/*--------------------------------------------------------------------*/
2/*--- Part of the MemCheck skin: instrument UCode to perform ---*/
3/*--- memory checking operations. ---*/
4/*--- vg_memcheck_translate.c ---*/
5/*--------------------------------------------------------------------*/
6/*
7 This file is part of Valgrind, an x86 protected-mode emulator
8 designed for debugging and profiling binaries on x86-Unixes.
9
10 Copyright (C) 2000-2002 Julian Seward
11 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
31#include "vg_memcheck_include.h"
32
33/* ---------------------------------------------------------------------
34 Template functions for extending UCode
35 ------------------------------------------------------------------ */
36
37/* Compare this with the restrictions on core instructions in
38 vg_translate.c:VG_(saneUInstr)(). Everything general said there applies
39 here too.
40*/
41Bool SK_(saneExtUInstr)(Bool beforeRA, Bool beforeLiveness, UInstr* u)
42{
43// SSS: duplicating these macros really sucks
44# define LIT0 (u->lit32 == 0)
45# define LIT1 (!(LIT0))
46# define LITm (u->tag1 == Literal ? True : LIT0 )
47# define SZ0 (u->size == 0)
48# define SZi (u->size == 4 || u->size == 2 || u->size == 1)
49# define SZj (u->size == 4 || u->size == 2 || u->size == 1 || u->size == 0)
50# define CC0 (u->flags_r == FlagsEmpty && u->flags_w == FlagsEmpty)
51# define TR1 (beforeRA ? (u->tag1 == TempReg) : (u->tag1 == RealReg))
52# define TR2 (beforeRA ? (u->tag2 == TempReg) : (u->tag2 == RealReg))
53# define A1 (u->tag1 == ArchReg)
54# define A2 (u->tag2 == ArchReg)
55# define L1 (u->tag1 == Literal && u->val1 == 0)
56# define Ls1 (u->tag1 == Lit16)
57# define Ls3 (u->tag3 == Lit16)
58# define TRL1 (TR1 || L1)
59# define TRA1 (TR1 || A1)
60# define N2 (u->tag2 == NoValue)
61# define N3 (u->tag3 == NoValue)
62# define COND0 (u->cond == 0)
63# define EXTRA4b0 (u->extra4b == 0)
64# define SG_WD0 (u->signed_widen == 0)
65# define JMPKIND0 (u->jmpkind == 0)
66# define CCALL0 (u->argc==0 && u->regparms_n==0 && u->has_ret_val==0 && \
67 ( beforeLiveness \
68 ? u->regs_live_after == ALL_RREGS_LIVE \
69 : True ))
70# define XOTHER (COND0 && EXTRA4b0 && SG_WD0 && JMPKIND0 && CCALL0)
71
72 Int n_lits = 0;
73 if (u->tag1 == Literal) n_lits++;
74 if (u->tag2 == Literal) n_lits++;
75 if (u->tag3 == Literal) n_lits++;
76 if (n_lits > 1)
77 return False;
78
79 /* Fields not checked: val1, val2, val3 */
80
81 switch (u->opcode) {
82
83 /* Fields checked: lit32 size flags_r/w tag1 tag2 tag3 (rest) */
84 case LOADV: return LIT0 && SZi && CC0 && TR1 && TR2 && N3 && XOTHER;
85 case STOREV: return LITm && SZi && CC0 && TRL1 && TR2 && N3 && XOTHER;
86 case GETV: return LIT0 && SZi && CC0 && A1 && TR2 && N3 && XOTHER;
87 case PUTV: return LITm && SZi && CC0 && TRL1 && A2 && N3 && XOTHER;
88 case GETVF:
89 case PUTVF: return LIT0 && SZ0 && CC0 && TR1 && N2 && N3 && XOTHER;
90 case TESTV:
91 case SETV: return LIT0 && SZj && CC0 && TRA1 && N2 && N3 && XOTHER;
92 case TAG1: return LIT0 && SZ0 && CC0 && TR1 && N2 && Ls3 && XOTHER;
93 case TAG2: return LIT0 && SZ0 && CC0 && TR1 && TR2 && Ls3 && XOTHER;
94 default:
95 VG_(printf)("unhandled opcode: %u\n", u->opcode);
96 VG_(panic)("SK_(saneExtUInstr): unhandled opcode");
97 }
98# undef LIT0
99# undef LIT1
100# undef LITm
101# undef SZ0
102# undef SZi
103# undef SZj
104# undef CC0
105# undef TR1
106# undef TR2
107# undef A1
108# undef A2
109# undef L1
110# undef Ls1
111# undef Ls3
112# undef TRL1
113# undef TRA1
114# undef N2
115# undef N3
116# undef COND0
117# undef EXTRA4b0
118# undef JMPKIND0
119# undef CCALL0
120# undef XOTHER
121}
122
123static Char* nameOfTagOp ( TagOp h )
124{
125 switch (h) {
126 case Tag_PCast40: return "PCast40";
127 case Tag_PCast20: return "PCast20";
128 case Tag_PCast10: return "PCast10";
129 case Tag_PCast01: return "PCast01";
130 case Tag_PCast02: return "PCast02";
131 case Tag_PCast04: return "PCast04";
132 case Tag_PCast14: return "PCast14";
133 case Tag_PCast12: return "PCast12";
134 case Tag_PCast11: return "PCast11";
135 case Tag_Left4: return "Left4";
136 case Tag_Left2: return "Left2";
137 case Tag_Left1: return "Left1";
138 case Tag_SWiden14: return "SWiden14";
139 case Tag_SWiden24: return "SWiden24";
140 case Tag_SWiden12: return "SWiden12";
141 case Tag_ZWiden14: return "ZWiden14";
142 case Tag_ZWiden24: return "ZWiden24";
143 case Tag_ZWiden12: return "ZWiden12";
144 case Tag_UifU4: return "UifU4";
145 case Tag_UifU2: return "UifU2";
146 case Tag_UifU1: return "UifU1";
147 case Tag_UifU0: return "UifU0";
148 case Tag_DifD4: return "DifD4";
149 case Tag_DifD2: return "DifD2";
150 case Tag_DifD1: return "DifD1";
151 case Tag_ImproveAND4_TQ: return "ImproveAND4_TQ";
152 case Tag_ImproveAND2_TQ: return "ImproveAND2_TQ";
153 case Tag_ImproveAND1_TQ: return "ImproveAND1_TQ";
154 case Tag_ImproveOR4_TQ: return "ImproveOR4_TQ";
155 case Tag_ImproveOR2_TQ: return "ImproveOR2_TQ";
156 case Tag_ImproveOR1_TQ: return "ImproveOR1_TQ";
157 case Tag_DebugFn: return "DebugFn";
158 default: VG_(panic)("vg_nameOfTagOp");
159 }
160}
161
162
163Char* SK_(nameExtUOpcode)(Opcode opc)
164{
165 switch (opc) {
166 case GETVF: return "GETVF";
167 case PUTVF: return "PUTVF";
168 case TAG1: return "TAG1";
169 case TAG2: return "TAG2";
170 case LOADV: return "LOADV";
171 case STOREV: return "STOREV";
172 case GETV: return "GETV";
173 case PUTV: return "PUTV";
174 case TESTV: return "TESTV";
175 case SETV: return "SETV";
176 default:
177 VG_(printf)("unhandled opcode: %u\n", opc);
178 VG_(panic)("SK_(nameExtUOpcode): unhandled case");
179 }
180}
181
182/* ---------------------------------------------------------------------
183 Debugging stuff.
184 ------------------------------------------------------------------ */
185
186void SK_(ppExtUInstr)(UInstr* u)
187{
188 switch (u->opcode) {
189
190 case TAG1:
191 VG_(printf)("\t");
192 VG_(ppUOperand)(u, 1, 4, False);
193 VG_(printf)(" = %s ( ", nameOfTagOp( u->val3 ));
194 VG_(ppUOperand)(u, 1, 4, False);
195 VG_(printf)(" )");
196 break;
197
198 case TAG2:
199 VG_(printf)("\t");
200 VG_(ppUOperand)(u, 2, 4, False);
201 VG_(printf)(" = %s ( ", nameOfTagOp( u->val3 ));
202 VG_(ppUOperand)(u, 1, 4, False);
203 VG_(printf)(", ");
204 VG_(ppUOperand)(u, 2, 4, False);
205 VG_(printf)(" )");
206 break;
207
208 case STOREV: case LOADV:
209 VG_(printf)("\t");
210 VG_(ppUOperand)(u, 1, u->size, u->opcode==LOADV);
211 VG_(printf)(", ");
212 VG_(ppUOperand)(u, 2, u->size, u->opcode==STOREV);
213 break;
214
215 case PUTVF: case GETVF:
216 VG_(printf)("\t");
217 VG_(ppUOperand)(u, 1, 0, False);
218 break;
219
220 case GETV: case PUTV:
221 VG_(printf)("\t");
222 VG_(ppUOperand)(u, 1, u->opcode==PUTV ? 4 : u->size, False);
223 VG_(printf)(", ");
224 VG_(ppUOperand)(u, 2, u->opcode==GETV ? 4 : u->size, False);
225 break;
226
227 case TESTV: case SETV:
228 VG_(printf)("\t");
229 VG_(ppUOperand)(u, 1, u->size, False);
230 break;
231
232 default:
233 VG_(printf)("unhandled opcode: %u\n", u->opcode);
234 VG_(panic)("SK_(ppExtUInstr): unhandled opcode");
235 }
236
237}
238
239Int SK_(getExtRegUsage)(UInstr* u, Tag tag, RegUse* arr)
240{
241# define RD(ono) VG_UINSTR_READS_REG(ono)
242# define WR(ono) VG_UINSTR_WRITES_REG(ono)
243
244 Int n = 0;
245 switch (u->opcode) {
246
247 // JJJ: I don't understand this comment... what about reg alloc? --njn
248
249 /* These sizes are only ever consulted when the instrumentation
250 code is being added, so the following can return
251 manifestly-bogus sizes. */
252
253 case TAG1: RD(1); WR(1); break;
254 case TAG2: RD(1); RD(2); WR(2); break;
255 case LOADV: RD(1); WR(2); break;
256 case STOREV: RD(1); RD(2); break;
257 case GETV: WR(2); break;
258 case PUTV: RD(1); break;
259 case TESTV: RD(1); break;
260 case SETV: WR(1); break;
261 case PUTVF: RD(1); break;
262 case GETVF: WR(1); break;
263
264 default:
265 VG_(printf)("unhandled opcode: %u\n", u->opcode);
266 VG_(panic)("SK_(getExtRegUsage): unhandled opcode");
267 }
268 return n;
269
270# undef RD
271# undef WR
272}
273
274/*------------------------------------------------------------*/
275/*--- New instrumentation machinery. ---*/
276/*------------------------------------------------------------*/
277
278#define uInstr1 VG_(newUInstr1)
279#define uInstr2 VG_(newUInstr2)
280#define uInstr3 VG_(newUInstr3)
281#define uLiteral VG_(setLiteralField)
282#define uCCall VG_(setCCallFields)
283#define newTemp VG_(getNewTemp)
284#define newShadow VG_(getNewShadow)
285
286static
287TagOp get_Tag_ImproveOR_TQ ( Int sz )
288{
289 switch (sz) {
290 case 4: return Tag_ImproveOR4_TQ;
291 case 2: return Tag_ImproveOR2_TQ;
292 case 1: return Tag_ImproveOR1_TQ;
293 default: VG_(panic)("get_Tag_ImproveOR_TQ");
294 }
295}
296
297
298static
299TagOp get_Tag_ImproveAND_TQ ( Int sz )
300{
301 switch (sz) {
302 case 4: return Tag_ImproveAND4_TQ;
303 case 2: return Tag_ImproveAND2_TQ;
304 case 1: return Tag_ImproveAND1_TQ;
305 default: VG_(panic)("get_Tag_ImproveAND_TQ");
306 }
307}
308
309
310static
311TagOp get_Tag_Left ( Int sz )
312{
313 switch (sz) {
314 case 4: return Tag_Left4;
315 case 2: return Tag_Left2;
316 case 1: return Tag_Left1;
317 default: VG_(panic)("get_Tag_Left");
318 }
319}
320
321
322static
323TagOp get_Tag_UifU ( Int sz )
324{
325 switch (sz) {
326 case 4: return Tag_UifU4;
327 case 2: return Tag_UifU2;
328 case 1: return Tag_UifU1;
329 case 0: return Tag_UifU0;
330 default: VG_(panic)("get_Tag_UifU");
331 }
332}
333
334
335static
336TagOp get_Tag_DifD ( Int sz )
337{
338 switch (sz) {
339 case 4: return Tag_DifD4;
340 case 2: return Tag_DifD2;
341 case 1: return Tag_DifD1;
342 default: VG_(panic)("get_Tag_DifD");
343 }
344}
345
346
347static
348TagOp get_Tag_PCast ( Int szs, Int szd )
349{
350 if (szs == 4 && szd == 0) return Tag_PCast40;
351 if (szs == 2 && szd == 0) return Tag_PCast20;
352 if (szs == 1 && szd == 0) return Tag_PCast10;
353 if (szs == 0 && szd == 1) return Tag_PCast01;
354 if (szs == 0 && szd == 2) return Tag_PCast02;
355 if (szs == 0 && szd == 4) return Tag_PCast04;
356 if (szs == 1 && szd == 4) return Tag_PCast14;
357 if (szs == 1 && szd == 2) return Tag_PCast12;
358 if (szs == 1 && szd == 1) return Tag_PCast11;
359 VG_(printf)("get_Tag_PCast(%d,%d)\n", szs, szd);
360 VG_(panic)("get_Tag_PCast");
361}
362
363
364static
365TagOp get_Tag_Widen ( Bool syned, Int szs, Int szd )
366{
367 if (szs == 1 && szd == 2 && syned) return Tag_SWiden12;
368 if (szs == 1 && szd == 2 && !syned) return Tag_ZWiden12;
369
370 if (szs == 1 && szd == 4 && syned) return Tag_SWiden14;
371 if (szs == 1 && szd == 4 && !syned) return Tag_ZWiden14;
372
373 if (szs == 2 && szd == 4 && syned) return Tag_SWiden24;
374 if (szs == 2 && szd == 4 && !syned) return Tag_ZWiden24;
375
376 VG_(printf)("get_Tag_Widen(%d,%d,%d)\n", (Int)syned, szs, szd);
377 VG_(panic)("get_Tag_Widen");
378}
379
380/* Pessimally cast the spec'd shadow from one size to another. */
381static
382void create_PCast ( UCodeBlock* cb, Int szs, Int szd, Int tempreg )
383{
384 if (szs == 0 && szd == 0)
385 return;
386 uInstr3(cb, TAG1, 0, TempReg, tempreg,
387 NoValue, 0,
388 Lit16, get_Tag_PCast(szs,szd));
389}
390
391
392/* Create a signed or unsigned widen of the spec'd shadow from one
393 size to another. The only allowed size transitions are 1->2, 1->4
394 and 2->4. */
395static
396void create_Widen ( UCodeBlock* cb, Bool signed_widen,
397 Int szs, Int szd, Int tempreg )
398{
399 if (szs == szd) return;
400 uInstr3(cb, TAG1, 0, TempReg, tempreg,
401 NoValue, 0,
402 Lit16, get_Tag_Widen(signed_widen,szs,szd));
403}
404
405
406/* Get the condition codes into a new shadow, at the given size. */
407static
408Int create_GETVF ( UCodeBlock* cb, Int sz )
409{
410 Int tt = newShadow(cb);
411 uInstr1(cb, GETVF, 0, TempReg, tt);
412 create_PCast(cb, 0, sz, tt);
413 return tt;
414}
415
416
417/* Save the condition codes from the spec'd shadow. */
418static
419void create_PUTVF ( UCodeBlock* cb, Int sz, Int tempreg )
420{
421 if (sz == 0) {
422 uInstr1(cb, PUTVF, 0, TempReg, tempreg);
423 } else {
424 Int tt = newShadow(cb);
425 uInstr2(cb, MOV, 4, TempReg, tempreg, TempReg, tt);
426 create_PCast(cb, sz, 0, tt);
427 uInstr1(cb, PUTVF, 0, TempReg, tt);
428 }
429}
430
431
432/* Do Left on the spec'd shadow. */
433static
434void create_Left ( UCodeBlock* cb, Int sz, Int tempreg )
435{
436 uInstr3(cb, TAG1, 0,
437 TempReg, tempreg,
438 NoValue, 0,
439 Lit16, get_Tag_Left(sz));
440}
441
442
443/* Do UifU on ts and td, putting the result in td. */
444static
445void create_UifU ( UCodeBlock* cb, Int sz, Int ts, Int td )
446{
447 uInstr3(cb, TAG2, 0, TempReg, ts, TempReg, td,
448 Lit16, get_Tag_UifU(sz));
449}
450
451
452/* Do DifD on ts and td, putting the result in td. */
453static
454void create_DifD ( UCodeBlock* cb, Int sz, Int ts, Int td )
455{
456 uInstr3(cb, TAG2, 0, TempReg, ts, TempReg, td,
457 Lit16, get_Tag_DifD(sz));
458}
459
460
461/* Do HelpAND on value tval and tag tqqq, putting the result in
462 tqqq. */
463static
464void create_ImproveAND_TQ ( UCodeBlock* cb, Int sz, Int tval, Int tqqq )
465{
466 uInstr3(cb, TAG2, 0, TempReg, tval, TempReg, tqqq,
467 Lit16, get_Tag_ImproveAND_TQ(sz));
468}
469
470
471/* Do HelpOR on value tval and tag tqqq, putting the result in
472 tqqq. */
473static
474void create_ImproveOR_TQ ( UCodeBlock* cb, Int sz, Int tval, Int tqqq )
475{
476 uInstr3(cb, TAG2, 0, TempReg, tval, TempReg, tqqq,
477 Lit16, get_Tag_ImproveOR_TQ(sz));
478}
479
480
481/* Get the shadow for an operand described by (tag, val). Emit code
482 to do this and return the identity of the shadow holding the
483 result. The result tag is always copied into a new shadow, so it
484 can be modified without trashing the original.*/
485static
486Int /* TempReg */ getOperandShadow ( UCodeBlock* cb,
487 Int sz, Int tag, Int val )
488{
489 Int sh;
490 sh = newShadow(cb);
491 if (tag == TempReg) {
492 uInstr2(cb, MOV, 4, TempReg, SHADOW(val), TempReg, sh);
493 return sh;
494 }
495 if (tag == Literal) {
496 uInstr1(cb, SETV, sz, TempReg, sh);
497 return sh;
498 }
499 if (tag == ArchReg) {
500 uInstr2(cb, GETV, sz, ArchReg, val, TempReg, sh);
501 return sh;
502 }
503 VG_(panic)("getOperandShadow");
504}
505
506/* Create and return an instrumented version of cb_in. Free cb_in
507 before returning. */
508static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in )
509{
510 UCodeBlock* cb;
511 Int i, j;
512 UInstr* u_in;
513 Int qs, qd, qt, qtt;
514 cb = VG_(allocCodeBlock)();
515 cb->nextTemp = cb_in->nextTemp;
516
517 for (i = 0; i < cb_in->used; i++) {
518 qs = qd = qt = qtt = INVALID_TEMPREG;
519 u_in = &cb_in->instrs[i];
520
521 switch (u_in->opcode) {
522
523 case NOP:
524 break;
525
526 case INCEIP:
527 VG_(copyUInstr)(cb, u_in);
528 break;
529
530 /* Loads and stores. Test the V bits for the address. 24
531 Mar 02: since the address is A-checked anyway, there's not
532 really much point in doing the V-check too, unless you
533 think that you might use addresses which are undefined but
534 still addressible. Hence the optionalisation of the V
535 check.
536
537 The LOADV/STOREV does an addressibility check for the
538 address. */
539
540 case LOAD:
541 if (SK_(clo_check_addrVs)) {
542 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val1));
543 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val1));
544 }
545 uInstr2(cb, LOADV, u_in->size,
546 TempReg, u_in->val1,
547 TempReg, SHADOW(u_in->val2));
548 VG_(copyUInstr)(cb, u_in);
549 break;
550
551 case STORE:
552 if (SK_(clo_check_addrVs)) {
553 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val2));
554 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val2));
555 }
556 uInstr2(cb, STOREV, u_in->size,
557 TempReg, SHADOW(u_in->val1),
558 TempReg, u_in->val2);
559 VG_(copyUInstr)(cb, u_in);
560 break;
561
562 /* Moving stuff around. Make the V bits follow accordingly,
563 but don't do anything else. */
564
565 case GET:
566 uInstr2(cb, GETV, u_in->size,
567 ArchReg, u_in->val1,
568 TempReg, SHADOW(u_in->val2));
569 VG_(copyUInstr)(cb, u_in);
570 break;
571
572 case PUT:
573 uInstr2(cb, PUTV, u_in->size,
574 TempReg, SHADOW(u_in->val1),
575 ArchReg, u_in->val2);
576 VG_(copyUInstr)(cb, u_in);
577 break;
578
579 case GETF:
580 /* This is not the smartest way to do it, but should work. */
581 qd = create_GETVF(cb, u_in->size);
582 uInstr2(cb, MOV, 4, TempReg, qd, TempReg, SHADOW(u_in->val1));
583 VG_(copyUInstr)(cb, u_in);
584 break;
585
586 case PUTF:
587 create_PUTVF(cb, u_in->size, SHADOW(u_in->val1));
588 VG_(copyUInstr)(cb, u_in);
589 break;
590
591 case MOV:
592 switch (u_in->tag1) {
593 case TempReg:
594 uInstr2(cb, MOV, 4,
595 TempReg, SHADOW(u_in->val1),
596 TempReg, SHADOW(u_in->val2));
597 break;
598 case Literal:
599 uInstr1(cb, SETV, u_in->size,
600 TempReg, SHADOW(u_in->val2));
601 break;
602 default:
603 VG_(panic)("memcheck_instrument: MOV");
604 }
605 VG_(copyUInstr)(cb, u_in);
606 break;
607
608 /* Special case of add, where one of the operands is a literal.
609 lea1(t) = t + some literal.
610 Therefore: lea1#(qa) = left(qa)
611 */
612 case LEA1:
613 vg_assert(u_in->size == 4 && !VG_(anyFlagUse)(u_in));
614 qs = SHADOW(u_in->val1);
615 qd = SHADOW(u_in->val2);
616 uInstr2(cb, MOV, 4, TempReg, qs, TempReg, qd);
617 create_Left(cb, u_in->size, qd);
618 VG_(copyUInstr)(cb, u_in);
619 break;
620
621 /* Another form of add.
622 lea2(ts,tt,shift) = ts + (tt << shift); shift is a literal
623 and is 0,1,2 or 3.
624 lea2#(qs,qt) = left(qs `UifU` (qt << shift)).
625 Note, subtly, that the shift puts zeroes at the bottom of qt,
626 meaning Valid, since the corresponding shift of tt puts
627 zeroes at the bottom of tb.
628 */
629 case LEA2: {
630 Int shift;
631 vg_assert(u_in->size == 4 && !VG_(anyFlagUse)(u_in));
632 switch (u_in->extra4b) {
633 case 1: shift = 0; break;
634 case 2: shift = 1; break;
635 case 4: shift = 2; break;
636 case 8: shift = 3; break;
637 default: VG_(panic)( "memcheck_instrument(LEA2)" );
638 }
639 qs = SHADOW(u_in->val1);
640 qt = SHADOW(u_in->val2);
641 qd = SHADOW(u_in->val3);
642 uInstr2(cb, MOV, 4, TempReg, qt, TempReg, qd);
643 if (shift > 0) {
644 uInstr2(cb, SHL, 4, Literal, 0, TempReg, qd);
645 uLiteral(cb, shift);
646 }
647 create_UifU(cb, 4, qs, qd);
648 create_Left(cb, u_in->size, qd);
649 VG_(copyUInstr)(cb, u_in);
650 break;
651 }
652
653 /* inc#/dec#(qd) = q `UifU` left(qd) = left(qd) */
654 case INC: case DEC:
655 qd = SHADOW(u_in->val1);
656 create_Left(cb, u_in->size, qd);
657 if (u_in->flags_w != FlagsEmpty)
658 create_PUTVF(cb, u_in->size, qd);
659 VG_(copyUInstr)(cb, u_in);
660 break;
661
662 /* This is a HACK (approximation :-) */
663 /* rcl#/rcr#(qs,qd)
664 = let q0 = pcast-sz-0(qd) `UifU` pcast-sz-0(qs) `UifU` eflags#
665 eflags# = q0
666 qd =pcast-0-sz(q0)
667 Ie, cast everything down to a single bit, then back up.
668 This assumes that any bad bits infect the whole word and
669 the eflags.
670 */
671 case RCL: case RCR:
672 vg_assert(u_in->flags_r != FlagsEmpty);
673 /* The following assertion looks like it makes sense, but is
674 actually wrong. Consider this:
675 rcll %eax
676 imull %eax, %eax
677 The rcll writes O and C but so does the imull, so the O and C
678 write of the rcll is annulled by the prior improvement pass.
679 Noticed by Kevin Ryde <user42@zip.com.au>
680 */
681 /* vg_assert(u_in->flags_w != FlagsEmpty); */
682 qs = getOperandShadow(cb, u_in->size, u_in->tag1, u_in->val1);
683 /* We can safely modify qs; cast it to 0-size. */
684 create_PCast(cb, u_in->size, 0, qs);
685 qd = SHADOW(u_in->val2);
686 create_PCast(cb, u_in->size, 0, qd);
687 /* qs is cast-to-0(shift count#), and qd is cast-to-0(value#). */
688 create_UifU(cb, 0, qs, qd);
689 /* qs is now free; reuse it for the flag definedness. */
690 qs = create_GETVF(cb, 0);
691 create_UifU(cb, 0, qs, qd);
692 create_PUTVF(cb, 0, qd);
693 create_PCast(cb, 0, u_in->size, qd);
694 VG_(copyUInstr)(cb, u_in);
695 break;
696
697 /* for OP in shl shr sar rol ror
698 (qs is shift count#, qd is value to be OP#d)
699 OP(ts,td)
700 OP#(qs,qd)
701 = pcast-1-sz(qs) `UifU` OP(ts,qd)
702 So we apply OP to the tag bits too, and then UifU with
703 the shift count# to take account of the possibility of it
704 being undefined.
705
706 A bit subtle:
707 ROL/ROR rearrange the tag bits as per the value bits.
708 SHL/SHR shifts zeroes into the value, and corresponding
709 zeroes indicating Definedness into the tag.
710 SAR copies the top bit of the value downwards, and therefore
711 SAR also copies the definedness of the top bit too.
712 So in all five cases, we just apply the same op to the tag
713 bits as is applied to the value bits. Neat!
714 */
715 case SHL:
716 case SHR: case SAR:
717 case ROL: case ROR: {
718 Int t_amount = INVALID_TEMPREG;
719 vg_assert(u_in->tag1 == TempReg || u_in->tag1 == Literal);
720 vg_assert(u_in->tag2 == TempReg);
721 qd = SHADOW(u_in->val2);
722
723 /* Make qs hold shift-count# and make
724 t_amount be a TempReg holding the shift count. */
725 if (u_in->tag1 == Literal) {
726 t_amount = newTemp(cb);
727 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_amount);
728 uLiteral(cb, u_in->lit32);
729 qs = SHADOW(t_amount);
730 uInstr1(cb, SETV, 1, TempReg, qs);
731 } else {
732 t_amount = u_in->val1;
733 qs = SHADOW(u_in->val1);
734 }
735
736 uInstr2(cb, u_in->opcode,
737 u_in->size,
738 TempReg, t_amount,
739 TempReg, qd);
740 qt = newShadow(cb);
741 uInstr2(cb, MOV, 4, TempReg, qs, TempReg, qt);
742 create_PCast(cb, 1, u_in->size, qt);
743 create_UifU(cb, u_in->size, qt, qd);
744 VG_(copyUInstr)(cb, u_in);
745 break;
746 }
747
748 /* One simple tag operation. */
749 case WIDEN:
750 vg_assert(u_in->tag1 == TempReg);
751 create_Widen(cb, u_in->signed_widen, u_in->extra4b, u_in->size,
752 SHADOW(u_in->val1));
753 VG_(copyUInstr)(cb, u_in);
754 break;
755
756 /* not#(x) = x (since bitwise independent) */
757 case NOT:
758 vg_assert(u_in->tag1 == TempReg);
759 VG_(copyUInstr)(cb, u_in);
760 break;
761
762 /* neg#(x) = left(x) (derivable from case for SUB) */
763 case NEG:
764 vg_assert(u_in->tag1 == TempReg);
765 create_Left(cb, u_in->size, SHADOW(u_in->val1));
766 VG_(copyUInstr)(cb, u_in);
767 break;
768
769 /* bswap#(x) = bswap(x) */
770 case BSWAP:
771 vg_assert(u_in->tag1 == TempReg);
772 vg_assert(u_in->size == 4);
773 qd = SHADOW(u_in->val1);
774 uInstr1(cb, BSWAP, 4, TempReg, qd);
775 VG_(copyUInstr)(cb, u_in);
776 break;
777
778 /* cc2val#(qd) = pcast-0-to-size(eflags#) */
779 case CC2VAL:
780 vg_assert(u_in->tag1 == TempReg);
781 vg_assert(u_in->flags_r != FlagsEmpty);
782 qt = create_GETVF(cb, u_in->size);
783 uInstr2(cb, MOV, 4, TempReg, qt, TempReg, SHADOW(u_in->val1));
784 VG_(copyUInstr)(cb, u_in);
785 break;
786
787 /* cmov#(qs,qd) = cmov(qs,qd)
788 That is, do the cmov of tags using the same flags as for
789 the data (obviously). However, first do a test on the
790 validity of the flags.
791 */
792 case CMOV:
793 vg_assert(u_in->size == 4);
794 vg_assert(u_in->tag1 == TempReg);
795 vg_assert(u_in->tag2 == TempReg);
796 vg_assert(u_in->flags_r != FlagsEmpty);
797 vg_assert(u_in->flags_w == FlagsEmpty);
798 qs = SHADOW(u_in->val1);
799 qd = SHADOW(u_in->val2);
800 qt = create_GETVF(cb, 0);
801 uInstr1(cb, TESTV, 0, TempReg, qt);
802 /* qt should never be referred to again. Nevertheless
803 ... */
804 uInstr1(cb, SETV, 0, TempReg, qt);
805
806 uInstr2(cb, CMOV, 4, TempReg, qs, TempReg, qd);
807 LAST_UINSTR(cb).cond = u_in->cond;
808 LAST_UINSTR(cb).flags_r = u_in->flags_r;
809
810 VG_(copyUInstr)(cb, u_in);
811 break;
812
813 /* add#/sub#(qs,qd)
814 = qs `UifU` qd `UifU` left(qs) `UifU` left(qd)
815 = left(qs) `UifU` left(qd)
816 = left(qs `UifU` qd)
817 adc#/sbb#(qs,qd)
818 = left(qs `UifU` qd) `UifU` pcast(eflags#)
819 Second arg (dest) is TempReg.
820 First arg (src) is Literal or TempReg or ArchReg.
821 */
822 case ADD: case SUB:
823 case ADC: case SBB:
824 qd = SHADOW(u_in->val2);
825 qs = getOperandShadow(cb, u_in->size, u_in->tag1, u_in->val1);
826 create_UifU(cb, u_in->size, qs, qd);
827 create_Left(cb, u_in->size, qd);
828 if (u_in->opcode == ADC || u_in->opcode == SBB) {
829 vg_assert(u_in->flags_r != FlagsEmpty);
830 qt = create_GETVF(cb, u_in->size);
831 create_UifU(cb, u_in->size, qt, qd);
832 }
833 if (u_in->flags_w != FlagsEmpty) {
834 create_PUTVF(cb, u_in->size, qd);
835 }
836 VG_(copyUInstr)(cb, u_in);
837 break;
838
839 /* xor#(qs,qd) = qs `UifU` qd */
840 case XOR:
841 qd = SHADOW(u_in->val2);
842 qs = getOperandShadow(cb, u_in->size, u_in->tag1, u_in->val1);
843 create_UifU(cb, u_in->size, qs, qd);
844 if (u_in->flags_w != FlagsEmpty) {
845 create_PUTVF(cb, u_in->size, qd);
846 }
847 VG_(copyUInstr)(cb, u_in);
848 break;
849
850 /* and#/or#(qs,qd)
851 = (qs `UifU` qd) `DifD` improve(vs,qs)
852 `DifD` improve(vd,qd)
853 where improve is the relevant one of
854 Improve{AND,OR}_TQ
855 Use the following steps, with qt as a temp:
856 qt = improve(vd,qd)
857 qd = qs `UifU` qd
858 qd = qt `DifD` qd
859 qt = improve(vs,qs)
860 qd = qt `DifD` qd
861 */
862 case AND: case OR:
863 vg_assert(u_in->tag1 == TempReg);
864 vg_assert(u_in->tag2 == TempReg);
865 qd = SHADOW(u_in->val2);
866 qs = SHADOW(u_in->val1);
867 qt = newShadow(cb);
868
869 /* qt = improve(vd,qd) */
870 uInstr2(cb, MOV, 4, TempReg, qd, TempReg, qt);
871 if (u_in->opcode == AND)
872 create_ImproveAND_TQ(cb, u_in->size, u_in->val2, qt);
873 else
874 create_ImproveOR_TQ(cb, u_in->size, u_in->val2, qt);
875 /* qd = qs `UifU` qd */
876 create_UifU(cb, u_in->size, qs, qd);
877 /* qd = qt `DifD` qd */
878 create_DifD(cb, u_in->size, qt, qd);
879 /* qt = improve(vs,qs) */
880 uInstr2(cb, MOV, 4, TempReg, qs, TempReg, qt);
881 if (u_in->opcode == AND)
882 create_ImproveAND_TQ(cb, u_in->size, u_in->val1, qt);
883 else
884 create_ImproveOR_TQ(cb, u_in->size, u_in->val1, qt);
885 /* qd = qt `DifD` qd */
886 create_DifD(cb, u_in->size, qt, qd);
887 /* So, finally qd is the result tag. */
888 if (u_in->flags_w != FlagsEmpty) {
889 create_PUTVF(cb, u_in->size, qd);
890 }
891 VG_(copyUInstr)(cb, u_in);
892 break;
893
894 /* Machinery to do with supporting CALLM. Copy the start and
895 end markers only to make the result easier to read
896 (debug); they generate no code and have no effect.
897 */
898 case CALLM_S: case CALLM_E:
899 VG_(copyUInstr)(cb, u_in);
900 break;
901
902 /* Copy PUSH and POP verbatim. Arg/result absval
903 calculations are done when the associated CALL is
904 processed. CLEAR has no effect on absval calculations but
905 needs to be copied.
906 */
907 case PUSH: case POP: case CLEAR:
908 VG_(copyUInstr)(cb, u_in);
909 break;
910
911 /* In short:
912 callm#(a1# ... an#) = (a1# `UifU` ... `UifU` an#)
913 We have to decide on a size to do the computation at,
914 although the choice doesn't affect correctness. We will
915 do a pcast to the final size anyway, so the only important
916 factor is to choose a size which minimises the total
917 number of casts needed. Valgrind: just use size 0,
918 regardless. It may not be very good for performance
919 but does simplify matters, mainly by reducing the number
920 of different pessimising casts which have to be implemented.
921 */
922 case CALLM: {
923 UInstr* uu;
924 Bool res_used;
925
926 /* Now generate the code. Get the final result absval
927 into qt. */
928 qt = newShadow(cb);
929 qtt = newShadow(cb);
930 uInstr1(cb, SETV, 0, TempReg, qt);
931 for (j = i-1; cb_in->instrs[j].opcode != CALLM_S; j--) {
932 uu = & cb_in->instrs[j];
933 if (uu->opcode != PUSH) continue;
934 /* cast via a temporary */
935 uInstr2(cb, MOV, 4, TempReg, SHADOW(uu->val1),
936 TempReg, qtt);
937 create_PCast(cb, uu->size, 0, qtt);
938 create_UifU(cb, 0, qtt, qt);
939 }
940 /* Remembering also that flags read count as inputs. */
941 if (u_in->flags_r != FlagsEmpty) {
942 qtt = create_GETVF(cb, 0);
943 create_UifU(cb, 0, qtt, qt);
944 }
945
946 /* qt now holds the result tag. If any results from the
947 call are used, either by fetching with POP or
948 implicitly by writing the flags, we copy the result
949 absval to the relevant location. If not used, the call
950 must have been for its side effects, so we test qt here
951 and now. Note that this assumes that all values
952 removed by POP continue to be live. So dead args
953 *must* be removed with CLEAR, not by POPping them into
954 a dummy tempreg.
955 */
956 res_used = False;
957 for (j = i+1; cb_in->instrs[j].opcode != CALLM_E; j++) {
958 uu = & cb_in->instrs[j];
959 if (uu->opcode != POP) continue;
960 /* Cast via a temp. */
961 uInstr2(cb, MOV, 4, TempReg, qt, TempReg, qtt);
962 create_PCast(cb, 0, uu->size, qtt);
963 uInstr2(cb, MOV, 4, TempReg, qtt,
964 TempReg, SHADOW(uu->val1));
965 res_used = True;
966 }
967 if (u_in->flags_w != FlagsEmpty) {
968 create_PUTVF(cb, 0, qt);
969 res_used = True;
970 }
971 if (!res_used) {
972 uInstr1(cb, TESTV, 0, TempReg, qt);
973 /* qt should never be referred to again. Nevertheless
974 ... */
975 uInstr1(cb, SETV, 0, TempReg, qt);
976 }
977 VG_(copyUInstr)(cb, u_in);
978 break;
979 }
980 /* Whew ... */
981
982 case JMP:
983 if (u_in->tag1 == TempReg) {
984 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val1));
985 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val1));
986 } else {
987 vg_assert(u_in->tag1 == Literal);
988 }
989 if (u_in->cond != CondAlways) {
990 vg_assert(u_in->flags_r != FlagsEmpty);
991 qt = create_GETVF(cb, 0);
992 uInstr1(cb, TESTV, 0, TempReg, qt);
993 /* qt should never be referred to again. Nevertheless
994 ... */
995 uInstr1(cb, SETV, 0, TempReg, qt);
996 }
997 VG_(copyUInstr)(cb, u_in);
998 break;
999
1000 case JIFZ:
1001 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val1));
1002 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val1));
1003 VG_(copyUInstr)(cb, u_in);
1004 break;
1005
1006 /* Emit a check on the address used. The value loaded into the
1007 FPU is checked by the call to fpu_{read/write}_check(). */
1008 case FPU_R: case FPU_W: {
1009 Int t_size = INVALID_TEMPREG;
1010
1011 vg_assert(u_in->tag2 == TempReg);
1012 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val2));
1013 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val2));
1014
1015 t_size = newTemp(cb);
1016 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
1017 uLiteral(cb, u_in->size);
1018 uInstr2(cb, CCALL, 0, TempReg, u_in->val2, TempReg, t_size);
1019 uCCall(cb,
1020 u_in->opcode==FPU_R ? (Addr) & SK_(fpu_read_check)
1021 : (Addr) & SK_(fpu_write_check),
1022 2, 2, False);
1023
1024 VG_(copyUInstr)(cb, u_in);
1025 break;
1026 }
1027
1028 /* For FPU insns not referencing memory, just copy thru. */
1029 case FPU:
1030 VG_(copyUInstr)(cb, u_in);
1031 break;
1032
1033 default:
1034 VG_(ppUInstr)(0, u_in);
1035 VG_(panic)( "memcheck_instrument: unhandled case");
1036
1037 } /* end of switch (u_in->opcode) */
1038
1039 } /* end of for loop */
1040
1041 VG_(freeCodeBlock)(cb_in);
1042 return cb;
1043}
1044
1045/*------------------------------------------------------------*/
1046/*--- Clean up mem check instrumentation. ---*/
1047/*------------------------------------------------------------*/
1048
1049Bool VG_(clo_memcheck_codegen) = False;
1050
1051#define dis VG_(print_codegen)
1052
1053
1054#define VGC_IS_SHADOW(tempreg) ((tempreg % 2) == 1)
1055#define VGC_UNDEF ((UChar)100)
1056#define VGC_VALUE ((UChar)101)
1057
1058#define NOP_no_msg(uu) \
1059 do { VG_(newNOP)(uu); } while (False)
1060
1061#define NOP_tag1_op(uu) \
1062 do { VG_(newNOP)(uu); \
1063 if (dis) \
1064 VG_(printf)(" at %2d: delete %s due to defd arg\n", \
1065 i, nameOfTagOp(u->val3)); \
1066 } while (False)
1067
1068#define SETV_tag1_op(uu,newsz) \
1069 do { uu->opcode = SETV; \
1070 uu->size = newsz; \
1071 uu->tag2 = uu->tag3 = NoValue; \
1072 if (dis) \
1073 VG_(printf)(" at %2d: convert %s to SETV%d " \
1074 "due to defd arg\n", \
1075 i, nameOfTagOp(u->val3), newsz); \
1076 } while (False)
1077
1078
1079
1080/* Run backwards and delete SETVs on shadow temps for which the next
1081 action is a write. Needs an env saying whether or not the next
1082 action is a write. The supplied UCodeBlock is destructively
1083 modified.
1084*/
1085static void vg_delete_redundant_SETVs ( UCodeBlock* cb )
1086{
1087 Int i, j, k;
1088 Int n_temps = cb->nextTemp;
1089 Bool* next_is_write;
1090 UInstr* u;
1091 RegUse tempUse[3];
1092
1093 if (n_temps == 0) return;
1094
1095 next_is_write = VG_(malloc)(n_temps * sizeof(Bool));
1096
1097 for (i = 0; i < n_temps; i++) next_is_write[i] = True;
1098
1099 for (i = cb->used-1; i >= 0; i--) {
1100 u = &cb->instrs[i];
1101
1102 /* If we're not checking address V bits, there will be a lot of
1103 GETVs, TAG1s and TAG2s calculating values which are never
1104 used. These first three cases get rid of them. */
1105
1106 if (u->opcode == GETV && VGC_IS_SHADOW(u->val2)
1107 && next_is_write[u->val2]
1108 && !SK_(clo_check_addrVs)) {
1109 VG_(newNOP)(u);
1110 if (dis)
1111 VG_(printf)(" at %2d: delete GETV\n", i);
1112 } else
1113
1114 if (u->opcode == TAG1 && VGC_IS_SHADOW(u->val1)
1115 && next_is_write[u->val1]
1116 && !SK_(clo_check_addrVs)) {
1117 VG_(newNOP)(u);
1118 if (dis)
1119 VG_(printf)(" at %2d: delete TAG1\n", i);
1120 } else
1121
1122 if (u->opcode == TAG2 && VGC_IS_SHADOW(u->val2)
1123 && next_is_write[u->val2]
1124 && !SK_(clo_check_addrVs)) {
1125 VG_(newNOP)(u);
1126 if (dis)
1127 VG_(printf)(" at %2d: delete TAG2\n", i);
1128 } else
1129
1130 /* We do the rest of these regardless of whether or not
1131 addresses are V-checked. */
1132
1133 if (u->opcode == MOV && VGC_IS_SHADOW(u->val2)
1134 && next_is_write[u->val2]) {
1135 /* This MOV is pointless because the target is dead at this
1136 point. Delete it. */
1137 VG_(newNOP)(u);
1138 if (dis)
1139 VG_(printf)(" at %2d: delete MOV\n", i);
1140 } else
1141
1142 if (u->opcode == SETV) {
1143 if (u->tag1 == TempReg) {
1144 vg_assert(VGC_IS_SHADOW(u->val1));
1145 if (next_is_write[u->val1]) {
1146 /* This write is pointless, so annul it. */
1147 VG_(newNOP)(u);
1148 if (dis)
1149 VG_(printf)(" at %2d: delete SETV\n", i);
1150 } else {
1151 /* This write has a purpose; don't annul it, but do
1152 notice that we did it. */
1153 next_is_write[u->val1] = True;
1154 }
1155
1156 }
1157
1158 } else {
1159 /* Find out what this insn does to the temps. */
1160 k = VG_(getRegUsage)(u, TempReg, &tempUse[0]);
1161 vg_assert(k <= 3);
1162 for (j = k-1; j >= 0; j--) {
1163 next_is_write[ tempUse[j].num ]
1164 = tempUse[j].isWrite;
1165 }
1166 }
1167 }
1168}
1169
1170
1171/* Run forwards, propagating and using the is-completely-defined
1172 property. This removes a lot of redundant tag-munging code.
1173 Unfortunately it requires intimate knowledge of how each uinstr and
1174 tagop modifies its arguments. This duplicates knowledge of uinstr
1175 tempreg uses embodied in VG_(getRegUsage)(), which is unfortunate.
1176 The supplied UCodeBlock* is modified in-place.
1177
1178 For each value temp, def[] should hold VGC_VALUE.
1179
1180 For each shadow temp, def[] may hold 4,2,1 or 0 iff that shadow is
1181 definitely known to be fully defined at that size. In all other
1182 circumstances a shadow's def[] entry is VGC_UNDEF, meaning possibly
1183 undefined. In cases of doubt, VGC_UNDEF is always safe.
1184*/
1185static void vg_propagate_definedness ( UCodeBlock* cb )
1186{
1187 Int i, j, k, t;
1188 Int n_temps = cb->nextTemp;
1189 UChar* def;
1190 UInstr* u;
1191 RegUse tempUse[3];
1192
1193 if (n_temps == 0) return;
1194
1195 def = VG_(malloc)(n_temps * sizeof(UChar));
1196
1197 for (i = 0; i < n_temps; i++)
1198 def[i] = VGC_IS_SHADOW(i) ? VGC_UNDEF : VGC_VALUE;
1199
1200 /* Run forwards, detecting and using the all-defined property. */
1201
1202 for (i = 0; i < cb->used; i++) {
1203 u = &cb->instrs[i];
1204 switch (u->opcode) {
1205
1206 /* Tag-handling uinstrs. */
1207
1208 /* Deal with these quickly. */
1209 case NOP:
1210 case INCEIP:
1211 break;
1212
1213 /* Make a tag defined. */
1214 case SETV:
1215 vg_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1216 def[u->val1] = u->size;
1217 break;
1218
1219 /* Check definedness of a tag. */
1220 case TESTV:
1221 vg_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1222 if (def[u->val1] <= 4) {
1223 vg_assert(def[u->val1] == u->size);
1224 NOP_no_msg(u);
1225 if (dis)
1226 VG_(printf)(" at %2d: delete TESTV on defd arg\n", i);
1227 }
1228 break;
1229
1230 /* Applies to both values and tags. Propagate Definedness
1231 property through copies. Note that this isn't optional;
1232 we *have* to do this to keep def[] correct. */
1233 case MOV:
1234 vg_assert(u->tag2 == TempReg);
1235 if (u->tag1 == TempReg) {
1236 if (VGC_IS_SHADOW(u->val1)) {
1237 vg_assert(VGC_IS_SHADOW(u->val2));
1238 def[u->val2] = def[u->val1];
1239 }
1240 }
1241 break;
1242
1243 case PUTV:
1244 vg_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1245 if (def[u->val1] <= 4) {
1246 vg_assert(def[u->val1] == u->size);
1247 u->tag1 = Literal;
1248 u->val1 = 0;
1249 switch (u->size) {
1250 case 4: u->lit32 = 0x00000000; break;
1251 case 2: u->lit32 = 0xFFFF0000; break;
1252 case 1: u->lit32 = 0xFFFFFF00; break;
1253 default: VG_(panic)("vg_cleanup(PUTV)");
1254 }
1255 if (dis)
1256 VG_(printf)(
1257 " at %2d: propagate definedness into PUTV\n", i);
1258 }
1259 break;
1260
1261 case STOREV:
1262 vg_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1263 if (def[u->val1] <= 4) {
1264 vg_assert(def[u->val1] == u->size);
1265 u->tag1 = Literal;
1266 u->val1 = 0;
1267 switch (u->size) {
1268 case 4: u->lit32 = 0x00000000; break;
1269 case 2: u->lit32 = 0xFFFF0000; break;
1270 case 1: u->lit32 = 0xFFFFFF00; break;
1271 default: VG_(panic)("vg_cleanup(STOREV)");
1272 }
1273 if (dis)
1274 VG_(printf)(
1275 " at %2d: propagate definedness into STandV\n", i);
1276 }
1277 break;
1278
1279 /* Nothing interesting we can do with this, I think. */
1280 case PUTVF:
1281 break;
1282
1283 /* Tag handling operations. */
1284 case TAG2:
1285 vg_assert(u->tag2 == TempReg && VGC_IS_SHADOW(u->val2));
1286 vg_assert(u->tag3 == Lit16);
1287 /* Ultra-paranoid "type" checking. */
1288 switch (u->val3) {
1289 case Tag_ImproveAND4_TQ: case Tag_ImproveAND2_TQ:
1290 case Tag_ImproveAND1_TQ: case Tag_ImproveOR4_TQ:
1291 case Tag_ImproveOR2_TQ: case Tag_ImproveOR1_TQ:
1292 vg_assert(u->tag1 == TempReg && !VGC_IS_SHADOW(u->val1));
1293 break;
1294 default:
1295 vg_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1296 break;
1297 }
1298 switch (u->val3) {
1299 Int sz;
1300 case Tag_UifU4:
1301 sz = 4; goto do_UifU;
1302 case Tag_UifU2:
1303 sz = 2; goto do_UifU;
1304 case Tag_UifU1:
1305 sz = 1; goto do_UifU;
1306 case Tag_UifU0:
1307 sz = 0; goto do_UifU;
1308 do_UifU:
1309 vg_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1310 vg_assert(u->tag2 == TempReg && VGC_IS_SHADOW(u->val2));
1311 if (def[u->val1] <= 4) {
1312 /* UifU. The first arg is defined, so result is
1313 simply second arg. Delete this operation. */
1314 vg_assert(def[u->val1] == sz);
1315 NOP_no_msg(u);
1316 if (dis)
1317 VG_(printf)(
1318 " at %2d: delete UifU%d due to defd arg1\n",
1319 i, sz);
1320 }
1321 else
1322 if (def[u->val2] <= 4) {
1323 /* UifU. The second arg is defined, so result is
1324 simply first arg. Copy to second. */
1325 vg_assert(def[u->val2] == sz);
1326 u->opcode = MOV;
1327 u->size = 4;
1328 u->tag3 = NoValue;
1329 def[u->val2] = def[u->val1];
1330 if (dis)
1331 VG_(printf)(
1332 " at %2d: change UifU%d to MOV due to defd"
1333 " arg2\n",
1334 i, sz);
1335 }
1336 break;
1337 case Tag_ImproveAND4_TQ:
1338 sz = 4; goto do_ImproveAND;
1339 case Tag_ImproveAND1_TQ:
1340 sz = 1; goto do_ImproveAND;
1341 do_ImproveAND:
1342 /* Implements Q = T OR Q. So if Q is entirely defined,
1343 ie all 0s, we get MOV T, Q. */
1344 if (def[u->val2] <= 4) {
1345 vg_assert(def[u->val2] == sz);
1346 u->size = 4; /* Regardless of sz */
1347 u->opcode = MOV;
1348 u->tag3 = NoValue;
1349 def[u->val2] = VGC_UNDEF;
1350 if (dis)
1351 VG_(printf)(
1352 " at %2d: change ImproveAND%d_TQ to MOV due "
1353 "to defd arg2\n",
1354 i, sz);
1355 }
1356 break;
1357 default:
1358 goto unhandled;
1359 }
1360 break;
1361
1362 case TAG1:
1363 vg_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1364 if (def[u->val1] > 4) break;
1365 /* We now know that the arg to the op is entirely defined.
1366 If the op changes the size of the arg, we must replace
1367 it with a SETV at the new size. If it doesn't change
1368 the size, we can delete it completely. */
1369 switch (u->val3) {
1370 /* Maintain the same size ... */
1371 case Tag_Left4:
1372 vg_assert(def[u->val1] == 4);
1373 NOP_tag1_op(u);
1374 break;
1375 case Tag_PCast11:
1376 vg_assert(def[u->val1] == 1);
1377 NOP_tag1_op(u);
1378 break;
1379 /* Change size ... */
1380 case Tag_PCast40:
1381 vg_assert(def[u->val1] == 4);
1382 SETV_tag1_op(u,0);
1383 def[u->val1] = 0;
1384 break;
1385 case Tag_PCast14:
1386 vg_assert(def[u->val1] == 1);
1387 SETV_tag1_op(u,4);
1388 def[u->val1] = 4;
1389 break;
1390 case Tag_PCast12:
1391 vg_assert(def[u->val1] == 1);
1392 SETV_tag1_op(u,2);
1393 def[u->val1] = 2;
1394 break;
1395 case Tag_PCast10:
1396 vg_assert(def[u->val1] == 1);
1397 SETV_tag1_op(u,0);
1398 def[u->val1] = 0;
1399 break;
1400 case Tag_PCast02:
1401 vg_assert(def[u->val1] == 0);
1402 SETV_tag1_op(u,2);
1403 def[u->val1] = 2;
1404 break;
1405 default:
1406 goto unhandled;
1407 }
1408 if (dis)
1409 VG_(printf)(
1410 " at %2d: delete TAG1 %s due to defd arg\n",
1411 i, nameOfTagOp(u->val3));
1412 break;
1413
1414 default:
1415 unhandled:
1416 /* We don't know how to handle this uinstr. Be safe, and
1417 set to VGC_VALUE or VGC_UNDEF all temps written by it. */
1418 k = VG_(getRegUsage)(u, TempReg, &tempUse[0]);
1419 vg_assert(k <= 3);
1420 for (j = 0; j < k; j++) {
1421 t = tempUse[j].num;
1422 vg_assert(t >= 0 && t < n_temps);
1423 if (!tempUse[j].isWrite) {
1424 /* t is read; ignore it. */
1425 if (0&& VGC_IS_SHADOW(t) && def[t] <= 4)
1426 VG_(printf)("ignoring def %d at %s %s\n",
1427 def[t],
1428 VG_(nameUOpcode)(True, u->opcode),
1429 (u->opcode == TAG1 || u->opcode == TAG2)
1430 ? nameOfTagOp(u->val3)
1431 : (Char*)"");
1432 } else {
1433 /* t is written; better nullify it. */
1434 def[t] = VGC_IS_SHADOW(t) ? VGC_UNDEF : VGC_VALUE;
1435 }
1436 }
1437 }
1438 }
1439}
1440
1441
1442/* Top level post-MemCheck-instrumentation cleanup function. */
1443static void vg_cleanup ( UCodeBlock* cb )
1444{
1445 vg_propagate_definedness ( cb );
1446 vg_delete_redundant_SETVs ( cb );
1447}
1448
1449
1450/* Caller will print out final instrumented code if necessary; we
1451 print out intermediate instrumented code here if necessary. */
1452UCodeBlock* SK_(instrument) ( UCodeBlock* cb, Addr not_used )
1453{
1454 cb = memcheck_instrument ( cb );
1455 if (SK_(clo_cleanup)) {
1456 if (dis) {
1457 VG_(ppUCodeBlock) ( cb, "Unimproved instrumented UCode:" );
1458 VG_(printf)("Instrumentation improvements:\n");
1459 }
1460 vg_cleanup(cb);
1461 if (dis) VG_(printf)("\n");
1462 }
1463 return cb;
1464}
1465
1466#undef dis
1467
1468/*--------------------------------------------------------------------*/
1469/*--- end vg_memcheck_translate.c ---*/
1470/*--------------------------------------------------------------------*/