private void collectBoogieCmds(BoogieCmd cmd, List <BoogieCmd> cmds) { if (cmd is BoogieStructuredCmd) { if (cmd is BoogieIfCmd) { BoogieIfCmd ifCmd = (BoogieIfCmd)cmd; foreach (var c in ifCmd.ThenBody.BigBlocks[0].SimpleCmds) { collectBoogieCmds(c, cmds); } if (ifCmd.ElseBody != null) { foreach (var c in ifCmd.ElseBody.BigBlocks[0].SimpleCmds) { collectBoogieCmds(c, cmds); } } } else if (cmd is BoogieWhileCmd) { BoogieWhileCmd whileCmd = (BoogieWhileCmd)cmd; foreach (var c in whileCmd.Body.BigBlocks[0].SimpleCmds) { collectBoogieCmds(c, cmds); } } else { cmds.Add(cmd); } } else { cmds.Add(cmd); } }
private void generateRevertLogicForCmd(BoogieCmd cmd, BoogieStmtList parent, bool isFail, bool inHarness) { List <BoogieExpr> dupAndReplaceExprList(List <BoogieExpr> exprs) { return(exprs.Select(e => dupAndReplaceExpr(e, isFail, inHarness)).ToList()); } BoogieStmtList dupAndReplaceStmList(BoogieStmtList stmtList) { if (stmtList == null) { return(null); } BoogieStmtList newList = new BoogieStmtList(); stmtList.BigBlocks[0].SimpleCmds.ForEach(c => generateRevertLogicForCmd(c, newList, isFail, inHarness)); return(newList); } if (cmd is BoogieAssignCmd assignCmd) { parent.AddStatement(new BoogieAssignCmd(dupAndReplaceExpr(assignCmd.Lhs, isFail, inHarness), dupAndReplaceExpr(assignCmd.Rhs, isFail, inHarness))); } else if (cmd is BoogieCallCmd callCmd) { string calleeName = callCmd.Callee; bool emitCheckRevertLogic = false; if (!isHarnessProcudure(calleeName) && procsWiltImplNames.Contains(calleeName)) { if (!inHarness || !isPublic(proceduresInProgram[calleeName])) { calleeName = calleeName + (isFail ? "__fail" : "__success"); emitCheckRevertLogic = !inHarness; } } var newIns = callCmd.Ins != null?dupAndReplaceExprList(callCmd.Ins) : null; var newOuts = callCmd.Outs != null?callCmd.Outs.Select(e => (BoogieIdentifierExpr)dupAndReplaceExpr(e, isFail, inHarness)).ToList() : null; parent.AddStatement(new BoogieCallCmd(calleeName, newIns, newOuts)); if (emitCheckRevertLogic) { BoogieStmtList thenBody = new BoogieStmtList(); thenBody.AddStatement(new BoogieReturnCmd()); parent.AddStatement(new BoogieIfCmd(new BoogieIdentifierExpr("revert"), thenBody, null)); } } else if (cmd is BoogieAssertCmd assertCmd) { if (!isFail) { parent.AddStatement(new BoogieAssertCmd(dupAndReplaceExpr(assertCmd.Expr, false, inHarness), assertCmd.Attributes)); } } else if (cmd is BoogieAssumeCmd assumeCmd) { parent.AddStatement(new BoogieAssumeCmd(dupAndReplaceExpr(assumeCmd.Expr, isFail, inHarness))); } else if (cmd is BoogieLoopInvCmd loopInvCmd) { parent.AddStatement(new BoogieLoopInvCmd(dupAndReplaceExpr(loopInvCmd.Expr, isFail, inHarness))); } else if (cmd is BoogieReturnExprCmd returnExprCmd) { // This one does not seem to be used. parent.AddStatement(new BoogieReturnExprCmd(dupAndReplaceExpr(returnExprCmd.Expr, isFail, inHarness))); } else if (cmd is BoogieHavocCmd havocCmd) { parent.AddStatement(new BoogieHavocCmd(havocCmd.Vars.Select(id => (BoogieIdentifierExpr)dupAndReplaceExpr(id, isFail, inHarness)).ToList())); } else if (cmd is BoogieIfCmd ifCmd) { parent.AddStatement(new BoogieIfCmd(dupAndReplaceExpr(ifCmd.Guard, isFail, inHarness), dupAndReplaceStmList(ifCmd.ThenBody), dupAndReplaceStmList(ifCmd.ElseBody))); } else if (cmd is BoogieWhileCmd whileCmd) { var body = dupAndReplaceStmList(whileCmd.Body); BoogieStmtList invsAsStmtList = new BoogieStmtList(); whileCmd.Invariants.ForEach(i => generateRevertLogicForCmd(i, invsAsStmtList, isFail, inHarness)); List <BoogiePredicateCmd> invs = invsAsStmtList.BigBlocks[0].SimpleCmds.Select(c => (BoogiePredicateCmd)c).ToList(); parent.AddStatement(new BoogieWhileCmd(dupAndReplaceExpr(whileCmd.Guard, isFail, inHarness), body, invs)); } else { parent.AddStatement(cmd); } }