void ppIRConst ( IRConst* con )
{
switch (con->tag) {
- case Ico_U8: vex_printf( "0x%x", (UInt)(con->Ico.U8)); break;
- case Ico_U16: vex_printf( "0x%x", (UInt)(con->Ico.U16)); break;
- case Ico_U32: vex_printf( "0x%x", (UInt)(con->Ico.U32)); break;
- case Ico_U64: vex_printf( "0x%llx", (ULong)(con->Ico.U64)); break;
+ case Ico_Bit: vex_printf( "%d:Bit", con->Ico.Bit ? 1 : 0); break;
+ case Ico_U8: vex_printf( "0x%x:I8", (UInt)(con->Ico.U8)); break;
+ case Ico_U16: vex_printf( "0x%x:I16", (UInt)(con->Ico.U16)); break;
+ case Ico_U32: vex_printf( "0x%x:I32", (UInt)(con->Ico.U32)); break;
+ case Ico_U64: vex_printf( "0x%llx:I64", (ULong)(con->Ico.U64)); break;
case Ico_F64: vex_printf("(f64 value)"); break;
default: vpanic("ppIRConst");
}
/* Constructors -- IRConst */
+IRConst* IRConst_Bit ( Bool bit )
+{
+ IRConst* c = LibVEX_Alloc(sizeof(IRConst));
+ c->tag = Ico_Bit;
+ c->Ico.Bit = bit;
+ return c;
+}
IRConst* IRConst_U8 ( UChar u8 )
{
IRConst* c = LibVEX_Alloc(sizeof(IRConst));
IRType typeOfIRConst ( IRConst* con )
{
switch (con->tag) {
+ case Ico_Bit: return Ity_Bit;
case Ico_U8: return Ity_I8;
case Ico_U16: return Ity_I16;
case Ico_U32: return Ity_I32;
(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
& e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
break;
+ case Iop_Or32:
+ e2 = IRExpr_Const(IRConst_U32(
+ (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
+ | e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
+ break;
case Iop_Shl32:
e2 = IRExpr_Const(IRConst_U32(
(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
<< e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
break;
+ case Iop_CmpEQ32:
+ e2 = IRExpr_Const(IRConst_Bit(
+ (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32
+ == e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)));
+ break;
case Iop_32HLto64:
e2 = IRExpr_Const(IRConst_U64(
(((ULong)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U32)) << 32)
| ((ULong)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32))
));
break;
-
-case Iop_CmpEQ32:
- vex_printf("FOLD: warning, missed CmpEQ32\n");
-break;
default:
goto unhandled;
}
/* Apply the subst to stmt, then fold the result as much as possible.
- Much simplified due to stmt being previously flattened. */
+ Much simplified due to stmt being previously flattened. Returning
+ NULL means the statement has been turned into a no-op. */
static IRStmt* subst_and_fold_Stmt ( Hash64* env, IRStmt* st )
{
}
if (st->tag == Ist_Exit) {
- vassert(isAtom(st->Ist.Exit.cond));
- return IRStmt_Exit(
- fold_Expr(subst_Expr(env, st->Ist.Exit.cond)),
- st->Ist.Exit.dst
- );
+ IRExpr* fcond;
+ vassert(isAtom(st->Ist.Exit.cond));
+ fcond = fold_Expr(subst_Expr(env, st->Ist.Exit.cond));
+ if (fcond->tag == Iex_Const) {
+ /* Interesting. The condition on this exit has folded down to
+ a constant. */
+ vassert(fcond->Iex.Const.con->tag == Ico_Bit);
+ if (fcond->Iex.Const.con->Ico.Bit == False) {
+ /* exit is never going to happen, so dump the statement. */
+ return NULL;
+ } else {
+ vassert(fcond->Iex.Const.con->Ico.Bit == True);
+ /* Hmmm. The exit has become unconditional. Leave it as
+ it is for now, since we'd have to truncate the BB at
+ this point, which is tricky. */
+ /* fall out into the reconstruct-the-exit code. */
+ vex_printf("subst_and_fold_Stmt: IRStmt_Exit became unconditional\n");
+ }
+ }
+ return IRStmt_Exit(fcond,st->Ist.Exit.dst);
}
vex_printf("\n");
st2 = subst_and_fold_Stmt( env, in->stmts[i] );
+ /* If the statement has been folded into a no-op, forget it. */
+ if (!st2)
+ continue;
+
/* Now consider what the stmt looks like. If it's of the form
't = const' or 't1 = t2', add it to the running environment
and not to the output BB. Otherwise, add it to the output