case Ist_IMark:
return;
+ /* --------- NO-OP --------- */
+ /* Fairly self-explanatory, wouldn't you say? */
+ case Ist_NoOp:
+ return;
+
/* --------- EXIT --------- */
case Ist_Exit: {
X86RI* dst;
/* Ok, finally we can iterate over the statements. */
for (i = 0; i < bb->stmts_used; i++)
- if (bb->stmts[i])
- iselStmt(env,bb->stmts[i]);
+ iselStmt(env,bb->stmts[i]);
iselNext(env,bb->next,bb->jumpkind);
void ppIRStmt ( IRStmt* s )
{
+ if (!s) {
+ vex_printf("!!! IRStmt* which is NULL !!!");
+ return;
+ }
switch (s->tag) {
+ case Ist_NoOp:
+ vex_printf("IR-NoOp");
+ break;
case Ist_IMark:
vex_printf( "------ IMark(0x%llx, %d) ------",
s->Ist.IMark.addr, s->Ist.IMark.len);
ppIRDirty(s->Ist.Dirty.details);
break;
case Ist_MFence:
- vex_printf("IRMemoryFence");
+ vex_printf("IR-MFence");
break;
case Ist_Exit:
vex_printf( "if (" );
ppIRTypeEnv(bb->tyenv);
vex_printf("\n");
for (i = 0; i < bb->stmts_used; i++) {
- if (bb->stmts[i]) {
- vex_printf( " ");
- ppIRStmt(bb->stmts[i]);
- }
+ vex_printf( " ");
+ ppIRStmt(bb->stmts[i]);
vex_printf( "\n");
}
vex_printf( " goto {");
/* Constructors -- IRStmt */
+IRStmt* IRStmt_NoOp ( void )
+{
+ /* Just use a single static closure. */
+ static IRStmt static_closure;
+ static_closure.tag = Ist_NoOp;
+ return &static_closure;
+}
IRStmt* IRStmt_IMark ( Addr64 addr, Int len ) {
IRStmt* s = LibVEX_Alloc(sizeof(IRStmt));
s->tag = Ist_IMark;
}
IRStmt* IRStmt_MFence ( void )
{
- IRStmt* s = LibVEX_Alloc(sizeof(IRStmt));
- s->tag = Ist_MFence;
- return s;
+ /* Just use a single static closure. */
+ static IRStmt static_closure;
+ static_closure.tag = Ist_MFence;
+ return &static_closure;
}
IRStmt* IRStmt_Exit ( IRExpr* guard, IRJumpKind jk, IRConst* dst ) {
IRStmt* s = LibVEX_Alloc(sizeof(IRStmt));
IRStmt* dopyIRStmt ( IRStmt* s )
{
switch (s->tag) {
+ case Ist_NoOp:
+ return IRStmt_NoOp();
case Ist_IMark:
return IRStmt_IMark(s->Ist.IMark.addr, s->Ist.IMark.len);
case Ist_Put:
dopyIRExpr(s->Ist.STle.data));
case Ist_Dirty:
return IRStmt_Dirty(dopyIRDirty(s->Ist.Dirty.details));
+ case Ist_MFence:
+ return IRStmt_MFence();
case Ist_Exit:
return IRStmt_Exit(dopyIRExpr(s->Ist.Exit.guard),
s->Ist.Exit.jk,
bb2->stmts_used = bb2->stmts_size = bb->stmts_used;
sts2 = LibVEX_Alloc(bb2->stmts_used * sizeof(IRStmt*));
for (i = 0; i < bb2->stmts_used; i++)
- sts2[i] = bb->stmts[i]==NULL ? NULL : dopyIRStmt(bb->stmts[i]);
+ sts2[i] = dopyIRStmt(bb->stmts[i]);
bb2->stmts = sts2;
bb2->next = dopyIRExpr(bb->next);
bb2->jumpkind = bb->jumpkind;
if (di->mAddr && !isIRAtom(di->mAddr))
return False;
return True;
+ case Ist_NoOp:
case Ist_IMark:
case Ist_MFence:
return True;
if (d->mFx != Ifx_None)
useBeforeDef_Expr(bb,stmt,d->mAddr,def_counts);
break;
+ case Ist_NoOp:
case Ist_MFence:
break;
case Ist_Exit:
break;
bad_dirty:
sanityCheckFail(bb,stmt,"IRStmt.Dirty: ill-formed");
+ case Ist_NoOp:
case Ist_MFence:
break;
case Ist_Exit:
for (i = 0; i < bb->stmts_used; i++) {
stmt = bb->stmts[i];
if (!stmt)
- continue;
+ sanityCheckFail(bb, stmt, "IRStmt: is NULL");
if (!isFlatIRStmt(stmt))
sanityCheckFail(bb, stmt, "IRStmt: is not flat");
}
for (i = 0; i < bb->stmts_used; i++) {
stmt = bb->stmts[i];
- if (!stmt)
- continue;
useBeforeDef_Stmt(bb,stmt,def_counts);
if (stmt->tag == Ist_Tmp) {
IRExpr *e1, *e2;
IRDirty *d, *d2;
switch (st->tag) {
- case Ist_IMark:
- addStmtToIRBB(bb, st);
- break;
case Ist_Put:
if (isIRAtom(st->Ist.Put.data)) {
/* optimisation to reduce the amount of heap wasted
d2->args[i] = flatten_Expr(bb, d2->args[i]);
addStmtToIRBB(bb, IRStmt_Dirty(d2));
break;
+ case Ist_NoOp:
case Ist_MFence:
+ case Ist_IMark:
addStmtToIRBB(bb, st);
break;
case Ist_Exit:
vassert(isIRAtom(st->Ist.PutI.data));
break;
+ case Ist_NoOp:
case Ist_IMark:
break;
vex_printf("rPUT: "); ppIRStmt(st);
vex_printf("\n");
}
- bb->stmts[i] = NULL;
+ bb->stmts[i] = IRStmt_NoOp();
} else {
/* We can't demonstrate that this Put is redundant, so add it
to the running collection. */
/* Apply the subst to stmt, then fold the result as much as possible.
- Much simplified due to stmt being previously flattened. Returning
- NULL means the statement has been turned into a no-op. */
-
+ Much simplified due to stmt being previously flattened. As a
+ result of this, the stmt may wind up being turned into a no-op.
+*/
static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st )
{
# if 0
case Ist_IMark:
return IRStmt_IMark(st->Ist.IMark.addr, st->Ist.IMark.len);
+ case Ist_NoOp:
+ return IRStmt_NoOp();
+
case Ist_MFence:
return IRStmt_MFence();
|| fcond->Iex.Const.con->Ico.U1 == True);
if (fcond->Iex.Const.con->Ico.U1 == False) {
/* exit is never going to happen, so dump the statement. */
- return NULL;
+ return IRStmt_NoOp();
} else {
vassert(fcond->Iex.Const.con->Ico.U1 == True);
/* Hmmm. The exit has become unconditional. Leave it as
for (i = 0; d->args[i] != NULL; i++)
addUses_Expr(set, d->args[i]);
return;
+ case Ist_NoOp:
case Ist_IMark:
case Ist_MFence:
return;
ppIRStmt(st);
vex_printf("\n");
}
- bb->stmts[i] = NULL;
+ bb->stmts[i] = IRStmt_NoOp();
}
else
if (st->tag == Ist_Dirty
&& st->Ist.Dirty.details->guard
&& isZeroU1(st->Ist.Dirty.details->guard)) {
- /* This is a dirty helper which will never get called. Delete it. */
- bb->stmts[i] = NULL;
+ /* This is a dirty helper which will never get called.
+ Delete it. */
+ bb->stmts[i] = IRStmt_NoOp();
}
else {
/* Note any IRTemp uses made by the current statement. */
getArrayBounds(pi->Ist.PutI.descr, &minoffP, &maxoffP);
switch (s2->tag) {
+ case Ist_NoOp:
case Ist_IMark:
return False;
ppIRStmt(st);
vex_printf("\n");
}
- bb->stmts[i] = NULL;
+ bb->stmts[i] = IRStmt_NoOp();
}
}
Int i;
IRDirty* d;
switch (st->tag) {
+ case Ist_NoOp:
case Ist_IMark:
break;
case Ist_Put:
for (i = 0; d->args[i]; i++)
occCount_Expr(env, d->args[i]);
return;
+ case Ist_NoOp:
case Ist_IMark:
case Ist_MFence:
return;
);
case Ist_IMark:
return IRStmt_IMark(st->Ist.IMark.addr, st->Ist.IMark.len);
+ case Ist_NoOp:
+ return IRStmt_NoOp();
case Ist_MFence:
return IRStmt_MFence();
case Ist_Dirty:
if (d->mFx != Ifx_None)
vassert(isIRAtom(d->mAddr));
break;
+ case Ist_NoOp:
case Ist_IMark:
case Ist_MFence:
break;
/* The possible kinds of statements are as follows: */
typedef
- enum {
+ enum {
+ Ist_NoOp, /* no-op (usually resulting from IR optimisation) */
Ist_IMark, /* instruction mark: describe addr/len of guest insn
whose IR follows */
Ist_Put, /* write guest state, fixed offset */
struct _IRStmt {
IRStmtTag tag;
union {
+ struct {
+ } NoOp;
struct {
Addr64 addr;
Int len;
}
IRStmt;
+extern IRStmt* IRStmt_NoOp ( void );
extern IRStmt* IRStmt_IMark ( Addr64 addr, Int len );
extern IRStmt* IRStmt_Put ( Int off, IRExpr* data );
extern IRStmt* IRStmt_PutI ( IRArray* descr, IRExpr* ix, Int bias,