//additional stuff needed to do for diff inlining is on private static void ProcessCounterexampleForDiffInline(SDiffCounterexamples errors, Implementation vtLeftProcImpl, Implementation vtRightProcImpl, Expr disjunctionDiffCond) { if (vtLeftProcImpl != null && vtRightProcImpl != null) { var blocksLeftProcImpl = vtLeftProcImpl.Blocks.ToArray(); var blocksRightProcImpl = vtRightProcImpl.Blocks.ToArray(); var firstCmdSecondBlockLeft = new AssumeCmd(Token.NoToken, disjunctionDiffCond); var firstCmdSecondBlockRight = new AssumeCmd(Token.NoToken, disjunctionDiffCond); var firstCmdThirdBlockLeft = new AssumeCmd(Token.NoToken, Expr.Not(disjunctionDiffCond)); var firstCmdThirdBlockRight = new AssumeCmd(Token.NoToken, Expr.Not(disjunctionDiffCond)); if (Options.PropagateSingleDifference && errors.Count > 1) { firstCmdThirdBlockLeft = new AssumeCmd(Token.NoToken, Expr.False); firstCmdThirdBlockRight = new AssumeCmd(Token.NoToken, Expr.False); } var leftSecondBlockCmdElems = blocksLeftProcImpl[1].Cmds; var leftThirdBlockCmdElems = blocksLeftProcImpl[2].Cmds; var rightSecondBlockCmdElems = blocksRightProcImpl[1].Cmds; var rightThirdBlockCmdElems = blocksRightProcImpl[2].Cmds; leftSecondBlockCmdElems[0] = firstCmdSecondBlockLeft; leftThirdBlockCmdElems[0] = firstCmdThirdBlockLeft; rightSecondBlockCmdElems[0] = firstCmdSecondBlockRight; rightThirdBlockCmdElems[0] = firstCmdThirdBlockRight; blocksLeftProcImpl[1].Cmds = leftSecondBlockCmdElems; blocksLeftProcImpl[2].Cmds = leftThirdBlockCmdElems; blocksRightProcImpl[1].Cmds = rightSecondBlockCmdElems; blocksRightProcImpl[2].Cmds = rightThirdBlockCmdElems; } }
public static void ProcessCounterexamplesWOSymbolicOut(SDiffCounterexamples errors, List <Variable> globals, List <Variable> eqLocVars, Implementation vtLeftProcImpl, Implementation vtRightProcImpl, List <Declaration> consts, List <Model> errModelList) { //inlining Cex (trace) within the Diff_inline body var impName = errors[0].Impl.Name.Replace("EQ_", ""); var index = impName.IndexOf("__xx__"); //avoid aliasing with funcs with x___y names var v1Name = impName.Substring(0, index); var v2Name = impName.Substring(index + 6); var indexPointV1Name = v1Name.IndexOf("."); var indexPointV2Name = v2Name.IndexOf("."); v1Name = v1Name.Substring(0, indexPointV1Name); v2Name = v2Name.Substring(0, indexPointV2Name); ProcessCounterexamplesWOSymbolicOut(errors, globals, eqLocVars, vtLeftProcImpl, vtRightProcImpl, consts, errModelList, v1Name, v2Name); }
public static int RunVerificationTask(VerificationTask vt, VC.ConditionGeneration vcgen, Program prog, out bool crashed, bool wrapper = true) { crashed = false; var attList = new List <Object>(1); attList.Add(Expr.Literal(1)); //save attributes var sqkLeft = vt.Left.Attributes; var sqkpLeft = vt.Left.Proc.Attributes; var sqkRight = vt.Right.Attributes; var sqkpRight = vt.Right.Proc.Attributes; //save postconditions var leftPosts = vt.Left.Proc.Ensures; var rightPosts = vt.Right.Proc.Ensures; //The ensures must have been removed at the time of stripContracts //The recursive case is handled by RVT option anyway. //vt.Left.Proc.Ensures = new List<Ensures>(); //vt.Right.Proc.Ensures = new List<Ensures>(); //inline procedures under analysis vt.Left.Attributes = Util.MkInlinedAttribute(attList); vt.Left.Proc.Attributes = vt.Left.Attributes; vt.Right.Attributes = Util.MkInlinedAttribute(attList); vt.Right.Proc.Attributes = vt.Right.Attributes; //RUN INLINER OVER EQ FUNCTION vt.Left.OriginalBlocks = vt.Left.Blocks; vt.Left.OriginalLocVars = vt.Left.LocVars; vt.Right.OriginalBlocks = vt.Right.Blocks; vt.Right.OriginalLocVars = vt.Right.LocVars; // inline diff_inline procedures IEnumerable <Declaration> procImplPIter = prog.TopLevelDeclarations.Where(x => x is Implementation); foreach (Implementation currentProcImpl in procImplPIter) { if (currentProcImpl.Name.Contains("_Diff_Inline")) { currentProcImpl.Attributes = Util.MkInlinedAttribute(attList); currentProcImpl.Proc.Attributes = Util.MkInlinedAttribute(attList); //RUN INLINER OVER EQ FUNCTION currentProcImpl.OriginalBlocks = currentProcImpl.Blocks; currentProcImpl.OriginalLocVars = currentProcImpl.LocVars; } } // prog = EQ program // vt.Eq = EQ_f_f' procedure with f, f' having {inline} tags Inliner.ProcessImplementation(prog, vt.Eq); SDiffCounterexamples SErrors = null; List <Model> errModelList = null; Implementation newEq = null; Program newProg = null; Dictionary <string, Declaration> newDict = null; Log.Out(Log.Verifier, "Verifying " + vt.Eq.Name); if (Options.TraceVerify) { Log.Out(Log.Normal, "Ready to verify:"); Log.LogEmit(Log.Normal, prog.Emit); } // To print the EQ files in Util.DumpBplAST(prog, vt.Eq.Name + "_out.bpl"); //RS: Uncomment this /*if (wrapper) * { * prog.RemoveTopLevelDeclaration(vt.Eq); * prog.RemoveTopLevelDeclaration(vt.Eq.Proc); * }*/ prog = null; ReplaceInFile(vt.Eq.Name + "_out.bpl", "@", "_"); if (!wrapper) { prog = BoogieUtils.ParseProgram("RS" + vt.Eq.Name + "_out.bpl"); if (prog == null) { Log.Out(Log.Verifier, "Parse Error!!! in " + vt.Eq.Name); return(1); } if (BoogieUtils.ResolveAndTypeCheckThrow(prog, Options.MergedProgramOutputFile)) { return(1); } newEq = vt.Eq; newProg = prog; vcgen = InitializeVC(newProg); //SDiff.Boogie.Process.ResolveAndTypeCheck(newProg, ""); newDict = SDiff.Boogie.Process.BuildProgramDictionary(newProg.TopLevelDeclarations.ToList()); //RS: Uncomment this newEq = (Implementation)newDict.Get(vt.Eq.Name + "$IMPL"); vt.Result = VerifyImplementation(vcgen, newEq, newProg, out SErrors, out errModelList); switch (vt.Result) { case VerificationResult.Error: Log.Out(Log.Verifier, "Result: Error"); break; case VerificationResult.Verified: Log.Out(Log.Verifier, "Result: Verified"); break; case VerificationResult.OutOfMemory: Log.Out(Log.Verifier, "Result: OutOfMemory"); break; case VerificationResult.TimeOut: Log.Out(Log.Verifier, "Result: TimeOut"); break; default: Log.Out(Log.Verifier, "Result: Unhandled"); crashed = true; break; } vcgen.Close(); } //restore postconditions IN THE OLD IN-MEMORY PROGRAM vt.Left.Proc.Ensures = leftPosts; vt.Right.Proc.Ensures = rightPosts; //remove the inline annotation IN THE OLD IN-MEMORY PROGRAM vt.Left.Attributes = sqkLeft; vt.Left.Proc.Attributes = sqkpLeft; vt.Right.Attributes = sqkRight; vt.Right.Proc.Attributes = sqkpRight; //remove the inline annotation in the Diff_Inline Procedures foreach (Implementation currentProcImpl in procImplPIter) { if (currentProcImpl.Name.Contains("_Diff_Inline")) { currentProcImpl.Attributes = null; currentProcImpl.Proc.Attributes = null; } } if (!wrapper) { if (vt.Result != VerificationResult.Error) { return(0); //even timeouts/unhandled, as we see timeouts with 1 error, 0 model } //process counterexamples OVER THE NEW IN-MEMORY PROGRAM var outputVars = new List <Variable>(); foreach (var v in vt.DesiredOutputVars) { outputVars.Add(newDict.Get(v.Name + "$VAR") as Variable); } var globals = new List <Variable>(); foreach (IdentifierExpr ie in newEq.Proc.Modifies) { globals.Add(ie.Decl); } if (SErrors != null && SErrors.Count > 0 && errModelList.Count == SErrors.Count) //change as now SErrors can be nonnull, yet Count == 0. Sometimes model.Count < SErrror!! { //somewhat misnamed... if (Options.DumpBeforeVerifying) { Log.Out(Log.SymEx, "Dumping procedure under verification"); newEq.Emit(Log.LogWriter, 0); } if (Options.DoSymEx) { var vtLeftProcImpl = (Implementation)Util.getDeclarationByName(vt.Left.Name + "_Diff_Inline", procImplPIter); var vtRightProcImpl = (Implementation)Util.getDeclarationByName(vt.Right.Name + "_Diff_Inline", procImplPIter); if (Options.PreciseDifferentialInline) { List <Declaration> consts = prog.TopLevelDeclarations.Where(x => x is Constant).ToList(); ProcessCounterexamplesWOSymbolicOut(SErrors, globals, vt.Eq.LocVars, vtLeftProcImpl, vtRightProcImpl, consts, errModelList); } else { ProcessCounterexamples(SErrors, globals, outputVars, newProg, vtLeftProcImpl, vtRightProcImpl); } } } return(SErrors == null ? 0 : SErrors.Count); } return(0); }
public static void ProcessCounterexamplesWOSymbolicOut(SDiffCounterexamples errors, List <Variable> globals, List <Variable> eqLocVars, Implementation vtLeftProcImpl, Implementation vtRightProcImpl, List <Declaration> consts, List <Model> errModelList, string v1Name, string v2Name) { List <Expr> constraintExprs = new List <Expr>(); List <Block> listBlocksV1 = new List <Block>(); List <Block> listBlocksV2 = new List <Block>(); Model[] errModelArray = errModelList.ToArray(); var label = new GotoCmd(Token.NoToken, new List <String>() { "DONE" }); label.labelNames = new List <string>(); // label.labelTargets = new List<Block>(); label.labelNames.Add("DONE"); //label.labelTargets.Add("DONE"); // First block var labels = new List <String>(); for (int j = 0; j < errors.Count; j++) { labels.Add("Cex" + j); } labels.Add("ELSE"); var labelEntry = new GotoCmd(Token.NoToken, labels); labelEntry.labelTargets = new List <Block>(); for (int j = 0; j < errors.Count; j++) { labelEntry.labelNames.Add("Cex" + j);//labelEntry.labelTargets.Add("Cex" + j); } for (int i = 0; i < errors.Count; i++) { var impl = errors[i].Impl; var trace = errors[i].Trace; //Log.Out(Log.Normal, "Attempting symbolic execution of [" + i + "] $ " + impl.Name); if (Options.GenerateCTrace) { Log.Out(Log.Normal, "Constructing metatrace from location annotations"); var extractor = new SDiff.SymEx.TraceExtractor(); extractor.VisitTrace(trace); //Log.Out(Log.CTrace, CTrace.Make(extractor.metaTrace)); var cTrace = CTrace.Make(extractor.metaTrace, consts, errModelArray[i], v1Name, v2Name); //var cTrace = ""; if (cTrace.Trim() != "") { //note that the index for cex on the output shows 1,2,..., instead of 0,1,2.... var fname = impl.Name + "_cex_" + (i + 1) + "_out.c"; var cexOut = new TokenTextWriter(impl.Name + "_cex_" + (i + 1) + "_out.c", true); cexOut.WriteLine(cTrace); cexOut.Close(); Log.Out(Log.CTrace, "n:" + (i + 1) + ":" + fname); Log.Out(Log.CTrace, "w:" + fname); } } Log.Out(Log.Normal, "Desugaring calls"); //HACK!!!: changes havoc x; assume (x= uf(..)); --> x := uf(...) var deCall = new SDiff.SymEx.DesugarCallCmds(); trace = deCall.VisitTrace(trace); //symbolic constants var symInParams = new List <Variable>(impl.InParams); foreach (var g in globals) { symInParams.Add(g); } Log.Out(Log.Normal, "Executing trace downward"); //symbolic stores (look at symex.cs for the datastructure) // var sTrace = SDiff.SymEx.Cexecutor.ExecDown(trace, symInParams); Log.Out(Log.Normal, "Executing trace upward"); //looks at each assume to create the path constants //clean up the duplication of assignments //SDiff.SymEx.Cexecutor.ExecUp(sTrace); Log.Out(Log.Normal, "Grabbing final execution values"); // var lastStore = sTrace.LastSCmd().Gammas.Last(); // var firstCons = sTrace.FirstSCmd().Cons; // constraintExprs.Add(firstCons.Conjoin()); //#hemr - generating new strategy right here with inlining counterexamples! // Second block List <Cmd> cmdsV1_Diff_inline = new List <Cmd>(); List <Cmd> cmdsV2_Diff_inline = new List <Cmd>(); Substitution replaceScopeV1 = delegate(Variable x) { return(replaceScopeGeneric(vtLeftProcImpl, x)); }; Substitution replaceScopeV2 = delegate(Variable x) { return(replaceScopeGeneric(vtRightProcImpl, x)); }; foreach (Block currentBlock in trace) { if (currentBlock.ToString().Contains("inline$" + v1Name)) { foreach (Cmd currentCmd in currentBlock.Cmds) { Cmd newCmd = Substituter.Apply(replaceScopeV1, currentCmd); cmdsV1_Diff_inline.Add(newCmd); } } else if (currentBlock.ToString().Contains("inline$" + v2Name)) { foreach (Cmd currentCmd in currentBlock.Cmds) { Cmd newCmd = Substituter.Apply(replaceScopeV2, currentCmd); cmdsV2_Diff_inline.Add(newCmd); } } } Block blockV1 = new Block(Token.NoToken, "Cex" + i, cmdsV1_Diff_inline, label); Block blockV2 = new Block(Token.NoToken, "Cex" + i, cmdsV2_Diff_inline, label); listBlocksV1.Add(blockV1); listBlocksV2.Add(blockV2); //#hemr - displaying values related to error model (at console level) Model currentModel = errModelArray[i]; //var keys = currentModel.identifierToPartition.Keys; var keys = currentModel.Functions.Where(f => f.Arity == 0).Select(f => f.GetConstant()); } Expr disjunctionDiffCond = Expr.False; foreach (Expr currentExpr in constraintExprs) { disjunctionDiffCond = Expr.Or(disjunctionDiffCond, currentExpr); } ProcessCounterexampleForDiffInliningWOSymbolicOut(eqLocVars, vtLeftProcImpl, vtRightProcImpl, v1Name, v2Name, listBlocksV1, listBlocksV2, labelEntry); }
public static void ProcessCounterexamples(SDiffCounterexamples errors, List <Variable> globals, List <Variable> outputVars, Program prog, Implementation vtLeftProcImpl, Implementation vtRightProcImpl) { List <Expr> constraintExprs = new List <Expr>(); for (int i = 0; i < errors.Count; i++) { var impl = errors[i].Impl; var trace = errors[i].Trace; Log.Out(Log.Normal, "Attempting symbolic execution of [" + (i + 1) + "] $ " + impl.Name); if (Options.GenerateCTrace) { Log.Out(Log.Normal, "Constructing metatrace from location annotations"); var extractor = new SDiff.SymEx.TraceExtractor(); extractor.VisitTrace(trace); //Log.Out(Log.CTrace, CTrace.Make(extractor.metaTrace)); var cTrace = CTrace.Make(extractor.metaTrace, null, null, "", ""); //var cTrace = ""; if (cTrace.Trim() != "") { var fname = impl.Name + "_cex_" + (i + 1) + "_out.c"; var cexOut = new TokenTextWriter(impl.Name + "_cex_" + (i + 1) + "_out.c", true); cexOut.WriteLine(cTrace); cexOut.Close(); Log.Out(Log.CTrace, "n:" + (i + 1) + ":" + fname); Log.Out(Log.CTrace, "w:" + fname); } } Log.Out(Log.Normal, "Desugaring calls"); //HACK!!!: changes havoc x; assume (x= uf(..)); --> x := uf(...) var deCall = new SDiff.SymEx.DesugarCallCmds(); trace = deCall.VisitTrace(trace); //symbolic constants var symInParams = new List <Variable>(impl.InParams); foreach (var g in globals) { symInParams.Add(g); } Log.Out(Log.Normal, "Executing trace downward"); //symbolic stores (look at symex.cs for the datastructure) var sTrace = SDiff.SymEx.Cexecutor.ExecDown(trace, symInParams); Log.Out(Log.Normal, "Executing trace upward"); //looks at each assume to create the path constants //clean up the duplication of assignments SDiff.SymEx.Cexecutor.ExecUp(sTrace); if (Options.DumpSymTrace) { SDiff.SymEx.CexDumper.PrintSymbolicTrace(sTrace); } //printing the symbolic stores at exit //still in SSA form Log.Out(Log.Normal, "Grabbing final execution values"); var lastStore = sTrace.LastSCmd().Gammas.Last(); var firstCons = sTrace.FirstSCmd().Cons; //resolves the outputs to be expressions over uif and symbolic constants only Log.Out(Log.Normal, "Resolving result expressions"); var outSymExprs = new List <Expr>(); foreach (var v in outputVars) { outSymExprs.Add(SymEx.ResolveSymExpr.Resolve(v, lastStore)); } Log.Out(Log.SymEx, "SymEx Results==================================="); Log.Out(Log.SymEx, "Input constraint"); if (Options.EraseUFArgumentsOnPrintout) // f(..) { var eraser = new ArgumentParameterEraser(); var duper = new Duplicator(); var dupConst = new SDiff.SymEx.Constraint(firstCons, true); foreach (var e in dupConst.Conjuncts) { eraser.VisitExpr(e); } Log.LogEmit(Log.SymEx, 1, dupConst.Emit); } else { Log.LogEmit(Log.SymEx, 1, firstCons.Emit); } constraintExprs.Add(firstCons.Conjoin()); Console.WriteLine(); Log.Out(Log.SymEx, "Symbolic output values"); var outSymExprsPrintable = outSymExprs; if (Options.EraseUFArgumentsOnPrintout) // f(..) { outSymExprsPrintable = new List <Expr>(); var eraser = new ArgumentParameterEraser(); var duper = new Duplicator(); foreach (Expr e in outSymExprs) { var ex = duper.VisitExpr(e); eraser.VisitExpr(ex); outSymExprsPrintable.Add(ex); } } //if the output variables aren't paired, iterate through normally if (outputVars.Count % 2 != 0) { for (int j = 0; j < outputVars.Count; j++) { Log.Out(Log.SymEx, "\t" + outputVars[j].ToString() + ": "); Log.LogEmit(Log.SymEx, 2, outSymExprsPrintable[j].Emit); Log.Out(Log.Normal, ""); } } //otherwise don't print a pair if it's syntactically equal else { for (int j = 0; j < outputVars.Count; j += 2) { if (!outSymExprs[j].StringEquals(outSymExprs[j + 1])) { Log.Out(Log.SymEx, "\t" + outputVars[j].ToString() + ": "); Log.LogEmit(Log.SymEx, 2, outSymExprsPrintable[j].Emit); Log.Out(Log.Normal, ""); Log.Out(Log.SymEx, "\t" + outputVars[j + 1].ToString() + ": "); Log.LogEmit(Log.SymEx, 2, outSymExprsPrintable[j + 1].Emit); Log.Out(Log.Normal, ""); } } } } Expr disjunctionDiffCond = Expr.False; if (Options.PropagateSingleDifference && errors.Count > 1) { var t = constraintExprs.First(); disjunctionDiffCond = Expr.Or(disjunctionDiffCond, constraintExprs.First()); } else { foreach (Expr currentExpr in constraintExprs) { disjunctionDiffCond = Expr.Or(disjunctionDiffCond, currentExpr); } } ProcessCounterexampleForDiffInline(errors, vtLeftProcImpl, vtRightProcImpl, disjunctionDiffCond); }
public static VerificationResult VerifyImplementation(VC.ConditionGeneration vcgen, Implementation impl, Program prog, out SDiffCounterexamples cex, out List <Model> errModelList) { VerifyImplCleanup vic; vic = new VerifyImplCleanup(); vic.Visit(prog); cex = null; errModelList = null; if (impl == null) { Log.Out(Log.Urgent, "VerifyImplementation saw null implementation"); return(VerificationResult.Unknown); } //Log.Out(Log.Verifier, "Verifying implementation " + impl.Name); List <Counterexample> errors; List <Model> errorsModel; VerificationResult sdoutcome = VerificationResult.Unknown; VC.VCGen.Outcome outcome; //Log.Out(Log.Verifier, "Saving implementation before Boogie preprocessing"); var duper = new Duplicator(); var imperativeBlocks = new Dictionary <string, Block>(); foreach (Block b in impl.Blocks) { //new: to avoid repeated blocks (MYSTERY) if (!imperativeBlocks.ContainsKey(b.Label)) { imperativeBlocks.Add(b.Label, duper.VisitBlock(b)); } } try { var start = DateTime.Now; //outcome = vcgen.VerifyImplementation(impl, prog, out errors); outcome = vcgen.VerifyImplementation(impl, /*prog,*/ out errors, out errorsModel); errModelList = errorsModel; var end = DateTime.Now; TimeSpan elapsed = end - start; Console.WriteLine(string.Format(" [{0} s] ", elapsed.TotalSeconds)); } catch (VC.VCGenException e) { Log.Out(Log.Error, "Error BP5010: {0} Encountered in implementation {1}: " + e.Message); errors = null; outcome = VC.VCGen.Outcome.Inconclusive; } catch (UnexpectedProverOutputException upo) { Log.Out(Log.Error, "Advisory: {0} SKIPPED because of internal error: unexpected prover output: {1}" + upo.Message); errors = null; outcome = VC.VCGen.Outcome.Inconclusive; } catch (Exception e) { Log.Out(Log.Error, "Unknown error somewhere in verification: "); Log.Out(Log.Error, e.ToString()); return(VerificationResult.Unknown); } switch (outcome) { case VC.VCGen.Outcome.Correct: sdoutcome = VerificationResult.Verified; break; case VC.VCGen.Outcome.Errors: sdoutcome = VerificationResult.Error; break; case VC.VCGen.Outcome.Inconclusive: sdoutcome = VerificationResult.Inconclusive; break; case VC.VCGen.Outcome.OutOfMemory: sdoutcome = VerificationResult.OutOfMemory; break; case VC.VCGen.Outcome.TimedOut: sdoutcome = VerificationResult.TimeOut; break; } Log.Out(Log.Normal, outcome.ToString()); var eqVarName = ""; if (errors != null && errors.Count() == 1) { //eqVarName = errors[0]; } Log.Out(Log.Verifier, (errors == null ? 0 : errors.Count) + " counterexamples..."); if (errors != null) { cex = new SDiffCounterexamples(); for (int i = 0; i < errors.Count; i++) { if (Options.EnumerateAllPaths) { //just remove any time for this option cex.Add(new SDiffCounterexample(errors[i], null, impl)); continue; } //reconstruct trace in terms of imperative blocks var trace = ReconstructImperativeTrace(errors[i].Trace, imperativeBlocks); if (SymEx.TraceValidator.Validate(trace)) { Log.Out(Log.Cex, "Trace " + "[" + i + "]:"); Log.Out(Log.Cex, "Validating..."); Log.Out(Log.Cex, "Trace is not complete! Printing.."); SDiff.SymEx.CexDumper.PrintTrace(trace); continue; } else { //Log.Out(Log.Cex, "Trace OK"); if (Options.DumpValidTraces) { SDiff.SymEx.CexDumper.PrintTrace(trace); } } cex.Add(new SDiffCounterexample(errors[i], trace, impl)); } } return(sdoutcome); }