From: Julian Seward Date: Thu, 15 Jul 2004 09:38:27 +0000 (+0000) Subject: Further improvements to the IR sanity checker. X-Git-Tag: svn/VALGRIND_3_0_1^2~1247 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bfb442688ab2845232c6d35f3134c97a875262bb;p=thirdparty%2Fvalgrind.git Further improvements to the IR sanity checker. Use these to fix various bugs found in x86->IR. git-svn-id: svn://svn.valgrind.org/vex/trunk@87 --- diff --git a/VEX/priv/guest-x86/x86toIR.c b/VEX/priv/guest-x86/x86toIR.c index e139fc93db..aa8412f418 100644 --- a/VEX/priv/guest-x86/x86toIR.c +++ b/VEX/priv/guest-x86/x86toIR.c @@ -70,6 +70,7 @@ static void stmt ( IRStmt* stmt ) /* Generate a new temporary of the given type. */ static IRTemp newTemp ( IRType ty ) { + vassert(isPlausibleType(ty)); return newIRTemp( irbb->tyenv, ty ); } @@ -583,7 +584,7 @@ static IRExpr* flag_to_bit0 ( UInt ccmask, IRTemp eflags ) if (shifts == 0) return mkexpr(eflags); else - return binop(Iop_Shr32, mkexpr(eflags), mkU32(shifts)); + return binop(Iop_Shr32, mkexpr(eflags), mkU8(shifts)); } @@ -1315,7 +1316,7 @@ IRTemp disAMode ( Int* len, UChar sorb, UInt delta, UChar* buf ) binop(Iop_Add32, getIReg(4,base_r), binop(Iop_Shl32, getIReg(4,index_r), - mkU32(scale))))); + mkU8(scale))))); } if (index_r != R_ESP && base_r == R_EBP) { @@ -1327,7 +1328,7 @@ IRTemp disAMode ( Int* len, UChar sorb, UInt delta, UChar* buf ) disAMode_copy2tmp( handleSegOverride(sorb, binop(Iop_Add32, - binop(Iop_Shl32, getIReg(4,index_r), mkU32(scale)), + binop(Iop_Shl32, getIReg(4,index_r), mkU8(scale)), mkU32(d)))); } @@ -1383,7 +1384,7 @@ IRTemp disAMode ( Int* len, UChar sorb, UInt delta, UChar* buf ) binop(Iop_Add32, getIReg(4,base_r), binop(Iop_Shl32, - getIReg(4,index_r), mkU32(scale))), + getIReg(4,index_r), mkU8(scale))), mkU32(d)))); } vassert(0); @@ -1422,7 +1423,7 @@ IRTemp disAMode ( Int* len, UChar sorb, UInt delta, UChar* buf ) binop(Iop_Add32, getIReg(4,base_r), binop(Iop_Shl32, - getIReg(4,index_r), mkU32(scale))), + getIReg(4,index_r), mkU8(scale))), mkU32(d)))); } vassert(0); @@ -1963,25 +1964,24 @@ UInt dis_Grp1 ( UChar sorb, } -/* Group 2 extended opcodes. */ +/* Group 2 extended opcodes. shift_expr must be an 8-bit typed + expression. */ + static UInt dis_Grp2 ( UChar sorb, UInt delta, UChar modrm, - Int am_sz, Int d_sz, Int sz, IRExpr* shift_expr ) + Int am_sz, Int d_sz, Int sz, IRExpr* shift_expr, + Char* shift_expr_txt ) { /* delta on entry points at the modrm byte. */ - UChar dis_buf[50]; - Int len; - IROp op8; - IRType ty = szToITy(sz); - IRTemp dst0 = newTemp(ty); - IRTemp dst1 = newTemp(ty); - IRTemp addr = INVALID_IRTEMP; - Bool isShift; - - // IRTemp dst1 = newTemp(ty); - // IRTemp src = newTemp(ty); - // IRTemp dst0 = newTemp(ty); + UChar dis_buf[50]; + Int len; + IROp op8; + Bool isShift; + IRType ty = szToITy(sz); + IRTemp dst0 = newTemp(ty); + IRTemp dst1 = newTemp(ty); + IRTemp addr = INVALID_IRTEMP; vassert(sz == 1 || sz == 2 || sz == 4); @@ -2011,7 +2011,7 @@ UInt dis_Grp2 ( UChar sorb, if (isShift) { IRTemp subshift = newTemp(ty); - IRTemp shift_amt = newTemp(ty); + IRTemp shift_amt = newTemp(Ity_I8); IRTemp guard = newTemp(Ity_Bit); switch (gregOfRM(modrm)) { @@ -2022,8 +2022,8 @@ UInt dis_Grp2 ( UChar sorb, } /* shift_amt = shift_expr & mask */ - assign(shift_amt, binop(mkSizedOp(ty,Iop_And8), - shift_expr, mkU(ty,8*sz-1))); + assign(shift_amt, binop(Iop_And8, + shift_expr, mkU8(8*sz-1))); /* dst1 = dst0 `shift` shift_amt */ assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(shift_amt))); @@ -2031,11 +2031,13 @@ UInt dis_Grp2 ( UChar sorb, assign(subshift, binop(mkSizedOp(ty,op8), mkexpr(dst0), - binop(mkSizedOp(ty,Iop_Sub8), - mkexpr(shift_amt), mkU(ty,1)))); + binop(Iop_And8, + binop(Iop_Sub8, + mkexpr(shift_amt), mkU8(1)), + mkU8(8*sz-1)))); /* guard = (shift_amt != 0) */ - assign(guard, binop(mkSizedOp(ty,Iop_CmpNE8), - mkexpr(shift_amt), mkU(ty,0))); + assign(guard, binop(Iop_CmpNE8, + mkexpr(shift_amt), mkU8(0))); /* Build the flags thunk. */ setFlags_DSTus_DST1(op8, subshift, dst1, ty, guard); @@ -2050,7 +2052,10 @@ UInt dis_Grp2 ( UChar sorb, if (print_codegen) { vex_printf("%s%c ", nameGrp2(gregOfRM(modrm)), nameISize(sz) ); - ppIRExpr(shift_expr); + if (shift_expr_txt) + vex_printf("%s", shift_expr_txt); + else + ppIRExpr(shift_expr); vex_printf(", %s\n", nameIReg(sz,eregOfRM(modrm))); } } else { @@ -2058,7 +2063,10 @@ UInt dis_Grp2 ( UChar sorb, if (print_codegen) { vex_printf("%s%c ", nameGrp2(gregOfRM(modrm)), nameISize(sz) ); - ppIRExpr(shift_expr); + if (shift_expr_txt) + vex_printf("%s", shift_expr_txt); + else + ppIRExpr(shift_expr); vex_printf(", %s\n", dis_buf); } } @@ -2585,7 +2593,7 @@ void dis_string_op_increment(Int sz, Int t_inc) if (sz == 4 || sz == 2) { assign( t_inc, binop(Iop_Shl32, IRExpr_Get( OFFB_DFLAG, Ity_I32 ), - mkU32(sz/2) ) ); + mkU8(sz/2) ) ); } else { assign( t_inc, IRExpr_Get( OFFB_DFLAG, Ity_I32 ) ); @@ -2659,7 +2667,7 @@ void dis_STOS ( Int sz, IRTemp t_inc ) assign( td, getIReg(4, R_EDI) ); //uInstr2(cb, STORE, sz, TempReg, ta, TempReg, td); - storeLE( mkexpr(ta), mkexpr(td) ); + storeLE( mkexpr(td), mkexpr(ta) ); //uInstr2(cb, ADD, 4, TempReg, t_inc, TempReg, td); //uInstr2(cb, PUT, 4, TempReg, td, ArchReg, R_EDI); @@ -2670,8 +2678,8 @@ static void dis_CMPS ( Int sz, IRTemp t_inc ) { IRType ty = szToITy(sz); - IRTemp tdv = newTemp(sz); /* (EDI) */ - IRTemp tsv = newTemp(sz); /* (ESI) */ + IRTemp tdv = newTemp(ty); /* (EDI) */ + IRTemp tsv = newTemp(ty); /* (ESI) */ IRTemp td = newTemp(Ity_I32); /* EDI */ IRTemp ts = newTemp(Ity_I32); /* ESI */ @@ -2786,8 +2794,8 @@ UInt dis_mul_E_G ( UChar sorb, UChar rm = getIByte(delta0); IRType ty = szToITy(size); //IRTemp ta = INVALID_IRTEMP; - IRTemp te = newTemp(size); - IRTemp tg = newTemp(size); + IRTemp te = newTemp(ty); + IRTemp tg = newTemp(ty); if (epartIsReg(rm)) { vassert(signed_multiply); @@ -3172,14 +3180,14 @@ UInt dis_SHLRD_Gv_Ev ( UChar sorb, Int len; UChar dis_buf[50]; - IRType ty = szToITy(sz); - IRTemp gsrc = newTemp(ty); - IRTemp esrc = newTemp(ty); - IRTemp addr = INVALID_IRTEMP; - IRTemp tmpSH = newTemp(Ity_I8); - IRTemp guard = newTemp(Ity_I32); - IRTemp tmpL = INVALID_IRTEMP; - IRTemp tmpRes = INVALID_IRTEMP; + IRType ty = szToITy(sz); + IRTemp gsrc = newTemp(ty); + IRTemp esrc = newTemp(ty); + IRTemp addr = INVALID_IRTEMP; + IRTemp tmpSH = newTemp(Ity_I8); + IRTemp guard = newTemp(Ity_Bit); + IRTemp tmpL = INVALID_IRTEMP; + IRTemp tmpRes = INVALID_IRTEMP; IRTemp tmpSubSh = INVALID_IRTEMP; IROp mkpair; IROp getres; @@ -6013,7 +6021,7 @@ static UInt disInstr ( UInt delta, Bool* isEnd ) putIReg(sz, R_EDX, binop(mkSizedOp(ty,Iop_Sar8), getIReg(sz, R_EAX), - mkU(ty,sz == 2 ? 15 : 31)) ); + mkU8(sz == 2 ? 15 : 31)) ); DIP(sz == 2 ? "cwdq\n" : "cdqq\n"); break; @@ -7034,7 +7042,8 @@ static UInt disInstr ( UInt delta, Bool* isEnd ) d_sz = 1; d32 = getSDisp8(delta + am_sz); sz = 1; - delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, mkU32(d32) ); + delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, + mkU8(d32 & 0xFF), NULL ); break; case 0xC1: /* Grp2 Ib,Ev */ @@ -7042,7 +7051,8 @@ static UInt disInstr ( UInt delta, Bool* isEnd ) am_sz = lengthAMode(delta); d_sz = 1; d32 = getSDisp8(delta + am_sz); - delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, mkU32(d32) ); + delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, + mkU8(d32 & 0xFF), NULL ); break; //-- case 0xD0: /* Grp2 1,Eb */ @@ -7059,7 +7069,8 @@ static UInt disInstr ( UInt delta, Bool* isEnd ) am_sz = lengthAMode(delta); d_sz = 0; d32 = 1; - delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, mkU32(d32) ); + delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, + mkU8(d32), NULL ); break; //-- case 0xD2: /* Grp2 CL,Eb */ @@ -7075,7 +7086,7 @@ static UInt disInstr ( UInt delta, Bool* isEnd ) am_sz = lengthAMode(delta); d_sz = 0; delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, - getIReg(sz,R_ECX) ); + getIReg(1,R_ECX), "%cl" ); break; /* ------------------------ (Grp3 extensions) ---------- */ diff --git a/VEX/priv/ir/ir_defs.c b/VEX/priv/ir/ir_defs.c index c0ff306ae1..0a38f972c3 100644 --- a/VEX/priv/ir/ir_defs.c +++ b/VEX/priv/ir/ir_defs.c @@ -25,7 +25,8 @@ void ppIRType ( IRType ty ) case Ity_I16: vex_printf( "I16"); break; case Ity_I32: vex_printf( "I32"); break; case Ity_I64: vex_printf( "I64"); break; - default: vpanic("ppIRType"); + default: vex_printf("ty = 0x%x\n", (Int)ty); + vpanic("ppIRType"); } } @@ -452,6 +453,22 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 ) case Iop_CmpEQ64: case Iop_CmpNE64: COMPARISON(Ity_I64); + case Iop_MullU32: case Iop_MullS32: + BINARY(Ity_I64,Ity_I32,Ity_I32); + + case Iop_DivModU64to32: + BINARY(Ity_I64,Ity_I64,Ity_I32); + + case Iop_64HIto32: case Iop_64LOto32: + UNARY(Ity_I32, Ity_I64); + case Iop_32HLto64: + BINARY(Ity_I64,Ity_I32,Ity_I32); + + case Iop_1Uto8: UNARY(Ity_I8,Ity_Bit); + case Iop_32to1: UNARY(Ity_Bit,Ity_I32); + case Iop_8Uto32: UNARY(Ity_I32,Ity_I8); + case Iop_16Uto32: UNARY(Ity_I32,Ity_I16); + default: ppIROp(op); vpanic("typeOfPrimop"); @@ -544,6 +561,18 @@ IRType typeOfIRExpr ( IRTypeEnv* tyenv, IRExpr* e ) } } +/* Is this any value actually in the enumeration 'IRType' ? */ +Bool isPlausibleType ( IRType ty ) +{ + switch (ty) { + case Ity_INVALID: case Ity_Bit: + case Ity_I8: case Ity_I16: case Ity_I32: case Ity_I64: + return True; + default: + return False; + } +} + /*---------------------------------------------------------------*/ /*--- Sanity checking ---*/ @@ -643,16 +672,36 @@ void tcExpr ( IRBB* bb, IRStmt* stmt, IRExpr* expr, IRType gWordTy ) case Iex_Get: case Iex_Tmp: break; - case Iex_Binop: + case Iex_Binop: { + IRType ttarg1, ttarg2; tcExpr(bb,stmt, expr->Iex.Binop.arg1, gWordTy ); tcExpr(bb,stmt, expr->Iex.Binop.arg2, gWordTy ); typeOfPrimop(expr->Iex.Binop.op, &t_dst, &t_arg1, &t_arg2); if (t_arg1 == Ity_INVALID || t_arg2 == Ity_INVALID) sanityCheckFail(bb,stmt,"Iex.Binop: wrong arity op"); - if (t_arg1 != typeOfIRExpr(tyenv, expr->Iex.Binop.arg1) - || t_arg2 != typeOfIRExpr(tyenv, expr->Iex.Binop.arg1)) - sanityCheckFail(bb,stmt,"Iex.Binop: arg tys don't match op tys"); + ttarg1 = typeOfIRExpr(tyenv, expr->Iex.Binop.arg1); + ttarg2 = typeOfIRExpr(tyenv, expr->Iex.Binop.arg2); + if (t_arg1 != ttarg1 || t_arg2 != ttarg2) { + vex_printf(" op name: "); + ppIROp(expr->Iex.Binop.op); + vex_printf("\n"); + vex_printf(" op type is ("); + ppIRType(t_arg1); + vex_printf(","); + ppIRType(t_arg2); + vex_printf(") -> "); + ppIRType (t_dst); + vex_printf("\narg tys are ("); + ppIRType(ttarg1); + vex_printf(","); + ppIRType(ttarg2); + vex_printf(")\n"); + sanityCheckFail(bb,stmt, + "Iex.Binop: arg tys don't match op tys\n" + "... additional details precede BB printout\n"); + } break; + } case Iex_Unop: tcExpr(bb,stmt, expr->Iex.Unop.arg, gWordTy ); typeOfPrimop(expr->Iex.Binop.op, &t_dst, &t_arg1, &t_arg2); @@ -702,7 +751,7 @@ void tcStmt ( IRBB* bb, IRStmt* stmt, IRType gWordTy ) tcExpr( bb, stmt, stmt->Ist.Tmp.expr, gWordTy ); if (lookupIRTypeEnv(tyenv, stmt->Ist.Tmp.tmp) != typeOfIRExpr(tyenv, stmt->Ist.Tmp.expr)) - sanityCheckFail(bb,stmt,"IRStmt.Put.TMp: tmp and expr do not match"); + sanityCheckFail(bb,stmt,"IRStmt.Put.Tmp: tmp and expr do not match"); break; case Ist_STle: tcExpr( bb, stmt, stmt->Ist.STle.addr, gWordTy ); @@ -724,7 +773,6 @@ void tcStmt ( IRBB* bb, IRStmt* stmt, IRType gWordTy ) } } - void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size ) { Int i; @@ -735,11 +783,22 @@ void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size ) vassert(guest_word_size == Ity_I32 || guest_word_size == Ity_I64); - for (i = 0; i < n_temps; i++) - def_counts[i] = 0; + /* Ensure each temp has a plausible type. */ + for (i = 0; i < n_temps; i++) { + IRType ty = lookupIRTypeEnv(bb->tyenv,(IRTemp)i); + if (!isPlausibleType(ty)) { + vex_printf("Temp t%d declared with implausible type 0x%x\n", + i, (UInt)ty); + sanityCheckFail(bb,NULL,"Temp declared with implausible type"); + } + } /* Count the defs of each temp. Only one def is allowed. Also, check that each used temp has already been defd. */ + + for (i = 0; i < n_temps; i++) + def_counts[i] = 0; + for (stmt = bb->stmts; stmt; stmt=stmt->link) { useBeforeDef_Stmt(bb,stmt,def_counts); if (stmt->tag == Ist_Tmp) { diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index c5a24783fc..85b61e7ee3 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -315,6 +315,9 @@ extern IRType typeOfIRExpr ( IRTypeEnv*, IRExpr* ); /* Sanity check a BB of IR */ extern void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size ); +/* Is this any value actually in the enumeration 'IRType' ? */ +extern Bool isPlausibleType ( IRType ty ); + #endif /* ndef __LIBVEX_IR_H */