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