From: Julian Seward Date: Mon, 11 Nov 2019 15:11:20 +0000 (+0100) Subject: Clean up machinery to do with conditionalising IRStmts: X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=15c69a57ed826c65867dbd1974f4d4a3b040e6cb;p=thirdparty%2Fvalgrind.git Clean up machinery to do with conditionalising IRStmts: * document some functions * change naming and terminology from 'speculation' (which it isn't) to 'guarding' (which it is) * add a new function |primopMightTrap| so as to avoid conditionalising IRExprs involving potentially trappy IROps --- diff --git a/VEX/priv/guest_generic_bb_to_IR.c b/VEX/priv/guest_generic_bb_to_IR.c index 4cb813f2aa..7782bcf96f 100644 --- a/VEX/priv/guest_generic_bb_to_IR.c +++ b/VEX/priv/guest_generic_bb_to_IR.c @@ -388,29 +388,42 @@ static void create_self_checks_as_needed( /*--------------------------------------------------------------*/ -/*--- To do with speculation of IRStmts ---*/ +/*--- To do with guarding (conditionalisation) of IRStmts ---*/ /*--------------------------------------------------------------*/ -static Bool expr_is_speculatable ( const IRExpr* e ) +// Is it possible to guard |e|? Meaning, is it safe (exception-free) to compute +// |e| and ignore the result? Since |e| is by definition otherwise +// side-effect-free, we don't have to ask about any other effects caused by +// first computing |e| and then ignoring the result. +static Bool expr_is_guardable ( const IRExpr* e ) { switch (e->tag) { case Iex_Load: return False; - case Iex_Unop: // FIXME BOGUS, since it might trap - case Iex_Binop: // FIXME ditto - case Iex_ITE: // this is OK - return True; + case Iex_Unop: + return !primopMightTrap(e->Iex.Unop.op); + case Iex_Binop: + return !primopMightTrap(e->Iex.Binop.op); + case Iex_ITE: case Iex_CCall: - return True; // This is probably correct case Iex_Get: return True; default: - vex_printf("\n"); ppIRExpr(e); - vpanic("expr_is_speculatable: unhandled expr"); + vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); + vpanic("expr_is_guardable: unhandled expr"); } } -static Bool stmt_is_speculatable ( const IRStmt* st ) +// Is it possible to guard |st|? Meaning, is it possible to replace |st| by +// some other sequence of IRStmts which have the same effect on the architected +// state when the guard is true, but when it is false, have no effect on the +// architected state and are guaranteed not to cause any exceptions? +// +// Note that this isn't as aggressive as it could be: it sometimes returns False +// in cases where |st| is actually guardable. This routine must coordinate +// closely with add_guarded_stmt_to_end_of below, in the sense that that routine +// must be able to handle any |st| for which this routine returns True. +static Bool stmt_is_guardable ( const IRStmt* st ) { switch (st->tag) { case Ist_IMark: @@ -421,35 +434,37 @@ static Bool stmt_is_speculatable ( const IRStmt* st ) case Ist_Exit: // We could in fact spec this, if required return False; case Ist_WrTmp: - return expr_is_speculatable(st->Ist.WrTmp.data); + return expr_is_guardable(st->Ist.WrTmp.data); default: - vex_printf("\n"); ppIRStmt(st); - vpanic("stmt_is_speculatable: unhandled stmt"); + vex_printf("\n"); ppIRStmt(st); vex_printf("\n"); + vpanic("stmt_is_guardable: unhandled stmt"); } } -static Bool block_is_speculatable ( const IRSB* bb ) +// Are all stmts (but not the end dst value) in |bb| guardable, per +// stmt_is_guardable? +static Bool block_is_guardable ( const IRSB* bb ) { Int i = bb->stmts_used; - vassert(i >= 2); // Must have at least: IMark, final Exit + vassert(i >= 2); // Must have at least: IMark, side Exit (at the end) i--; vassert(bb->stmts[i]->tag == Ist_Exit); i--; for (; i >= 0; i--) { - if (!stmt_is_speculatable(bb->stmts[i])) + if (!stmt_is_guardable(bb->stmts[i])) return False; } return True; } -static void speculate_stmt_to_end_of ( /*MOD*/IRSB* bb, - /*IN*/ IRStmt* st, IRTemp guard ) +// Guard |st| with |guard| and add it to |bb|. This must be able to handle any +// |st| for which stmt_is_guardable returns True. +static void add_guarded_stmt_to_end_of ( /*MOD*/IRSB* bb, + /*IN*/ IRStmt* st, IRTemp guard ) { - // We assume all stmts we're presented with here have previously been OK'd by - // stmt_is_speculatable above. switch (st->tag) { case Ist_IMark: - case Ist_WrTmp: // FIXME is this ok? + case Ist_WrTmp: addStmtToIRSB(bb, st); break; case Ist_Put: { @@ -472,7 +487,7 @@ static void speculate_stmt_to_end_of ( /*MOD*/IRSB* bb, case Ist_Exit: { // Exit(xguard, dst, jk, offsIP) // ==> t1 = And1(xguard, guard) - // Exit(And1(xguard, guard), dst, jk, offsIP) + // Exit(t1, dst, jk, offsIP) IRExpr* xguard = st->Ist.Exit.guard; IRTemp t1 = newIRTemp(bb->tyenv, Ity_I1); addStmtToIRSB(bb, IRStmt_WrTmp(t1, IRExpr_Binop(Iop_And1, xguard, @@ -482,8 +497,8 @@ static void speculate_stmt_to_end_of ( /*MOD*/IRSB* bb, break; } default: - vex_printf("\n"); ppIRStmt(st); - vpanic("speculate_stmt_to_end_of: unhandled stmt"); + vex_printf("\n"); ppIRStmt(st); vex_printf("\n"); + vpanic("add_guarded_stmt_to_end_of: unhandled stmt"); } } @@ -1435,10 +1450,10 @@ IRSB* bb_to_IR ( ppBlockEnd(&sx_be); vex_printf("\n"); } - // Finally, check the sx block actually is speculatable. - ok = block_is_speculatable(sx_bb); + // Finally, check the sx block actually is guardable. + ok = block_is_guardable(sx_bb); if (!ok && debug_print) { - vex_printf("\n-+-+ SX not speculatable, giving up. -+-+\n\n"); + vex_printf("\n-+-+ SX not guardable, giving up. -+-+\n\n"); } } @@ -1450,10 +1465,10 @@ IRSB* bb_to_IR ( // 0. remove the last Exit on irsb. // 1. Add irsb->tyenv->types_used to all the tmps in sx_bb, // by calling deltaIRStmt on all stmts. - // 2. Speculate all stmts in sx_bb on irsb_be.Be.Cond.condSX, + // 2. Guard all stmts in sx_bb on irsb_be.Be.Cond.condSX, // **including** the last stmt (which must be an Exit). It's // here that the And1 is generated. - // 3. Copy all speculated stmts to the end of irsb. + // 3. Copy all guarded stmts to the end of irsb. vassert(irsb->stmts_used >= 2); irsb->stmts_used--; Int delta = irsb->tyenv->types_used; @@ -1466,7 +1481,7 @@ IRSB* bb_to_IR ( for (Int i = 0; i < sx_bb->stmts_used; i++) { IRStmt* st = deepCopyIRStmt(sx_bb->stmts[i]); deltaIRStmt(st, delta); - speculate_stmt_to_end_of(irsb, st, irsb_be.Be.Cond.condSX); + add_guarded_stmt_to_end_of(irsb, st, irsb_be.Be.Cond.condSX); } if (debug_print) { diff --git a/VEX/priv/ir_defs.c b/VEX/priv/ir_defs.c index 6035574663..d687d8f0a4 100644 --- a/VEX/priv/ir_defs.c +++ b/VEX/priv/ir_defs.c @@ -1345,6 +1345,432 @@ void ppIROp ( IROp op ) } } +// A very few primops might trap (eg, divide by zero). We need to be able to +// identify them. +Bool primopMightTrap ( IROp op ) +{ + switch (op) { + + // The few potentially trapping ones + case Iop_DivU32: case Iop_DivS32: case Iop_DivU64: case Iop_DivS64: + case Iop_DivU64E: case Iop_DivS64E: case Iop_DivU32E: case Iop_DivS32E: + case Iop_DivModU64to32: case Iop_DivModS64to32: case Iop_DivModU128to64: + case Iop_DivModS128to64: case Iop_DivModS64to64: case Iop_DivModU64to64: + case Iop_DivModS32to32: case Iop_DivModU32to32: + return True; + + // All the rest are non-trapping + case Iop_Add8: case Iop_Add16: case Iop_Add32: case Iop_Add64: + case Iop_Sub8: case Iop_Sub16: case Iop_Sub32: case Iop_Sub64: + case Iop_Mul8: case Iop_Mul16: case Iop_Mul32: case Iop_Mul64: + case Iop_Or8: case Iop_Or16: case Iop_Or32: case Iop_Or64: + case Iop_And8: case Iop_And16: case Iop_And32: case Iop_And64: + case Iop_Xor8: case Iop_Xor16: case Iop_Xor32: case Iop_Xor64: + case Iop_Shl8: case Iop_Shl16: case Iop_Shl32: case Iop_Shl64: + case Iop_Shr8: case Iop_Shr16: case Iop_Shr32: case Iop_Shr64: + case Iop_Sar8: case Iop_Sar16: case Iop_Sar32: case Iop_Sar64: + case Iop_CmpEQ8: case Iop_CmpEQ16: case Iop_CmpEQ32: case Iop_CmpEQ64: + case Iop_CmpNE8: case Iop_CmpNE16: case Iop_CmpNE32: case Iop_CmpNE64: + case Iop_Not8: case Iop_Not16: case Iop_Not32: case Iop_Not64: + case Iop_CasCmpEQ8: case Iop_CasCmpEQ16: case Iop_CasCmpEQ32: + case Iop_CasCmpEQ64: case Iop_CasCmpNE8: case Iop_CasCmpNE16: + case Iop_CasCmpNE32: case Iop_CasCmpNE64: case Iop_ExpCmpNE8: + case Iop_ExpCmpNE16: case Iop_ExpCmpNE32: case Iop_ExpCmpNE64: + case Iop_MullS8: case Iop_MullS16: case Iop_MullS32: case Iop_MullS64: + case Iop_MullU8: case Iop_MullU16: case Iop_MullU32: case Iop_MullU64: + case Iop_Clz64: case Iop_Clz32: case Iop_Ctz64: case Iop_Ctz32: + case Iop_ClzNat64: case Iop_ClzNat32: case Iop_CtzNat64: case Iop_CtzNat32: + case Iop_PopCount64: case Iop_PopCount32: + case Iop_CmpLT32S: case Iop_CmpLT64S: case Iop_CmpLE32S: case Iop_CmpLE64S: + case Iop_CmpLT32U: case Iop_CmpLT64U: case Iop_CmpLE32U: case Iop_CmpLE64U: + case Iop_CmpNEZ8: case Iop_CmpNEZ16: case Iop_CmpNEZ32: case Iop_CmpNEZ64: + case Iop_CmpwNEZ32: case Iop_CmpwNEZ64: + case Iop_Left8: case Iop_Left16: case Iop_Left32: case Iop_Left64: + case Iop_Max32U: case Iop_CmpORD32U: case Iop_CmpORD64U: + case Iop_CmpORD32S: case Iop_CmpORD64S: + case Iop_8Uto16: case Iop_8Uto32: case Iop_8Uto64: + case Iop_16Uto32: case Iop_16Uto64: case Iop_32Uto64: + case Iop_8Sto16: case Iop_8Sto32: case Iop_8Sto64: + case Iop_16Sto32: case Iop_16Sto64: case Iop_32Sto64: + case Iop_64to8: case Iop_32to8: case Iop_64to16: + case Iop_16to8: case Iop_16HIto8: case Iop_8HLto16: case Iop_32to16: + case Iop_32HIto16: case Iop_16HLto32: case Iop_64to32: case Iop_64HIto32: + case Iop_32HLto64: case Iop_128to64: case Iop_128HIto64: case Iop_64HLto128: + case Iop_Not1: case Iop_And1: case Iop_Or1: case Iop_32to1: case Iop_64to1: + case Iop_1Uto8: case Iop_1Uto32: case Iop_1Uto64: case Iop_1Sto8: + case Iop_1Sto16: case Iop_1Sto32: case Iop_1Sto64: + case Iop_AddF64: case Iop_SubF64: case Iop_MulF64: case Iop_DivF64: + case Iop_AddF32: case Iop_SubF32: case Iop_MulF32: case Iop_DivF32: + case Iop_AddF64r32: case Iop_SubF64r32: case Iop_MulF64r32: + case Iop_DivF64r32: case Iop_NegF64: case Iop_AbsF64: + case Iop_NegF32: case Iop_AbsF32: case Iop_SqrtF64: case Iop_SqrtF32: + case Iop_CmpF64: case Iop_CmpF32: case Iop_CmpF128: case Iop_F64toI16S: + case Iop_F64toI32S: case Iop_F64toI64S: case Iop_F64toI64U: + case Iop_F64toI32U: case Iop_I32StoF64: case Iop_I64StoF64: + case Iop_I64UtoF64: case Iop_I64UtoF32: case Iop_I32UtoF32: + case Iop_I32UtoF64: case Iop_F32toI32S: case Iop_F32toI64S: + case Iop_F32toI32U: case Iop_F32toI64U: case Iop_I32StoF32: + case Iop_I64StoF32: case Iop_F32toF64: case Iop_F64toF32: + case Iop_ReinterpF64asI64: case Iop_ReinterpI64asF64: + case Iop_ReinterpF32asI32: case Iop_ReinterpI32asF32: + case Iop_F64HLtoF128: case Iop_F128HItoF64: case Iop_F128LOtoF64: + case Iop_AddF128: case Iop_SubF128: case Iop_MulF128: case Iop_DivF128: + case Iop_MAddF128: case Iop_MSubF128: case Iop_NegMAddF128: + case Iop_NegMSubF128: case Iop_NegF128: case Iop_AbsF128: + case Iop_SqrtF128: case Iop_I32StoF128: case Iop_I64StoF128: + case Iop_I32UtoF128: case Iop_I64UtoF128: case Iop_F32toF128: + case Iop_F64toF128: case Iop_F128toI32S: case Iop_F128toI64S: + case Iop_F128toI32U: case Iop_F128toI64U: case Iop_F128toI128S: + case Iop_F128toF64: case Iop_F128toF32: case Iop_RndF128: + case Iop_TruncF128toI32S: case Iop_TruncF128toI32U: case Iop_TruncF128toI64U: + case Iop_TruncF128toI64S: case Iop_AtanF64: case Iop_Yl2xF64: + case Iop_Yl2xp1F64: case Iop_PRemF64: case Iop_PRemC3210F64: + case Iop_PRem1F64: case Iop_PRem1C3210F64: case Iop_ScaleF64: + case Iop_SinF64: case Iop_CosF64: case Iop_TanF64: + case Iop_2xm1F64: case Iop_RoundF128toInt: case Iop_RoundF64toInt: + case Iop_RoundF32toInt: case Iop_MAddF32: case Iop_MSubF32: + case Iop_MAddF64: case Iop_MSubF64: + case Iop_MAddF64r32: case Iop_MSubF64r32: + case Iop_RSqrtEst5GoodF64: case Iop_RoundF64toF64_NEAREST: + case Iop_RoundF64toF64_NegINF: case Iop_RoundF64toF64_PosINF: + case Iop_RoundF64toF64_ZERO: case Iop_TruncF64asF32: case Iop_RoundF64toF32: + case Iop_RecpExpF64: case Iop_RecpExpF32: case Iop_MaxNumF64: + case Iop_MinNumF64: case Iop_MaxNumF32: case Iop_MinNumF32: + case Iop_F16toF64: case Iop_F64toF16: case Iop_F16toF32: + case Iop_F32toF16: case Iop_QAdd32S: case Iop_QSub32S: + case Iop_Add16x2: case Iop_Sub16x2: + case Iop_QAdd16Sx2: case Iop_QAdd16Ux2: + case Iop_QSub16Sx2: case Iop_QSub16Ux2: + case Iop_HAdd16Ux2: case Iop_HAdd16Sx2: + case Iop_HSub16Ux2: case Iop_HSub16Sx2: + case Iop_Add8x4: case Iop_Sub8x4: + case Iop_QAdd8Sx4: case Iop_QAdd8Ux4: + case Iop_QSub8Sx4: case Iop_QSub8Ux4: + case Iop_HAdd8Ux4: case Iop_HAdd8Sx4: + case Iop_HSub8Ux4: case Iop_HSub8Sx4: case Iop_Sad8Ux4: + case Iop_CmpNEZ16x2: case Iop_CmpNEZ8x4: case Iop_Reverse8sIn32_x1: + case Iop_I32UtoF32x2_DEP: case Iop_I32StoF32x2_DEP: + case Iop_F32toI32Ux2_RZ: case Iop_F32toI32Sx2_RZ: + case Iop_F32ToFixed32Ux2_RZ: case Iop_F32ToFixed32Sx2_RZ: + case Iop_Fixed32UToF32x2_RN: case Iop_Fixed32SToF32x2_RN: + case Iop_Max32Fx2: case Iop_Min32Fx2: + case Iop_PwMax32Fx2: case Iop_PwMin32Fx2: + case Iop_CmpEQ32Fx2: case Iop_CmpGT32Fx2: case Iop_CmpGE32Fx2: + case Iop_RecipEst32Fx2: case Iop_RecipStep32Fx2: case Iop_RSqrtEst32Fx2: + case Iop_RSqrtStep32Fx2: case Iop_Neg32Fx2: case Iop_Abs32Fx2: + case Iop_CmpNEZ8x8: case Iop_CmpNEZ16x4: case Iop_CmpNEZ32x2: + case Iop_Add8x8: case Iop_Add16x4: case Iop_Add32x2: + case Iop_QAdd8Ux8: case Iop_QAdd16Ux4: case Iop_QAdd32Ux2: case Iop_QAdd64Ux1: + case Iop_QAdd8Sx8: case Iop_QAdd16Sx4: case Iop_QAdd32Sx2: case Iop_QAdd64Sx1: + case Iop_PwAdd8x8: case Iop_PwAdd16x4: case Iop_PwAdd32x2: + case Iop_PwMax8Sx8: case Iop_PwMax16Sx4: case Iop_PwMax32Sx2: + case Iop_PwMax8Ux8: case Iop_PwMax16Ux4: case Iop_PwMax32Ux2: + case Iop_PwMin8Sx8: case Iop_PwMin16Sx4: case Iop_PwMin32Sx2: + case Iop_PwMin8Ux8: case Iop_PwMin16Ux4: case Iop_PwMin32Ux2: + case Iop_PwAddL8Ux8: case Iop_PwAddL16Ux4: case Iop_PwAddL32Ux2: + case Iop_PwAddL8Sx8: case Iop_PwAddL16Sx4: case Iop_PwAddL32Sx2: + case Iop_Sub8x8: case Iop_Sub16x4: case Iop_Sub32x2: + case Iop_QSub8Ux8: case Iop_QSub16Ux4: case Iop_QSub32Ux2: case Iop_QSub64Ux1: + case Iop_QSub8Sx8: case Iop_QSub16Sx4: case Iop_QSub32Sx2: case Iop_QSub64Sx1: + case Iop_Abs8x8: case Iop_Abs16x4: case Iop_Abs32x2: + case Iop_Mul8x8: case Iop_Mul16x4: case Iop_Mul32x2: + case Iop_Mul32Fx2: case Iop_MulHi16Ux4: case Iop_MulHi16Sx4: + case Iop_PolynomialMul8x8: case Iop_QDMulHi16Sx4: case Iop_QDMulHi32Sx2: + case Iop_QRDMulHi16Sx4: case Iop_QRDMulHi32Sx2: case Iop_Avg8Ux8: + case Iop_Avg16Ux4: case Iop_Max8Sx8: case Iop_Max16Sx4: case Iop_Max32Sx2: + case Iop_Max8Ux8: case Iop_Max16Ux4: case Iop_Max32Ux2: + case Iop_Min8Sx8: case Iop_Min16Sx4: case Iop_Min32Sx2: + case Iop_Min8Ux8: case Iop_Min16Ux4: case Iop_Min32Ux2: + case Iop_CmpEQ8x8: case Iop_CmpEQ16x4: case Iop_CmpEQ32x2: + case Iop_CmpGT8Ux8: case Iop_CmpGT16Ux4: case Iop_CmpGT32Ux2: + case Iop_CmpGT8Sx8: case Iop_CmpGT16Sx4: case Iop_CmpGT32Sx2: + case Iop_Cnt8x8: case Iop_Clz8x8: case Iop_Clz16x4: case Iop_Clz32x2: + case Iop_Cls8x8: case Iop_Cls16x4: case Iop_Cls32x2: case Iop_Clz64x2: + case Iop_Ctz8x16: case Iop_Ctz16x8: case Iop_Ctz32x4: case Iop_Ctz64x2: + case Iop_Shl8x8: case Iop_Shl16x4: case Iop_Shl32x2: + case Iop_Shr8x8: case Iop_Shr16x4: case Iop_Shr32x2: + case Iop_Sar8x8: case Iop_Sar16x4: case Iop_Sar32x2: + case Iop_Sal8x8: case Iop_Sal16x4: case Iop_Sal32x2: case Iop_Sal64x1: + case Iop_ShlN8x8: case Iop_ShlN16x4: case Iop_ShlN32x2: + case Iop_ShrN8x8: case Iop_ShrN16x4: case Iop_ShrN32x2: + case Iop_SarN8x8: case Iop_SarN16x4: case Iop_SarN32x2: + case Iop_QShl8x8: case Iop_QShl16x4: case Iop_QShl32x2: case Iop_QShl64x1: + case Iop_QSal8x8: case Iop_QSal16x4: case Iop_QSal32x2: case Iop_QSal64x1: + case Iop_QShlNsatSU8x8: case Iop_QShlNsatSU16x4: + case Iop_QShlNsatSU32x2: case Iop_QShlNsatSU64x1: + case Iop_QShlNsatUU8x8: case Iop_QShlNsatUU16x4: + case Iop_QShlNsatUU32x2: case Iop_QShlNsatUU64x1: + case Iop_QShlNsatSS8x8: case Iop_QShlNsatSS16x4: + case Iop_QShlNsatSS32x2: case Iop_QShlNsatSS64x1: + case Iop_QNarrowBin16Sto8Ux8: + case Iop_QNarrowBin16Sto8Sx8: case Iop_QNarrowBin32Sto16Sx4: + case Iop_NarrowBin16to8x8: case Iop_NarrowBin32to16x4: + case Iop_InterleaveHI8x8: case Iop_InterleaveHI16x4: + case Iop_InterleaveHI32x2: + case Iop_InterleaveLO8x8: case Iop_InterleaveLO16x4: + case Iop_InterleaveLO32x2: + case Iop_InterleaveOddLanes8x8: case Iop_InterleaveEvenLanes8x8: + case Iop_InterleaveOddLanes16x4: case Iop_InterleaveEvenLanes16x4: + case Iop_CatOddLanes8x8: case Iop_CatOddLanes16x4: + case Iop_CatEvenLanes8x8: case Iop_CatEvenLanes16x4: + case Iop_GetElem8x8: case Iop_GetElem16x4: case Iop_GetElem32x2: + case Iop_SetElem8x8: case Iop_SetElem16x4: case Iop_SetElem32x2: + case Iop_Dup8x8: case Iop_Dup16x4: case Iop_Dup32x2: + case Iop_Slice64: case Iop_Reverse8sIn16_x4: + case Iop_Reverse8sIn32_x2: case Iop_Reverse16sIn32_x2: + case Iop_Reverse8sIn64_x1: case Iop_Reverse16sIn64_x1: + case Iop_Reverse32sIn64_x1: case Iop_Perm8x8: case Iop_PermOrZero8x8: + case Iop_GetMSBs8x8: case Iop_RecipEst32Ux2: case Iop_RSqrtEst32Ux2: + case Iop_AddD64: case Iop_SubD64: case Iop_MulD64: case Iop_DivD64: + case Iop_AddD128: case Iop_SubD128: case Iop_MulD128: case Iop_DivD128: + case Iop_ShlD64: case Iop_ShrD64: + case Iop_ShlD128: case Iop_ShrD128: + case Iop_D32toD64: case Iop_D64toD128: case Iop_I32StoD128: + case Iop_I32UtoD128: case Iop_I64StoD128: case Iop_I64UtoD128: + case Iop_D64toD32: case Iop_D128toD64: case Iop_I32StoD64: + case Iop_I32UtoD64: case Iop_I64StoD64: case Iop_I64UtoD64: + case Iop_D64toI32S: case Iop_D64toI32U: case Iop_D64toI64S: + case Iop_D64toI64U: case Iop_D128toI32S: case Iop_D128toI32U: + case Iop_D128toI64S: case Iop_D128toI64U: case Iop_F32toD32: + case Iop_F32toD64: case Iop_F32toD128: case Iop_F64toD32: + case Iop_F64toD64: case Iop_F64toD128: case Iop_F128toD32: + case Iop_F128toD64: case Iop_F128toD128: case Iop_D32toF32: + case Iop_D32toF64: case Iop_D32toF128: case Iop_D64toF32: case Iop_D64toF64: + case Iop_D64toF128: case Iop_D128toF32: case Iop_D128toF64: + case Iop_D128toF128: case Iop_RoundD64toInt: case Iop_RoundD128toInt: + case Iop_CmpD64: case Iop_CmpD128: case Iop_CmpExpD64: + case Iop_CmpExpD128: case Iop_QuantizeD64: case Iop_QuantizeD128: + case Iop_SignificanceRoundD64: case Iop_SignificanceRoundD128: + case Iop_ExtractExpD64: case Iop_ExtractExpD128: case Iop_ExtractSigD64: + case Iop_ExtractSigD128: case Iop_InsertExpD64: case Iop_InsertExpD128: + case Iop_D64HLtoD128: case Iop_D128HItoD64: case Iop_D128LOtoD64: + case Iop_DPBtoBCD: case Iop_BCDtoDPB: case Iop_BCDAdd: case Iop_BCDSub: + case Iop_I128StoBCD128: case Iop_BCD128toI128S: case Iop_ReinterpI64asD64: + case Iop_ReinterpD64asI64: + case Iop_Add32Fx4: case Iop_Sub32Fx4: case Iop_Mul32Fx4: case Iop_Div32Fx4: + case Iop_Max32Fx4: case Iop_Min32Fx4: + case Iop_Add32Fx2: case Iop_Sub32Fx2: + case Iop_CmpEQ32Fx4: case Iop_CmpLT32Fx4: + case Iop_CmpLE32Fx4: case Iop_CmpUN32Fx4: + case Iop_CmpGT32Fx4: case Iop_CmpGE32Fx4: + case Iop_PwMax32Fx4: case Iop_PwMin32Fx4: + case Iop_Abs32Fx4: case Iop_Neg32Fx4: case Iop_Sqrt32Fx4: + case Iop_RecipEst32Fx4: case Iop_RecipStep32Fx4: case Iop_RSqrtEst32Fx4: + case Iop_Scale2_32Fx4: case Iop_Log2_32Fx4: case Iop_Exp2_32Fx4: + case Iop_RSqrtStep32Fx4: + case Iop_I32UtoF32x4_DEP: case Iop_I32StoF32x4_DEP: case Iop_I32StoF32x4: + case Iop_F32toI32Sx4: case Iop_F32toI32Ux4_RZ: case Iop_F32toI32Sx4_RZ: + case Iop_QF32toI32Ux4_RZ: case Iop_QF32toI32Sx4_RZ: + case Iop_RoundF32x4_RM: case Iop_RoundF32x4_RP: + case Iop_RoundF32x4_RN: case Iop_RoundF32x4_RZ: + case Iop_F32ToFixed32Ux4_RZ: case Iop_F32ToFixed32Sx4_RZ: + case Iop_Fixed32UToF32x4_RN: case Iop_Fixed32SToF32x4_RN: + case Iop_F32toF16x4_DEP: case Iop_F32toF16x4: case Iop_F16toF32x4: + case Iop_F64toF16x2_DEP: case Iop_F16toF64x2: case Iop_F32x4_2toQ16x8: + case Iop_Add32F0x4: case Iop_Sub32F0x4: case Iop_Mul32F0x4: + case Iop_Div32F0x4: case Iop_Max32F0x4: case Iop_Min32F0x4: + case Iop_CmpEQ32F0x4: case Iop_CmpLT32F0x4: case Iop_CmpLE32F0x4: + case Iop_CmpUN32F0x4: + case Iop_RecipEst32F0x4: case Iop_Sqrt32F0x4: case Iop_RSqrtEst32F0x4: + case Iop_Add64Fx2: case Iop_Sub64Fx2: case Iop_Mul64Fx2: case Iop_Div64Fx2: + case Iop_Max64Fx2: case Iop_Min64Fx2: + case Iop_CmpEQ64Fx2: case Iop_CmpLT64Fx2: case Iop_CmpLE64Fx2: + case Iop_CmpUN64Fx2: case Iop_Abs64Fx2: case Iop_Neg64Fx2: + case Iop_Sqrt64Fx2: case Iop_Scale2_64Fx2: case Iop_Log2_64Fx2: + case Iop_RecipEst64Fx2: case Iop_RecipStep64Fx2: case Iop_RSqrtEst64Fx2: + case Iop_RSqrtStep64Fx2: case Iop_F64x2_2toQ32x4: + case Iop_Add64F0x2: case Iop_Sub64F0x2: case Iop_Mul64F0x2: + case Iop_Div64F0x2: case Iop_Max64F0x2: case Iop_Min64F0x2: + case Iop_CmpEQ64F0x2: case Iop_CmpLT64F0x2: case Iop_CmpLE64F0x2: + case Iop_CmpUN64F0x2: case Iop_Sqrt64F0x2: case Iop_V128to64: + case Iop_V128HIto64: case Iop_64HLtoV128: case Iop_64UtoV128: + case Iop_SetV128lo64: case Iop_ZeroHI64ofV128: case Iop_ZeroHI96ofV128: + case Iop_ZeroHI112ofV128: case Iop_ZeroHI120ofV128: case Iop_32UtoV128: + case Iop_V128to32: case Iop_SetV128lo32: case Iop_NotV128: + case Iop_AndV128: case Iop_OrV128: case Iop_XorV128: + case Iop_ShlV128: case Iop_ShrV128: case Iop_SarV128: + case Iop_CmpNEZ8x16: case Iop_CmpNEZ16x8: case Iop_CmpNEZ32x4: + case Iop_CmpNEZ64x2: case Iop_CmpNEZ128x1: + case Iop_Add8x16: case Iop_Add16x8: case Iop_Add32x4: + case Iop_Add64x2: case Iop_Add128x1: + case Iop_QAdd8Ux16: case Iop_QAdd16Ux8: case Iop_QAdd32Ux4: + case Iop_QAdd64Ux2: + case Iop_QAdd8Sx16: case Iop_QAdd16Sx8: case Iop_QAdd32Sx4: + case Iop_QAdd64Sx2: + case Iop_QAddExtUSsatSS8x16: case Iop_QAddExtUSsatSS16x8: + case Iop_QAddExtUSsatSS32x4: case Iop_QAddExtUSsatSS64x2: + case Iop_QAddExtSUsatUU8x16: case Iop_QAddExtSUsatUU16x8: + case Iop_QAddExtSUsatUU32x4: case Iop_QAddExtSUsatUU64x2: + case Iop_Sub8x16: case Iop_Sub16x8: case Iop_Sub32x4: + case Iop_Sub64x2: case Iop_Sub128x1: + case Iop_QSub8Ux16: case Iop_QSub16Ux8: case Iop_QSub32Ux4: + case Iop_QSub64Ux2: + case Iop_QSub8Sx16: case Iop_QSub16Sx8: case Iop_QSub32Sx4: + case Iop_QSub64Sx2: + case Iop_Mul8x16: case Iop_Mul16x8: case Iop_Mul32x4: + case Iop_MulHi8Ux16: case Iop_MulHi16Ux8: case Iop_MulHi32Ux4: + case Iop_MulHi8Sx16: case Iop_MulHi16Sx8: case Iop_MulHi32Sx4: + case Iop_MullEven8Ux16: case Iop_MullEven16Ux8: case Iop_MullEven32Ux4: + case Iop_MullEven8Sx16: case Iop_MullEven16Sx8: case Iop_MullEven32Sx4: + case Iop_Mull8Ux8: case Iop_Mull8Sx8: + case Iop_Mull16Ux4: case Iop_Mull16Sx4: + case Iop_Mull32Ux2: case Iop_Mull32Sx2: + case Iop_QDMull16Sx4: case Iop_QDMull32Sx2: + case Iop_QDMulHi16Sx8: case Iop_QDMulHi32Sx4: + case Iop_QRDMulHi16Sx8: case Iop_QRDMulHi32Sx4: + case Iop_PolynomialMul8x16: case Iop_PolynomialMull8x8: + case Iop_PolynomialMulAdd8x16: case Iop_PolynomialMulAdd16x8: + case Iop_PolynomialMulAdd32x4: case Iop_PolynomialMulAdd64x2: + case Iop_PwAdd8x16: case Iop_PwAdd16x8: case Iop_PwAdd32x4: + case Iop_PwAdd32Fx2: case Iop_PwAddL8Ux16: case Iop_PwAddL16Ux8: + case Iop_PwAddL32Ux4: case Iop_PwAddL64Ux2: + case Iop_PwAddL8Sx16: case Iop_PwAddL16Sx8: case Iop_PwAddL32Sx4: + case Iop_PwExtUSMulQAdd8x16: + case Iop_PwBitMtxXpose64x2: + case Iop_Abs8x16: case Iop_Abs16x8: case Iop_Abs32x4: case Iop_Abs64x2: + case Iop_Avg8Ux16: case Iop_Avg16Ux8: case Iop_Avg32Ux4: case Iop_Avg64Ux2: + case Iop_Avg8Sx16: case Iop_Avg16Sx8: case Iop_Avg32Sx4: case Iop_Avg64Sx2: + case Iop_Max8Sx16: case Iop_Max16Sx8: case Iop_Max32Sx4: case Iop_Max64Sx2: + case Iop_Max8Ux16: case Iop_Max16Ux8: case Iop_Max32Ux4: case Iop_Max64Ux2: + case Iop_Min8Sx16: case Iop_Min16Sx8: case Iop_Min32Sx4: case Iop_Min64Sx2: + case Iop_Min8Ux16: case Iop_Min16Ux8: case Iop_Min32Ux4: case Iop_Min64Ux2: + case Iop_CmpEQ8x16: case Iop_CmpEQ16x8: case Iop_CmpEQ32x4: + case Iop_CmpEQ64x2: + case Iop_CmpGT8Sx16: case Iop_CmpGT16Sx8: case Iop_CmpGT32Sx4: + case Iop_CmpGT64Sx2: + case Iop_CmpGT8Ux16: case Iop_CmpGT16Ux8: case Iop_CmpGT32Ux4: + case Iop_CmpGT64Ux2: + case Iop_Cnt8x16: + case Iop_Clz8x16: case Iop_Clz16x8: case Iop_Clz32x4: + case Iop_Cls8x16: case Iop_Cls16x8: case Iop_Cls32x4: + case Iop_ShlN8x16: case Iop_ShlN16x8: case Iop_ShlN32x4: case Iop_ShlN64x2: + case Iop_ShrN8x16: case Iop_ShrN16x8: case Iop_ShrN32x4: case Iop_ShrN64x2: + case Iop_SarN8x16: case Iop_SarN16x8: case Iop_SarN32x4: case Iop_SarN64x2: + case Iop_Shl8x16: case Iop_Shl16x8: case Iop_Shl32x4: case Iop_Shl64x2: + case Iop_Shr8x16: case Iop_Shr16x8: case Iop_Shr32x4: case Iop_Shr64x2: + case Iop_Sar8x16: case Iop_Sar16x8: case Iop_Sar32x4: case Iop_Sar64x2: + case Iop_Sal8x16: case Iop_Sal16x8: case Iop_Sal32x4: case Iop_Sal64x2: + case Iop_Rol8x16: case Iop_Rol16x8: case Iop_Rol32x4: case Iop_Rol64x2: + case Iop_QShl8x16: case Iop_QShl16x8: case Iop_QShl32x4: case Iop_QShl64x2: + case Iop_QSal8x16: case Iop_QSal16x8: case Iop_QSal32x4: case Iop_QSal64x2: + case Iop_QShlNsatSU8x16: case Iop_QShlNsatSU16x8: + case Iop_QShlNsatSU32x4: case Iop_QShlNsatSU64x2: + case Iop_QShlNsatUU8x16: case Iop_QShlNsatUU16x8: + case Iop_QShlNsatUU32x4: case Iop_QShlNsatUU64x2: + case Iop_QShlNsatSS8x16: case Iop_QShlNsatSS16x8: + case Iop_QShlNsatSS32x4: case Iop_QShlNsatSS64x2: + case Iop_QandUQsh8x16: case Iop_QandUQsh16x8: + case Iop_QandUQsh32x4: case Iop_QandUQsh64x2: + case Iop_QandSQsh8x16: case Iop_QandSQsh16x8: + case Iop_QandSQsh32x4: case Iop_QandSQsh64x2: + case Iop_QandUQRsh8x16: case Iop_QandUQRsh16x8: + case Iop_QandUQRsh32x4: case Iop_QandUQRsh64x2: + case Iop_QandSQRsh8x16: case Iop_QandSQRsh16x8: + case Iop_QandSQRsh32x4: case Iop_QandSQRsh64x2: + case Iop_Sh8Sx16: case Iop_Sh16Sx8: case Iop_Sh32Sx4: case Iop_Sh64Sx2: + case Iop_Sh8Ux16: case Iop_Sh16Ux8: case Iop_Sh32Ux4: case Iop_Sh64Ux2: + case Iop_Rsh8Sx16: case Iop_Rsh16Sx8: case Iop_Rsh32Sx4: case Iop_Rsh64Sx2: + case Iop_Rsh8Ux16: case Iop_Rsh16Ux8: case Iop_Rsh32Ux4: case Iop_Rsh64Ux2: + case Iop_QandQShrNnarrow16Uto8Ux8: + case Iop_QandQShrNnarrow32Uto16Ux4: case Iop_QandQShrNnarrow64Uto32Ux2: + case Iop_QandQSarNnarrow16Sto8Sx8: + case Iop_QandQSarNnarrow32Sto16Sx4: case Iop_QandQSarNnarrow64Sto32Sx2: + case Iop_QandQSarNnarrow16Sto8Ux8: + case Iop_QandQSarNnarrow32Sto16Ux4: case Iop_QandQSarNnarrow64Sto32Ux2: + case Iop_QandQRShrNnarrow16Uto8Ux8: + case Iop_QandQRShrNnarrow32Uto16Ux4: case Iop_QandQRShrNnarrow64Uto32Ux2: + case Iop_QandQRSarNnarrow16Sto8Sx8: + case Iop_QandQRSarNnarrow32Sto16Sx4: case Iop_QandQRSarNnarrow64Sto32Sx2: + case Iop_QandQRSarNnarrow16Sto8Ux8: + case Iop_QandQRSarNnarrow32Sto16Ux4: case Iop_QandQRSarNnarrow64Sto32Ux2: + case Iop_QNarrowBin16Sto8Ux16: case Iop_QNarrowBin32Sto16Ux8: + case Iop_QNarrowBin16Sto8Sx16: case Iop_QNarrowBin32Sto16Sx8: + case Iop_QNarrowBin16Uto8Ux16: case Iop_QNarrowBin32Uto16Ux8: + case Iop_NarrowBin16to8x16: case Iop_NarrowBin32to16x8: + case Iop_QNarrowBin64Sto32Sx4: case Iop_QNarrowBin64Uto32Ux4: + case Iop_NarrowBin64to32x4: + case Iop_NarrowUn16to8x8: case Iop_NarrowUn32to16x4: + case Iop_NarrowUn64to32x2: + case Iop_QNarrowUn16Sto8Sx8: case Iop_QNarrowUn32Sto16Sx4: + case Iop_QNarrowUn64Sto32Sx2: + case Iop_QNarrowUn16Sto8Ux8: case Iop_QNarrowUn32Sto16Ux4: + case Iop_QNarrowUn64Sto32Ux2: + case Iop_QNarrowUn16Uto8Ux8: case Iop_QNarrowUn32Uto16Ux4: + case Iop_QNarrowUn64Uto32Ux2: + case Iop_Widen8Uto16x8: case Iop_Widen16Uto32x4: case Iop_Widen32Uto64x2: + case Iop_Widen8Sto16x8: case Iop_Widen16Sto32x4: case Iop_Widen32Sto64x2: + case Iop_InterleaveHI8x16: case Iop_InterleaveHI16x8: + case Iop_InterleaveHI32x4: case Iop_InterleaveHI64x2: + case Iop_InterleaveLO8x16: case Iop_InterleaveLO16x8: + case Iop_InterleaveLO32x4: case Iop_InterleaveLO64x2: + case Iop_InterleaveOddLanes8x16: case Iop_InterleaveEvenLanes8x16: + case Iop_InterleaveOddLanes16x8: case Iop_InterleaveEvenLanes16x8: + case Iop_InterleaveOddLanes32x4: case Iop_InterleaveEvenLanes32x4: + case Iop_PackOddLanes8x16: case Iop_PackEvenLanes8x16: + case Iop_PackOddLanes16x8: case Iop_PackEvenLanes16x8: + case Iop_PackOddLanes32x4: case Iop_PackEvenLanes32x4: + case Iop_CatOddLanes8x16: case Iop_CatOddLanes16x8: case Iop_CatOddLanes32x4: + case Iop_CatEvenLanes8x16: case Iop_CatEvenLanes16x8: + case Iop_CatEvenLanes32x4: + case Iop_GetElem8x16: case Iop_GetElem16x8: case Iop_GetElem32x4: + case Iop_GetElem64x2: + case Iop_SetElem8x16: case Iop_SetElem16x8: case Iop_SetElem32x4: + case Iop_SetElem64x2: + case Iop_Dup8x16: case Iop_Dup16x8: case Iop_Dup32x4: + case Iop_SliceV128: case Iop_Reverse8sIn16_x8: + case Iop_Reverse8sIn32_x4: case Iop_Reverse16sIn32_x4: + case Iop_Reverse8sIn64_x2: case Iop_Reverse16sIn64_x2: + case Iop_Reverse32sIn64_x2: case Iop_Reverse1sIn8_x16: case Iop_Perm8x16: + case Iop_Perm32x4: case Iop_PermOrZero8x16: case Iop_Perm8x16x2: + case Iop_GetMSBs8x16: case Iop_RecipEst32Ux4: case Iop_RSqrtEst32Ux4: + case Iop_MulI128by10: case Iop_MulI128by10Carry: case Iop_MulI128by10E: + case Iop_MulI128by10ECarry: case Iop_V256to64_0: case Iop_V256to64_1: + case Iop_V256to64_2: case Iop_V256to64_3: case Iop_64x4toV256: + case Iop_V256toV128_0: case Iop_V256toV128_1: case Iop_V128HLtoV256: + case Iop_AndV256: case Iop_OrV256: case Iop_XorV256: + case Iop_NotV256: + case Iop_CmpNEZ8x32: case Iop_CmpNEZ16x16: case Iop_CmpNEZ32x8: + case Iop_CmpNEZ64x4: + case Iop_Add8x32: case Iop_Add16x16: case Iop_Add32x8: case Iop_Add64x4: + case Iop_Sub8x32: case Iop_Sub16x16: case Iop_Sub32x8: case Iop_Sub64x4: + case Iop_CmpEQ8x32: case Iop_CmpEQ16x16: case Iop_CmpEQ32x8: + case Iop_CmpEQ64x4: + case Iop_CmpGT8Sx32: case Iop_CmpGT16Sx16: case Iop_CmpGT32Sx8: + case Iop_CmpGT64Sx4: + case Iop_ShlN16x16: case Iop_ShlN32x8: case Iop_ShlN64x4: + case Iop_ShrN16x16: case Iop_ShrN32x8: case Iop_ShrN64x4: + case Iop_SarN16x16: case Iop_SarN32x8: + case Iop_Max8Sx32: case Iop_Max16Sx16: case Iop_Max32Sx8: + case Iop_Max8Ux32: case Iop_Max16Ux16: case Iop_Max32Ux8: + case Iop_Min8Sx32: case Iop_Min16Sx16: case Iop_Min32Sx8: + case Iop_Min8Ux32: case Iop_Min16Ux16: case Iop_Min32Ux8: + case Iop_Mul16x16: case Iop_Mul32x8: + case Iop_MulHi16Ux16: case Iop_MulHi16Sx16: + case Iop_QAdd8Ux32: case Iop_QAdd16Ux16: + case Iop_QAdd8Sx32: case Iop_QAdd16Sx16: + case Iop_QSub8Ux32: case Iop_QSub16Ux16: + case Iop_QSub8Sx32: case Iop_QSub16Sx16: + case Iop_Avg8Ux32: case Iop_Avg16Ux16: + case Iop_Perm32x8: + case Iop_CipherV128: case Iop_CipherLV128: case Iop_CipherSV128: + case Iop_NCipherV128: case Iop_NCipherLV128: + case Iop_SHA512: case Iop_SHA256: + case Iop_Add64Fx4: case Iop_Sub64Fx4: case Iop_Mul64Fx4: case Iop_Div64Fx4: + case Iop_Add32Fx8: case Iop_Sub32Fx8: case Iop_Mul32Fx8: case Iop_Div32Fx8: + case Iop_I32StoF32x8: case Iop_F32toI32Sx8: case Iop_F32toF16x8: + case Iop_F16toF32x8: case Iop_Sqrt32Fx8: case Iop_Sqrt64Fx4: + case Iop_RSqrtEst32Fx8: case Iop_RecipEst32Fx8: + case Iop_Max32Fx8: case Iop_Min32Fx8: + case Iop_Max64Fx4: case Iop_Min64Fx4: + case Iop_Rotx32: case Iop_Rotx64: + return False; + + default: + vpanic("primopMightTrap"); + + } +} + void ppIRExpr ( const IRExpr* e ) { Int i; diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 087a414573..9120a49fc4 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -2013,6 +2013,11 @@ extern void typeOfPrimop ( IROp op, /*OUTs*/ IRType* t_dst, IRType* t_arg1, IRType* t_arg2, IRType* t_arg3, IRType* t_arg4 ); +/* Might the given primop trap (eg, attempt integer division by zero)? If in + doubt returns True. However, the vast majority of primops will never + trap. */ +extern Bool primopMightTrap ( IROp op ); + /* Encoding of IEEE754-specified rounding modes. Note, various front and back ends rely on the actual numerical values of these, so do not change them. */